mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 15:45:42 +00:00
HostDisplay: Add method to render screenshots at window size
This commit is contained in:
parent
757bef7b6d
commit
2aea58d056
|
@ -613,3 +613,40 @@ bool HostDisplay::WriteDisplayTextureToBuffer(std::vector<u32>* buffer, u32 resi
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HostDisplay::WriteScreenshotToFile(std::string filename, bool compress_on_thread /*= false*/)
|
||||
{
|
||||
const u32 width = m_window_info.surface_width;
|
||||
const u32 height = m_window_info.surface_height;
|
||||
if (width == 0 || height == 0)
|
||||
return false;
|
||||
|
||||
std::vector<u32> pixels;
|
||||
u32 pixels_stride;
|
||||
HostDisplayPixelFormat pixels_format;
|
||||
if (!RenderScreenshot(width, height, &pixels, &pixels_stride, &pixels_format))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to render %ux%u screenshot", width, height);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto fp = FileSystem::OpenManagedCFile(filename.c_str(), "wb");
|
||||
if (!fp)
|
||||
{
|
||||
Log_ErrorPrintf("Can't open file '%s': errno %d", filename.c_str(), errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
const RenderAPI api = GetRenderAPI();
|
||||
const bool flip_y = (api == RenderAPI::OpenGL || api == RenderAPI::OpenGLES);
|
||||
if (!compress_on_thread)
|
||||
{
|
||||
return CompressAndWriteTextureToFile(width, height, std::move(filename), std::move(fp), true, flip_y, width, height,
|
||||
std::move(pixels), pixels_stride, pixels_format);
|
||||
}
|
||||
|
||||
std::thread compress_thread(CompressAndWriteTextureToFile, width, height, std::move(filename), std::move(fp), true,
|
||||
flip_y, width, height, std::move(pixels), pixels_stride, pixels_format);
|
||||
compress_thread.detach();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -115,6 +115,10 @@ public:
|
|||
/// Returns false if the window was completely occluded.
|
||||
virtual bool Render() = 0;
|
||||
|
||||
/// Renders the display with postprocessing to the specified image.
|
||||
virtual bool RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
|
||||
HostDisplayPixelFormat* out_format) = 0;
|
||||
|
||||
virtual void SetVSync(bool enabled) = 0;
|
||||
|
||||
#ifdef WITH_IMGUI
|
||||
|
@ -232,6 +236,9 @@ public:
|
|||
bool WriteDisplayTextureToBuffer(std::vector<u32>* buffer, u32 resize_width = 0, u32 resize_height = 0,
|
||||
bool clear_alpha = true);
|
||||
|
||||
/// Helper function to save screenshot to PNG.
|
||||
bool WriteScreenshotToFile(std::string filename, bool compress_on_thread = false);
|
||||
|
||||
protected:
|
||||
ALWAYS_INLINE bool HasSoftwareCursor() const { return static_cast<bool>(m_cursor_texture); }
|
||||
ALWAYS_INLINE bool HasDisplayTexture() const { return (m_display_texture_handle != nullptr); }
|
||||
|
|
|
@ -709,6 +709,59 @@ bool D3D11HostDisplay::Render()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool D3D11HostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
|
||||
HostDisplayPixelFormat* out_format)
|
||||
{
|
||||
static constexpr DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
static constexpr HostDisplayPixelFormat hdformat = HostDisplayPixelFormat::RGBA8;
|
||||
|
||||
D3D11::Texture render_texture;
|
||||
if (!render_texture.Create(m_device.Get(), width, height, 1, 1, format, D3D11_BIND_RENDER_TARGET) ||
|
||||
!m_readback_staging_texture.EnsureSize(m_context.Get(), width, height, format, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr std::array<float, 4> clear_color = {};
|
||||
m_context->ClearRenderTargetView(render_texture.GetD3DRTV(), clear_color.data());
|
||||
m_context->OMSetRenderTargets(1, render_texture.GetD3DRTVArray(), nullptr);
|
||||
|
||||
if (HasDisplayTexture())
|
||||
{
|
||||
const auto [left, top, draw_width, draw_height] = CalculateDrawRect(width, height, 0);
|
||||
|
||||
if (!m_post_processing_chain.IsEmpty())
|
||||
{
|
||||
ApplyPostProcessingChain(render_texture.GetD3DRTV(), left, top, draw_width, draw_height, m_display_texture_handle,
|
||||
m_display_texture_width, m_display_texture_height, m_display_texture_view_x,
|
||||
m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
|
||||
width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderDisplay(left, top, draw_width, draw_height, m_display_texture_handle, m_display_texture_width,
|
||||
m_display_texture_height, m_display_texture_view_x, m_display_texture_view_y,
|
||||
m_display_texture_view_width, m_display_texture_view_height, m_display_linear_filtering);
|
||||
}
|
||||
}
|
||||
|
||||
m_context->OMSetRenderTargets(0, nullptr, nullptr);
|
||||
|
||||
m_readback_staging_texture.CopyFromTexture(m_context.Get(), render_texture, 0, 0, 0, 0, 0, width, height);
|
||||
|
||||
if (!m_readback_staging_texture.Map(m_context.Get(), false))
|
||||
return false;
|
||||
|
||||
const u32 stride = sizeof(u32) * width;
|
||||
out_pixels->resize(width * height);
|
||||
*out_stride = stride;
|
||||
*out_format = hdformat;
|
||||
|
||||
m_readback_staging_texture.ReadPixels<u32>(0, 0, width, height, stride, out_pixels->data());
|
||||
m_readback_staging_texture.Unmap(m_context.Get());
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D11HostDisplay::RenderImGui()
|
||||
{
|
||||
ImGui::Render();
|
||||
|
@ -726,7 +779,8 @@ void D3D11HostDisplay::RenderDisplay()
|
|||
{
|
||||
ApplyPostProcessingChain(m_swap_chain_rtv.Get(), left, top, width, height, m_display_texture_handle,
|
||||
m_display_texture_width, m_display_texture_height, m_display_texture_view_x,
|
||||
m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height);
|
||||
m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
|
||||
GetWindowWidth(), GetWindowHeight());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -971,11 +1025,12 @@ bool D3D11HostDisplay::CheckPostProcessingRenderTargets(u32 target_width, u32 ta
|
|||
void D3D11HostDisplay::ApplyPostProcessingChain(ID3D11RenderTargetView* final_target, s32 final_left, s32 final_top,
|
||||
s32 final_width, s32 final_height, void* texture_handle,
|
||||
u32 texture_width, s32 texture_height, s32 texture_view_x,
|
||||
s32 texture_view_y, s32 texture_view_width, s32 texture_view_height)
|
||||
s32 texture_view_y, s32 texture_view_width, s32 texture_view_height,
|
||||
u32 target_width, u32 target_height)
|
||||
{
|
||||
static constexpr std::array<float, 4> clear_color = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
if (!CheckPostProcessingRenderTargets(GetWindowWidth(), GetWindowHeight()))
|
||||
if (!CheckPostProcessingRenderTargets(target_width, target_height))
|
||||
{
|
||||
RenderDisplay(final_left, final_top, final_width, final_height, texture_handle, texture_width, texture_height,
|
||||
texture_view_x, texture_view_y, texture_view_width, texture_view_height, m_display_linear_filtering);
|
||||
|
|
|
@ -68,6 +68,8 @@ public:
|
|||
virtual void SetVSync(bool enabled) override;
|
||||
|
||||
virtual bool Render() override;
|
||||
virtual bool RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
|
||||
HostDisplayPixelFormat* out_format) override;
|
||||
|
||||
static AdapterAndModeList StaticGetAdapterAndModeList();
|
||||
|
||||
|
@ -107,7 +109,7 @@ protected:
|
|||
void ApplyPostProcessingChain(ID3D11RenderTargetView* final_target, s32 final_left, s32 final_top, s32 final_width,
|
||||
s32 final_height, void* texture_handle, u32 texture_width, s32 texture_height,
|
||||
s32 texture_view_x, s32 texture_view_y, s32 texture_view_width,
|
||||
s32 texture_view_height);
|
||||
s32 texture_view_height, u32 target_width, u32 target_height);
|
||||
|
||||
ComPtr<ID3D11Device> m_device;
|
||||
ComPtr<ID3D11DeviceContext> m_context;
|
||||
|
|
|
@ -749,7 +749,6 @@ bool OpenGLHostDisplay::Render()
|
|||
return false;
|
||||
}
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
@ -765,6 +764,46 @@ bool OpenGLHostDisplay::Render()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool OpenGLHostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
|
||||
HostDisplayPixelFormat* out_format)
|
||||
{
|
||||
GL::Texture texture;
|
||||
if (!texture.Create(width, height, 1, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr) || !texture.CreateFramebuffer())
|
||||
return false;
|
||||
|
||||
texture.BindFramebuffer(GL_FRAMEBUFFER);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (HasDisplayTexture())
|
||||
{
|
||||
const auto [left, top, draw_width, draw_height] = CalculateDrawRect(width, height, 0);
|
||||
|
||||
if (!m_post_processing_chain.IsEmpty())
|
||||
{
|
||||
ApplyPostProcessingChain(texture.GetGLFramebufferID(), left, height - top - draw_height, draw_width, draw_height,
|
||||
m_display_texture_handle, m_display_texture_width, m_display_texture_height,
|
||||
m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
|
||||
m_display_texture_view_height, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderDisplay(left, height - top - draw_height, draw_width, draw_height, m_display_texture_handle,
|
||||
m_display_texture_width, m_display_texture_height, m_display_texture_view_x,
|
||||
m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
|
||||
m_display_linear_filtering);
|
||||
}
|
||||
}
|
||||
|
||||
out_pixels->resize(width * height);
|
||||
*out_stride = sizeof(u32) * width;
|
||||
*out_format = HostDisplayPixelFormat::RGBA8;
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, out_pixels->data());
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLHostDisplay::RenderImGui()
|
||||
{
|
||||
ImGui::Render();
|
||||
|
@ -783,7 +822,8 @@ void OpenGLHostDisplay::RenderDisplay()
|
|||
{
|
||||
ApplyPostProcessingChain(0, left, GetWindowHeight() - top - height, width, height, m_display_texture_handle,
|
||||
m_display_texture_width, m_display_texture_height, m_display_texture_view_x,
|
||||
m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height);
|
||||
m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
|
||||
GetWindowWidth(), GetWindowHeight());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -995,11 +1035,12 @@ bool OpenGLHostDisplay::CheckPostProcessingRenderTargets(u32 target_width, u32 t
|
|||
void OpenGLHostDisplay::ApplyPostProcessingChain(GLuint final_target, s32 final_left, s32 final_top, s32 final_width,
|
||||
s32 final_height, void* texture_handle, u32 texture_width,
|
||||
s32 texture_height, s32 texture_view_x, s32 texture_view_y,
|
||||
s32 texture_view_width, s32 texture_view_height)
|
||||
s32 texture_view_width, s32 texture_view_height, u32 target_width,
|
||||
u32 target_height)
|
||||
{
|
||||
if (!CheckPostProcessingRenderTargets(GetWindowWidth(), GetWindowHeight()))
|
||||
if (!CheckPostProcessingRenderTargets(target_width, target_height))
|
||||
{
|
||||
RenderDisplay(final_left, GetWindowHeight() - final_top - final_height, final_width, final_height, texture_handle,
|
||||
RenderDisplay(final_left, target_height - final_top - final_height, final_width, final_height, texture_handle,
|
||||
texture_width, texture_height, texture_view_x, texture_view_y, texture_view_width,
|
||||
texture_view_height, m_display_linear_filtering);
|
||||
return;
|
||||
|
@ -1008,7 +1049,7 @@ void OpenGLHostDisplay::ApplyPostProcessingChain(GLuint final_target, s32 final_
|
|||
// downsample/upsample - use same viewport for remainder
|
||||
m_post_processing_input_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
RenderDisplay(final_left, GetWindowHeight() - final_top - final_height, final_width, final_height, texture_handle,
|
||||
RenderDisplay(final_left, target_height - final_top - final_height, final_width, final_height, texture_handle,
|
||||
texture_width, texture_height, texture_view_x, texture_view_y, texture_view_width, texture_view_height,
|
||||
m_display_linear_filtering);
|
||||
|
||||
|
|
|
@ -32,8 +32,10 @@ public:
|
|||
virtual bool HasRenderDevice() const override;
|
||||
virtual bool HasRenderSurface() const override;
|
||||
|
||||
virtual bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool debug_device, bool threaded_presentation) override;
|
||||
virtual bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device, bool threaded_presentation) override;
|
||||
virtual bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool debug_device,
|
||||
bool threaded_presentation) override;
|
||||
virtual bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device,
|
||||
bool threaded_presentation) override;
|
||||
virtual void DestroyRenderDevice() override;
|
||||
|
||||
virtual bool MakeRenderContextCurrent() override;
|
||||
|
@ -65,6 +67,8 @@ public:
|
|||
virtual void SetVSync(bool enabled) override;
|
||||
|
||||
virtual bool Render() override;
|
||||
virtual bool RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
|
||||
HostDisplayPixelFormat* out_format) override;
|
||||
|
||||
protected:
|
||||
const char* GetGLSLVersionString() const;
|
||||
|
@ -99,7 +103,8 @@ protected:
|
|||
bool CheckPostProcessingRenderTargets(u32 target_width, u32 target_height);
|
||||
void ApplyPostProcessingChain(GLuint final_target, s32 final_left, s32 final_top, s32 final_width, s32 final_height,
|
||||
void* texture_handle, u32 texture_width, s32 texture_height, s32 texture_view_x,
|
||||
s32 texture_view_y, s32 texture_view_width, s32 texture_view_height);
|
||||
s32 texture_view_y, s32 texture_view_width, s32 texture_view_height, u32 target_width,
|
||||
u32 target_height);
|
||||
|
||||
std::unique_ptr<GL::Context> m_gl_context;
|
||||
|
||||
|
|
|
@ -640,14 +640,107 @@ bool VulkanHostDisplay::Render()
|
|||
return true;
|
||||
}
|
||||
|
||||
void VulkanHostDisplay::BeginSwapChainRenderPass(VkFramebuffer framebuffer)
|
||||
bool VulkanHostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
|
||||
HostDisplayPixelFormat* out_format)
|
||||
{
|
||||
// in theory we could do this without a swap chain, but postprocessing assumes it for now...
|
||||
if (!m_swap_chain)
|
||||
return false;
|
||||
|
||||
const VkFormat format = m_swap_chain ? m_swap_chain->GetTextureFormat() : VK_FORMAT_R8G8B8A8_UNORM;
|
||||
switch (format)
|
||||
{
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
case VK_FORMAT_R8G8B8A8_SRGB:
|
||||
*out_format = HostDisplayPixelFormat::RGBA8;
|
||||
*out_stride = sizeof(u32) * width;
|
||||
out_pixels->resize(width * height);
|
||||
break;
|
||||
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||
*out_format = HostDisplayPixelFormat::BGRA8;
|
||||
*out_stride = sizeof(u32) * width;
|
||||
out_pixels->resize(width * height);
|
||||
break;
|
||||
|
||||
case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
|
||||
*out_format = HostDisplayPixelFormat::RGBA5551;
|
||||
*out_stride = sizeof(u16) * width;
|
||||
out_pixels->resize(((width * height) + 1) / 2);
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R5G6B5_UNORM_PACK16:
|
||||
*out_format = HostDisplayPixelFormat::RGB565;
|
||||
*out_stride = sizeof(u16) * width;
|
||||
out_pixels->resize(((width * height) + 1) / 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
Log_ErrorPrintf("Unhandled swap chain pixel format %u", static_cast<unsigned>(format));
|
||||
break;
|
||||
}
|
||||
|
||||
Vulkan::Texture tex;
|
||||
Vulkan::StagingTexture staging_tex;
|
||||
if (!tex.Create(width, height, 1, 1, format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT) ||
|
||||
!staging_tex.Create(Vulkan::StagingBuffer::Type::Readback, format, width, height))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const VkRenderPass rp =
|
||||
m_swap_chain ?
|
||||
m_swap_chain->GetClearRenderPass() :
|
||||
g_vulkan_context->GetRenderPass(format, VK_FORMAT_UNDEFINED, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR);
|
||||
if (!rp)
|
||||
return false;
|
||||
|
||||
const VkFramebuffer fb = tex.CreateFramebuffer(rp);
|
||||
if (!fb)
|
||||
return false;
|
||||
|
||||
tex.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
const auto [left, top, draw_width, draw_height] =
|
||||
CalculateDrawRect(GetWindowWidth(), GetWindowHeight(), m_display_top_margin);
|
||||
|
||||
if (!m_post_processing_chain.IsEmpty())
|
||||
{
|
||||
ApplyPostProcessingChain(fb, left, top, draw_width, draw_height, m_display_texture_handle, m_display_texture_width,
|
||||
m_display_texture_height, m_display_texture_view_x, m_display_texture_view_y,
|
||||
m_display_texture_view_width, m_display_texture_view_height, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
BeginSwapChainRenderPass(fb, width, height);
|
||||
RenderDisplay(left, top, draw_width, draw_height, m_display_texture_handle, m_display_texture_width,
|
||||
m_display_texture_height, m_display_texture_view_x, m_display_texture_view_y,
|
||||
m_display_texture_view_width, m_display_texture_view_height, m_display_linear_filtering);
|
||||
}
|
||||
|
||||
vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer());
|
||||
tex.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
staging_tex.CopyFromTexture(tex, 0, 0, 0, 0, 0, 0, width, height);
|
||||
staging_tex.ReadTexels(0, 0, width, height, out_pixels->data(), *out_stride);
|
||||
|
||||
// destroying these immediately should be safe since nothing's going to access them, and it's not part of the command
|
||||
// stream
|
||||
vkDestroyFramebuffer(g_vulkan_context->GetDevice(), fb, nullptr);
|
||||
staging_tex.Destroy(false);
|
||||
tex.Destroy(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void VulkanHostDisplay::BeginSwapChainRenderPass(VkFramebuffer framebuffer, u32 width, u32 height)
|
||||
{
|
||||
const VkClearValue clear_value = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
|
||||
const VkRenderPassBeginInfo rp = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
nullptr,
|
||||
m_swap_chain->GetClearRenderPass(),
|
||||
framebuffer,
|
||||
{{0, 0}, {m_swap_chain->GetWidth(), m_swap_chain->GetHeight()}},
|
||||
{{0, 0}, {width, height}},
|
||||
1u,
|
||||
&clear_value};
|
||||
vkCmdBeginRenderPass(g_vulkan_context->GetCurrentCommandBuffer(), &rp, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
@ -657,7 +750,8 @@ void VulkanHostDisplay::RenderDisplay()
|
|||
{
|
||||
if (!HasDisplayTexture())
|
||||
{
|
||||
BeginSwapChainRenderPass(m_swap_chain->GetCurrentFramebuffer());
|
||||
BeginSwapChainRenderPass(m_swap_chain->GetCurrentFramebuffer(), m_swap_chain->GetWidth(),
|
||||
m_swap_chain->GetHeight());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -665,13 +759,14 @@ void VulkanHostDisplay::RenderDisplay()
|
|||
|
||||
if (!m_post_processing_chain.IsEmpty())
|
||||
{
|
||||
ApplyPostProcessingChain(left, top, width, height, m_display_texture_handle, m_display_texture_width,
|
||||
m_display_texture_height, m_display_texture_view_x, m_display_texture_view_y,
|
||||
m_display_texture_view_width, m_display_texture_view_height);
|
||||
ApplyPostProcessingChain(m_swap_chain->GetCurrentFramebuffer(), left, top, width, height, m_display_texture_handle,
|
||||
m_display_texture_width, m_display_texture_height, m_display_texture_view_x,
|
||||
m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
|
||||
m_swap_chain->GetWidth(), m_swap_chain->GetHeight());
|
||||
return;
|
||||
}
|
||||
|
||||
BeginSwapChainRenderPass(m_swap_chain->GetCurrentFramebuffer());
|
||||
BeginSwapChainRenderPass(m_swap_chain->GetCurrentFramebuffer(), m_swap_chain->GetWidth(), m_swap_chain->GetHeight());
|
||||
RenderDisplay(left, top, width, height, m_display_texture_handle, m_display_texture_width, m_display_texture_height,
|
||||
m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
|
||||
m_display_texture_view_height, m_display_linear_filtering);
|
||||
|
@ -946,14 +1041,15 @@ bool VulkanHostDisplay::CheckPostProcessingRenderTargets(u32 target_width, u32 t
|
|||
return true;
|
||||
}
|
||||
|
||||
void VulkanHostDisplay::ApplyPostProcessingChain(s32 final_left, s32 final_top, s32 final_width, s32 final_height,
|
||||
void* texture_handle, u32 texture_width, s32 texture_height,
|
||||
s32 texture_view_x, s32 texture_view_y, s32 texture_view_width,
|
||||
s32 texture_view_height)
|
||||
void VulkanHostDisplay::ApplyPostProcessingChain(VkFramebuffer target_fb, s32 final_left, s32 final_top,
|
||||
s32 final_width, s32 final_height, void* texture_handle,
|
||||
u32 texture_width, s32 texture_height, s32 texture_view_x,
|
||||
s32 texture_view_y, s32 texture_view_width, s32 texture_view_height,
|
||||
u32 target_width, u32 target_height)
|
||||
{
|
||||
if (!CheckPostProcessingRenderTargets(m_swap_chain->GetWidth(), m_swap_chain->GetHeight()))
|
||||
if (!CheckPostProcessingRenderTargets(target_width, target_height))
|
||||
{
|
||||
BeginSwapChainRenderPass(m_swap_chain->GetCurrentFramebuffer());
|
||||
BeginSwapChainRenderPass(target_fb, target_width, target_height);
|
||||
RenderDisplay(final_left, final_top, final_width, final_height, texture_handle, texture_width, texture_height,
|
||||
texture_view_x, texture_view_y, texture_view_width, texture_view_height, m_display_linear_filtering);
|
||||
return;
|
||||
|
@ -962,7 +1058,7 @@ void VulkanHostDisplay::ApplyPostProcessingChain(s32 final_left, s32 final_top,
|
|||
// downsample/upsample - use same viewport for remainder
|
||||
VkCommandBuffer cmdbuffer = g_vulkan_context->GetCurrentCommandBuffer();
|
||||
m_post_processing_input_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
BeginSwapChainRenderPass(m_post_processing_input_framebuffer);
|
||||
BeginSwapChainRenderPass(m_post_processing_input_framebuffer, target_width, target_height);
|
||||
RenderDisplay(final_left, final_top, final_width, final_height, texture_handle, texture_width, texture_height,
|
||||
texture_view_x, texture_view_y, texture_view_width, texture_view_height, m_display_linear_filtering);
|
||||
vkCmdEndRenderPass(cmdbuffer);
|
||||
|
@ -983,11 +1079,11 @@ void VulkanHostDisplay::ApplyPostProcessingChain(s32 final_left, s32 final_top,
|
|||
if (i != final_stage)
|
||||
{
|
||||
pps.output_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
BeginSwapChainRenderPass(pps.output_framebuffer);
|
||||
BeginSwapChainRenderPass(pps.output_framebuffer, target_width, target_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
BeginSwapChainRenderPass(m_swap_chain->GetCurrentFramebuffer());
|
||||
BeginSwapChainRenderPass(target_fb, target_width, target_height);
|
||||
}
|
||||
|
||||
const bool use_push_constants = m_post_processing_chain.GetShaderStage(i).UsePushConstants();
|
||||
|
|
|
@ -64,6 +64,8 @@ public:
|
|||
virtual void SetVSync(bool enabled) override;
|
||||
|
||||
virtual bool Render() override;
|
||||
virtual bool RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
|
||||
HostDisplayPixelFormat* out_format) override;
|
||||
|
||||
static AdapterAndModeList StaticGetAdapterAndModeList(const WindowInfo* wi);
|
||||
|
||||
|
@ -89,9 +91,10 @@ protected:
|
|||
};
|
||||
|
||||
bool CheckPostProcessingRenderTargets(u32 target_width, u32 target_height);
|
||||
void ApplyPostProcessingChain(s32 final_left, s32 final_top, s32 final_width, s32 final_height, void* texture_handle,
|
||||
u32 texture_width, s32 texture_height, s32 texture_view_x, s32 texture_view_y,
|
||||
s32 texture_view_width, s32 texture_view_height);
|
||||
void ApplyPostProcessingChain(VkFramebuffer target_fb, s32 final_left, s32 final_top, s32 final_width,
|
||||
s32 final_height, void* texture_handle, u32 texture_width, s32 texture_height,
|
||||
s32 texture_view_x, s32 texture_view_y, s32 texture_view_width, s32 texture_view_height,
|
||||
u32 target_width, u32 target_height);
|
||||
|
||||
// Can be overridden by frontends.
|
||||
virtual VkRenderPass GetRenderPassForDisplay() const;
|
||||
|
@ -103,7 +106,7 @@ protected:
|
|||
virtual void DestroyImGuiContext() override;
|
||||
virtual bool UpdateImGuiFontTexture() override;
|
||||
|
||||
void BeginSwapChainRenderPass(VkFramebuffer framebuffer);
|
||||
void BeginSwapChainRenderPass(VkFramebuffer framebuffer, u32 width, u32 height);
|
||||
void RenderDisplay();
|
||||
void RenderImGui();
|
||||
void RenderSoftwareCursor();
|
||||
|
|
Loading…
Reference in a new issue