GPU/HW: Expose depth buffer to postprocessing
This commit is contained in:
parent
ac1fcb4c93
commit
b2ebff1f67
129
src/core/gpu.cpp
129
src/core/gpu.cpp
|
@ -48,6 +48,9 @@ static void JoinScreenshotThreads();
|
||||||
static std::deque<std::thread> s_screenshot_threads;
|
static std::deque<std::thread> s_screenshot_threads;
|
||||||
static std::mutex s_screenshot_threads_mutex;
|
static std::mutex s_screenshot_threads_mutex;
|
||||||
|
|
||||||
|
// Format used for screen-resolution depth buffer copy. This should align with the HW format.
|
||||||
|
static constexpr GPUTexture::Format DISPLAY_DEPTH_FORMAT = GPUTexture::Format::R16;
|
||||||
|
|
||||||
GPU::GPU()
|
GPU::GPU()
|
||||||
{
|
{
|
||||||
ResetStatistics();
|
ResetStatistics();
|
||||||
|
@ -1624,42 +1627,62 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
|
||||||
|
|
||||||
if (display)
|
if (display)
|
||||||
{
|
{
|
||||||
plconfig.layout = GPUPipeline::Layout::SingleTextureAndPushConstants;
|
m_display_pipeline.reset();
|
||||||
plconfig.SetTargetFormats(g_gpu_device->HasSurface() ? g_gpu_device->GetWindowFormat() : GPUTexture::Format::RGBA8);
|
m_display_depth_pipeline.reset();
|
||||||
|
|
||||||
std::string vs = shadergen.GenerateDisplayVertexShader();
|
std::unique_ptr<GPUShader> vso =
|
||||||
std::string fs;
|
g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GenerateDisplayVertexShader());
|
||||||
switch (g_settings.display_scaling)
|
if (!vso)
|
||||||
{
|
|
||||||
case DisplayScalingMode::BilinearSharp:
|
|
||||||
fs = shadergen.GenerateDisplaySharpBilinearFragmentShader();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DisplayScalingMode::BilinearSmooth:
|
|
||||||
fs = shadergen.GenerateDisplayFragmentShader(true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DisplayScalingMode::Nearest:
|
|
||||||
case DisplayScalingMode::NearestInteger:
|
|
||||||
default:
|
|
||||||
fs = shadergen.GenerateDisplayFragmentShader(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<GPUShader> vso = g_gpu_device->CreateShader(GPUShaderStage::Vertex, vs);
|
|
||||||
std::unique_ptr<GPUShader> fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, fs);
|
|
||||||
if (!vso || !fso)
|
|
||||||
return false;
|
return false;
|
||||||
GL_OBJECT_NAME(vso, "Display Vertex Shader");
|
GL_OBJECT_NAME(vso, "Display Vertex Shader");
|
||||||
GL_OBJECT_NAME_FMT(fso, "Display Fragment Shader [{}]",
|
|
||||||
Settings::GetDisplayScalingName(g_settings.display_scaling));
|
|
||||||
|
|
||||||
plconfig.vertex_shader = vso.get();
|
for (u32 depth = 0; depth < 2; depth++)
|
||||||
plconfig.fragment_shader = fso.get();
|
{
|
||||||
if (!(m_display_pipeline = g_gpu_device->CreatePipeline(plconfig)))
|
plconfig.layout =
|
||||||
return false;
|
depth ? GPUPipeline::Layout::MultiTextureAndPushConstants : GPUPipeline::Layout::SingleTextureAndPushConstants;
|
||||||
GL_OBJECT_NAME_FMT(m_display_pipeline, "Display Pipeline [{}]",
|
plconfig.SetTargetFormats(g_gpu_device->HasSurface() ? g_gpu_device->GetWindowFormat() :
|
||||||
Settings::GetDisplayScalingName(g_settings.display_scaling));
|
GPUTexture::Format::RGBA8);
|
||||||
|
if (depth)
|
||||||
|
plconfig.color_formats[1] = DISPLAY_DEPTH_FORMAT;
|
||||||
|
|
||||||
|
std::string fs;
|
||||||
|
switch (g_settings.display_scaling)
|
||||||
|
{
|
||||||
|
case DisplayScalingMode::BilinearSharp:
|
||||||
|
fs = shadergen.GenerateDisplaySharpBilinearFragmentShader(ConvertToBoolUnchecked(depth));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DisplayScalingMode::BilinearSmooth:
|
||||||
|
fs = shadergen.GenerateDisplayFragmentShader(ConvertToBoolUnchecked(depth), true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DisplayScalingMode::Nearest:
|
||||||
|
case DisplayScalingMode::NearestInteger:
|
||||||
|
default:
|
||||||
|
fs = shadergen.GenerateDisplayFragmentShader(ConvertToBoolUnchecked(depth), false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GPUShader> fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, fs);
|
||||||
|
if (!fso)
|
||||||
|
return false;
|
||||||
|
GL_OBJECT_NAME_FMT(fso, "Display Fragment Shader [{}]{}",
|
||||||
|
Settings::GetDisplayScalingName(g_settings.display_scaling), depth ? "[Depth]" : "");
|
||||||
|
|
||||||
|
plconfig.vertex_shader = vso.get();
|
||||||
|
plconfig.fragment_shader = fso.get();
|
||||||
|
|
||||||
|
std::unique_ptr<GPUPipeline> pipeline = g_gpu_device->CreatePipeline(plconfig);
|
||||||
|
if (!pipeline)
|
||||||
|
return false;
|
||||||
|
GL_OBJECT_NAME_FMT(pipeline, "Display Pipeline [{}]{}",
|
||||||
|
Settings::GetDisplayScalingName(g_settings.display_scaling), depth ? "[Depth]" : "");
|
||||||
|
|
||||||
|
if (depth)
|
||||||
|
m_display_depth_pipeline = std::move(pipeline);
|
||||||
|
else
|
||||||
|
m_display_pipeline = std::move(pipeline);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deinterlace)
|
if (deinterlace)
|
||||||
|
@ -1796,10 +1819,12 @@ void GPU::ClearDisplayTexture()
|
||||||
m_display_texture_view_height = 0;
|
m_display_texture_view_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::SetDisplayTexture(GPUTexture* texture, s32 view_x, s32 view_y, s32 view_width, s32 view_height)
|
void GPU::SetDisplayTexture(GPUTexture* texture, GPUTexture* depth_buffer, s32 view_x, s32 view_y, s32 view_width,
|
||||||
|
s32 view_height)
|
||||||
{
|
{
|
||||||
DebugAssert(texture);
|
DebugAssert(texture);
|
||||||
m_display_texture = texture;
|
m_display_texture = texture;
|
||||||
|
m_display_depth_buffer = depth_buffer;
|
||||||
m_display_texture_view_x = view_x;
|
m_display_texture_view_x = view_x;
|
||||||
m_display_texture_view_y = view_y;
|
m_display_texture_view_y = view_y;
|
||||||
m_display_texture_view_width = view_width;
|
m_display_texture_view_width = view_width;
|
||||||
|
@ -1880,16 +1905,28 @@ bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_r
|
||||||
const GPUTexture::Format hdformat = target ? target->GetFormat() : g_gpu_device->GetWindowFormat();
|
const GPUTexture::Format hdformat = target ? target->GetFormat() : g_gpu_device->GetWindowFormat();
|
||||||
const u32 target_width = target ? target->GetWidth() : g_gpu_device->GetWindowWidth();
|
const u32 target_width = target ? target->GetWidth() : g_gpu_device->GetWindowWidth();
|
||||||
const u32 target_height = target ? target->GetHeight() : g_gpu_device->GetWindowHeight();
|
const u32 target_height = target ? target->GetHeight() : g_gpu_device->GetWindowHeight();
|
||||||
|
const bool postfx_depth = (PostProcessing::NeedsDepthBuffer() && m_display_depth_buffer);
|
||||||
const bool really_postfx =
|
const bool really_postfx =
|
||||||
(postfx && HasDisplayTexture() && PostProcessing::IsActive() && !g_gpu_device->GetWindowInfo().IsSurfaceless() &&
|
(postfx && HasDisplayTexture() && PostProcessing::IsActive() && !g_gpu_device->GetWindowInfo().IsSurfaceless() &&
|
||||||
hdformat != GPUTexture::Format::Unknown && target_width > 0 && target_height > 0 &&
|
hdformat != GPUTexture::Format::Unknown && target_width > 0 && target_height > 0 &&
|
||||||
PostProcessing::CheckTargets(hdformat, GPUTexture::Format::Unknown, target_width, target_height));
|
PostProcessing::CheckTargets(hdformat, postfx_depth ? DISPLAY_DEPTH_FORMAT : GPUTexture::Format::Unknown,
|
||||||
|
target_width, target_height));
|
||||||
const Common::Rectangle<s32> real_draw_rect =
|
const Common::Rectangle<s32> real_draw_rect =
|
||||||
g_gpu_device->UsesLowerLeftOrigin() ? GPUDevice::FlipToLowerLeft(draw_rect, target_height) : draw_rect;
|
g_gpu_device->UsesLowerLeftOrigin() ? GPUDevice::FlipToLowerLeft(draw_rect, target_height) : draw_rect;
|
||||||
if (really_postfx)
|
if (really_postfx)
|
||||||
{
|
{
|
||||||
g_gpu_device->ClearRenderTarget(PostProcessing::GetInputTexture(), 0);
|
if (postfx_depth)
|
||||||
g_gpu_device->SetRenderTarget(PostProcessing::GetInputTexture());
|
{
|
||||||
|
GPUTexture* rts[] = {PostProcessing::GetInputTexture(), PostProcessing::GetInputDepthTexture()};
|
||||||
|
for (GPUTexture* rt : rts)
|
||||||
|
g_gpu_device->ClearRenderTarget(rt, 0);
|
||||||
|
g_gpu_device->SetRenderTargets(rts, static_cast<u32>(std::size(rts)), nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_gpu_device->ClearRenderTarget(PostProcessing::GetInputTexture(), 0);
|
||||||
|
g_gpu_device->SetRenderTarget(PostProcessing::GetInputTexture());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1902,9 +1939,17 @@ bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_r
|
||||||
if (!HasDisplayTexture())
|
if (!HasDisplayTexture())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
g_gpu_device->SetPipeline(m_display_pipeline.get());
|
|
||||||
g_gpu_device->SetTextureSampler(
|
g_gpu_device->SetTextureSampler(
|
||||||
0, m_display_texture, texture_filter_linear ? g_gpu_device->GetLinearSampler() : g_gpu_device->GetNearestSampler());
|
0, m_display_texture, texture_filter_linear ? g_gpu_device->GetLinearSampler() : g_gpu_device->GetNearestSampler());
|
||||||
|
if (really_postfx && m_display_depth_buffer)
|
||||||
|
{
|
||||||
|
g_gpu_device->SetPipeline(m_display_depth_pipeline.get());
|
||||||
|
g_gpu_device->SetTextureSampler(1, m_display_depth_buffer, g_gpu_device->GetLinearSampler());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_gpu_device->SetPipeline(m_display_pipeline.get());
|
||||||
|
}
|
||||||
|
|
||||||
// For bilinear, clamp to 0.5/SIZE-0.5 to avoid bleeding from the adjacent texels in VRAM. This is because
|
// For bilinear, clamp to 0.5/SIZE-0.5 to avoid bleeding from the adjacent texels in VRAM. This is because
|
||||||
// 1.0 in UV space is not the bottom-right texel, but a mix of the bottom-right and wrapped/next texel.
|
// 1.0 in UV space is not the bottom-right texel, but a mix of the bottom-right and wrapped/next texel.
|
||||||
|
@ -1969,7 +2014,7 @@ bool GPU::Deinterlace(u32 field, u32 line_skip)
|
||||||
if (!DeinterlaceExtractField(0, src, x, y, width, height, line_skip)) [[unlikely]]
|
if (!DeinterlaceExtractField(0, src, x, y, width, height, line_skip)) [[unlikely]]
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SetDisplayTexture(m_deinterlace_buffers[0].get(), 0, 0, width, height);
|
SetDisplayTexture(m_deinterlace_buffers[0].get(), m_display_depth_buffer, 0, 0, width, height);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1995,7 +2040,7 @@ bool GPU::Deinterlace(u32 field, u32 line_skip)
|
||||||
g_gpu_device->Draw(3, 0);
|
g_gpu_device->Draw(3, 0);
|
||||||
|
|
||||||
m_deinterlace_texture->MakeReadyForSampling();
|
m_deinterlace_texture->MakeReadyForSampling();
|
||||||
SetDisplayTexture(m_deinterlace_texture.get(), 0, 0, width, full_height);
|
SetDisplayTexture(m_deinterlace_texture.get(), m_display_depth_buffer, 0, 0, width, full_height);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2027,7 +2072,7 @@ bool GPU::Deinterlace(u32 field, u32 line_skip)
|
||||||
g_gpu_device->Draw(3, 0);
|
g_gpu_device->Draw(3, 0);
|
||||||
|
|
||||||
m_deinterlace_texture->MakeReadyForSampling();
|
m_deinterlace_texture->MakeReadyForSampling();
|
||||||
SetDisplayTexture(m_deinterlace_texture.get(), 0, 0, width, height);
|
SetDisplayTexture(m_deinterlace_texture.get(), m_display_depth_buffer, 0, 0, width, height);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2062,7 +2107,7 @@ bool GPU::Deinterlace(u32 field, u32 line_skip)
|
||||||
g_gpu_device->Draw(3, 0);
|
g_gpu_device->Draw(3, 0);
|
||||||
|
|
||||||
m_deinterlace_texture->MakeReadyForSampling();
|
m_deinterlace_texture->MakeReadyForSampling();
|
||||||
SetDisplayTexture(m_deinterlace_texture.get(), 0, 0, width, full_height);
|
SetDisplayTexture(m_deinterlace_texture.get(), m_display_depth_buffer, 0, 0, width, full_height);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2165,7 +2210,7 @@ bool GPU::ApplyChromaSmoothing()
|
||||||
g_gpu_device->Draw(3, 0);
|
g_gpu_device->Draw(3, 0);
|
||||||
|
|
||||||
m_chroma_smoothing_texture->MakeReadyForSampling();
|
m_chroma_smoothing_texture->MakeReadyForSampling();
|
||||||
SetDisplayTexture(m_chroma_smoothing_texture.get(), 0, 0, width, height);
|
SetDisplayTexture(m_chroma_smoothing_texture.get(), m_display_depth_buffer, 0, 0, width, height);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -569,7 +569,8 @@ protected:
|
||||||
u32 m_fifo_size = 128;
|
u32 m_fifo_size = 128;
|
||||||
|
|
||||||
void ClearDisplayTexture();
|
void ClearDisplayTexture();
|
||||||
void SetDisplayTexture(GPUTexture* texture, s32 view_x, s32 view_y, s32 view_width, s32 view_height);
|
void SetDisplayTexture(GPUTexture* texture, GPUTexture* depth_buffer, s32 view_x, s32 view_y, s32 view_width,
|
||||||
|
s32 view_height);
|
||||||
void SetDisplayParameters(s32 display_width, s32 display_height, s32 active_left, s32 active_top, s32 active_width,
|
void SetDisplayParameters(s32 display_width, s32 display_height, s32 active_left, s32 active_top, s32 active_width,
|
||||||
s32 active_height, float display_aspect_ratio);
|
s32 active_height, float display_aspect_ratio);
|
||||||
|
|
||||||
|
@ -603,7 +604,9 @@ protected:
|
||||||
std::unique_ptr<GPUTexture> m_chroma_smoothing_texture;
|
std::unique_ptr<GPUTexture> m_chroma_smoothing_texture;
|
||||||
|
|
||||||
std::unique_ptr<GPUPipeline> m_display_pipeline;
|
std::unique_ptr<GPUPipeline> m_display_pipeline;
|
||||||
|
std::unique_ptr<GPUPipeline> m_display_depth_pipeline;
|
||||||
GPUTexture* m_display_texture = nullptr;
|
GPUTexture* m_display_texture = nullptr;
|
||||||
|
GPUTexture* m_display_depth_buffer = nullptr;
|
||||||
s32 m_display_texture_view_x = 0;
|
s32 m_display_texture_view_x = 0;
|
||||||
s32 m_display_texture_view_y = 0;
|
s32 m_display_texture_view_y = 0;
|
||||||
s32 m_display_texture_view_width = 0;
|
s32 m_display_texture_view_width = 0;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
#include "util/imgui_manager.h"
|
#include "util/imgui_manager.h"
|
||||||
|
#include "util/postprocessing.h"
|
||||||
#include "util/state_wrapper.h"
|
#include "util/state_wrapper.h"
|
||||||
|
|
||||||
#include "common/align.h"
|
#include "common/align.h"
|
||||||
|
@ -32,6 +33,7 @@ Log_SetChannel(GPU_HW);
|
||||||
|
|
||||||
static constexpr GPUTexture::Format VRAM_RT_FORMAT = GPUTexture::Format::RGBA8;
|
static constexpr GPUTexture::Format VRAM_RT_FORMAT = GPUTexture::Format::RGBA8;
|
||||||
static constexpr GPUTexture::Format VRAM_DS_FORMAT = GPUTexture::Format::D16;
|
static constexpr GPUTexture::Format VRAM_DS_FORMAT = GPUTexture::Format::D16;
|
||||||
|
static constexpr GPUTexture::Format VRAM_DS_EXTRACT_FORMAT = GPUTexture::Format::R16;
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
static u32 s_draw_number = 0;
|
static u32 s_draw_number = 0;
|
||||||
|
@ -398,6 +400,7 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
||||||
{
|
{
|
||||||
m_pgxp_depth_buffer = g_settings.UsingPGXPDepthBuffer();
|
m_pgxp_depth_buffer = g_settings.UsingPGXPDepthBuffer();
|
||||||
m_batch.use_depth_buffer = false;
|
m_batch.use_depth_buffer = false;
|
||||||
|
m_depth_was_copied = false;
|
||||||
|
|
||||||
// might be null when resizing
|
// might be null when resizing
|
||||||
if (m_vram_texture)
|
if (m_vram_texture)
|
||||||
|
@ -645,8 +648,10 @@ bool GPU_HW::CreateBuffers()
|
||||||
if (!(m_vram_texture = g_gpu_device->FetchTexture(texture_width, texture_height, 1, 1, samples,
|
if (!(m_vram_texture = g_gpu_device->FetchTexture(texture_width, texture_height, 1, 1, samples,
|
||||||
GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)) ||
|
GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)) ||
|
||||||
(needs_depth_buffer &&
|
(needs_depth_buffer &&
|
||||||
!(m_vram_depth_texture = g_gpu_device->FetchTexture(texture_width, texture_height, 1, 1, samples,
|
(!(m_vram_depth_texture = g_gpu_device->FetchTexture(texture_width, texture_height, 1, 1, samples,
|
||||||
GPUTexture::Type::DepthStencil, VRAM_DS_FORMAT))) ||
|
GPUTexture::Type::DepthStencil, VRAM_DS_FORMAT)) ||
|
||||||
|
!(m_vram_depth_copy_texture = g_gpu_device->FetchTexture(
|
||||||
|
texture_width, texture_height, 1, 1, samples, GPUTexture::Type::RenderTarget, VRAM_DS_EXTRACT_FORMAT)))) ||
|
||||||
!(m_vram_read_texture =
|
!(m_vram_read_texture =
|
||||||
g_gpu_device->FetchTexture(texture_width, texture_height, 1, 1, 1, read_texture_type, VRAM_RT_FORMAT)) ||
|
g_gpu_device->FetchTexture(texture_width, texture_height, 1, 1, 1, read_texture_type, VRAM_RT_FORMAT)) ||
|
||||||
!(m_vram_readback_texture = g_gpu_device->FetchTexture(VRAM_WIDTH / 2, VRAM_HEIGHT, 1, 1, 1,
|
!(m_vram_readback_texture = g_gpu_device->FetchTexture(VRAM_WIDTH / 2, VRAM_HEIGHT, 1, 1, 1,
|
||||||
|
@ -730,8 +735,10 @@ void GPU_HW::DestroyBuffers()
|
||||||
m_vram_upload_buffer.reset();
|
m_vram_upload_buffer.reset();
|
||||||
m_vram_readback_download_texture.reset();
|
m_vram_readback_download_texture.reset();
|
||||||
g_gpu_device->RecycleTexture(std::move(m_downsample_texture));
|
g_gpu_device->RecycleTexture(std::move(m_downsample_texture));
|
||||||
|
g_gpu_device->RecycleTexture(std::move(m_vram_extract_depth_texture));
|
||||||
g_gpu_device->RecycleTexture(std::move(m_vram_extract_texture));
|
g_gpu_device->RecycleTexture(std::move(m_vram_extract_texture));
|
||||||
g_gpu_device->RecycleTexture(std::move(m_vram_read_texture));
|
g_gpu_device->RecycleTexture(std::move(m_vram_read_texture));
|
||||||
|
g_gpu_device->RecycleTexture(std::move(m_vram_depth_copy_texture));
|
||||||
g_gpu_device->RecycleTexture(std::move(m_vram_depth_texture));
|
g_gpu_device->RecycleTexture(std::move(m_vram_depth_texture));
|
||||||
g_gpu_device->RecycleTexture(std::move(m_vram_texture));
|
g_gpu_device->RecycleTexture(std::move(m_vram_texture));
|
||||||
g_gpu_device->RecycleTexture(std::move(m_vram_readback_texture));
|
g_gpu_device->RecycleTexture(std::move(m_vram_readback_texture));
|
||||||
|
@ -1167,22 +1174,49 @@ bool GPU_HW::CompilePipelines()
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
{
|
{
|
||||||
for (u8 depth_24 = 0; depth_24 < 2; depth_24++)
|
for (u8 shader = 0; shader < 3; shader++)
|
||||||
{
|
{
|
||||||
|
// 24-bit doesn't give you a depth buffer.
|
||||||
|
const bool color_24bit = (shader == 1);
|
||||||
|
const bool depth_extract = (shader == 2);
|
||||||
|
if (depth_extract && !m_pgxp_depth_buffer)
|
||||||
|
continue;
|
||||||
|
|
||||||
std::unique_ptr<GPUShader> fs = g_gpu_device->CreateShader(
|
std::unique_ptr<GPUShader> fs = g_gpu_device->CreateShader(
|
||||||
GPUShaderStage::Fragment, shadergen.GenerateVRAMExtractFragmentShader(ConvertToBoolUnchecked(depth_24)));
|
GPUShaderStage::Fragment, shadergen.GenerateVRAMExtractFragmentShader(color_24bit, depth_extract));
|
||||||
if (!fs)
|
if (!fs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
plconfig.fragment_shader = fs.get();
|
plconfig.fragment_shader = fs.get();
|
||||||
|
|
||||||
if (!(m_vram_extract_pipeline[depth_24] = g_gpu_device->CreatePipeline(plconfig)))
|
plconfig.layout = depth_extract ? GPUPipeline::Layout::MultiTextureAndPushConstants :
|
||||||
|
GPUPipeline::Layout::SingleTextureAndPushConstants;
|
||||||
|
plconfig.color_formats[1] = depth_extract ? VRAM_DS_EXTRACT_FORMAT : GPUTexture::Format::Unknown;
|
||||||
|
|
||||||
|
if (!(m_vram_extract_pipeline[shader] = g_gpu_device->CreatePipeline(plconfig)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
progress.Increment();
|
progress.Increment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plconfig.layout = GPUPipeline::Layout::SingleTextureAndPushConstants;
|
||||||
|
|
||||||
|
if (m_pgxp_depth_buffer)
|
||||||
|
{
|
||||||
|
std::unique_ptr<GPUShader> fs =
|
||||||
|
g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GenerateCopyFragmentShader());
|
||||||
|
if (!fs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
plconfig.fragment_shader = fs.get();
|
||||||
|
plconfig.SetTargetFormats(VRAM_DS_EXTRACT_FORMAT);
|
||||||
|
if (!(m_copy_depth_pipeline = g_gpu_device->CreatePipeline(plconfig)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
plconfig.SetTargetFormats(VRAM_RT_FORMAT);
|
||||||
|
|
||||||
if (m_downsample_mode == GPUDownsampleMode::Adaptive)
|
if (m_downsample_mode == GPUDownsampleMode::Adaptive)
|
||||||
{
|
{
|
||||||
std::unique_ptr<GPUShader> vs =
|
std::unique_ptr<GPUShader> vs =
|
||||||
|
@ -1294,6 +1328,8 @@ void GPU_HW::DestroyPipelines()
|
||||||
destroy(m_downsample_blur_pass_pipeline);
|
destroy(m_downsample_blur_pass_pipeline);
|
||||||
destroy(m_downsample_composite_pass_pipeline);
|
destroy(m_downsample_composite_pass_pipeline);
|
||||||
m_downsample_composite_sampler.reset();
|
m_downsample_composite_sampler.reset();
|
||||||
|
|
||||||
|
m_copy_depth_pipeline.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
GPU_HW::BatchRenderMode GPU_HW::BatchConfig::GetRenderMode() const
|
GPU_HW::BatchRenderMode GPU_HW::BatchConfig::GetRenderMode() const
|
||||||
|
@ -1390,10 +1426,40 @@ void GPU_HW::UpdateDepthBufferFromMaskBit()
|
||||||
SetScissor();
|
SetScissor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPU_HW::CopyAndClearDepthBuffer()
|
||||||
|
{
|
||||||
|
if (!m_depth_was_copied)
|
||||||
|
{
|
||||||
|
// Take a copy of the current depth buffer so it can be used when the previous frame/buffer gets scanned out.
|
||||||
|
// Don't bother when we're not postprocessing, it'd just be a wasted copy.
|
||||||
|
if (PostProcessing::NeedsDepthBuffer())
|
||||||
|
{
|
||||||
|
// TODO: Shrink this to only the active area.
|
||||||
|
GL_SCOPE("Copy Depth Buffer");
|
||||||
|
|
||||||
|
m_vram_texture->MakeReadyForSampling();
|
||||||
|
g_gpu_device->InvalidateRenderTarget(m_vram_depth_copy_texture.get());
|
||||||
|
g_gpu_device->SetRenderTarget(m_vram_depth_copy_texture.get());
|
||||||
|
g_gpu_device->SetViewportAndScissor(0, 0, m_vram_depth_texture->GetWidth(), m_vram_depth_texture->GetHeight());
|
||||||
|
g_gpu_device->SetTextureSampler(0, m_vram_depth_texture.get(), g_gpu_device->GetNearestSampler());
|
||||||
|
|
||||||
|
const float uniforms[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||||
|
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
|
||||||
|
g_gpu_device->SetPipeline(m_copy_depth_pipeline.get());
|
||||||
|
g_gpu_device->Draw(3, 0);
|
||||||
|
RestoreDeviceContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_depth_was_copied = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearDepthBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
void GPU_HW::ClearDepthBuffer()
|
void GPU_HW::ClearDepthBuffer()
|
||||||
{
|
{
|
||||||
|
GL_SCOPE("GPU_HW::ClearDepthBuffer()");
|
||||||
DebugAssert(m_pgxp_depth_buffer);
|
DebugAssert(m_pgxp_depth_buffer);
|
||||||
|
|
||||||
g_gpu_device->ClearDepth(m_vram_depth_texture.get(), 1.0f);
|
g_gpu_device->ClearDepth(m_vram_depth_texture.get(), 1.0f);
|
||||||
m_last_depth_z = 1.0f;
|
m_last_depth_z = 1.0f;
|
||||||
}
|
}
|
||||||
|
@ -1753,13 +1819,9 @@ void GPU_HW::CheckForDepthClear(const BatchVertex* vertices, u32 num_vertices)
|
||||||
|
|
||||||
if ((average_z - m_last_depth_z) >= g_settings.gpu_pgxp_depth_clear_threshold)
|
if ((average_z - m_last_depth_z) >= g_settings.gpu_pgxp_depth_clear_threshold)
|
||||||
{
|
{
|
||||||
if (m_batch_index_count > 0)
|
FlushRender();
|
||||||
{
|
CopyAndClearDepthBuffer();
|
||||||
FlushRender();
|
EnsureVertexBufferSpaceForCurrentCommand();
|
||||||
EnsureVertexBufferSpaceForCurrentCommand();
|
|
||||||
}
|
|
||||||
|
|
||||||
ClearDepthBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_last_depth_z = average_z;
|
m_last_depth_z = average_z;
|
||||||
|
@ -3064,7 +3126,11 @@ void GPU_HW::DispatchRenderCommand()
|
||||||
SetScissor();
|
SetScissor();
|
||||||
|
|
||||||
if (m_pgxp_depth_buffer && m_last_depth_z < 1.0f)
|
if (m_pgxp_depth_buffer && m_last_depth_z < 1.0f)
|
||||||
ClearDepthBuffer();
|
{
|
||||||
|
FlushRender();
|
||||||
|
CopyAndClearDepthBuffer();
|
||||||
|
EnsureVertexBufferSpaceForCurrentCommand();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_sw_renderer)
|
if (m_sw_renderer)
|
||||||
{
|
{
|
||||||
|
@ -3139,12 +3205,12 @@ void GPU_HW::UpdateDisplay()
|
||||||
if (IsUsingMultisampling())
|
if (IsUsingMultisampling())
|
||||||
{
|
{
|
||||||
UpdateVRAMReadTexture(true, true);
|
UpdateVRAMReadTexture(true, true);
|
||||||
SetDisplayTexture(m_vram_read_texture.get(), 0, 0, m_vram_read_texture->GetWidth(),
|
SetDisplayTexture(m_vram_read_texture.get(), nullptr, 0, 0, m_vram_read_texture->GetWidth(),
|
||||||
m_vram_read_texture->GetHeight());
|
m_vram_read_texture->GetHeight());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetDisplayTexture(m_vram_texture.get(), 0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight());
|
SetDisplayTexture(m_vram_texture.get(), nullptr, 0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
|
@ -3168,6 +3234,12 @@ void GPU_HW::UpdateDisplay()
|
||||||
const u32 line_skip = m_GPUSTAT.vertical_resolution;
|
const u32 line_skip = m_GPUSTAT.vertical_resolution;
|
||||||
bool drew_anything = false;
|
bool drew_anything = false;
|
||||||
|
|
||||||
|
// Don't bother grabbing depth if postfx doesn't need it.
|
||||||
|
GPUTexture* depth_source =
|
||||||
|
(!m_GPUSTAT.display_area_color_depth_24 && m_pgxp_depth_buffer && PostProcessing::NeedsDepthBuffer()) ?
|
||||||
|
(m_depth_was_copied ? m_vram_depth_copy_texture.get() : m_vram_depth_texture.get()) :
|
||||||
|
nullptr;
|
||||||
|
|
||||||
if (IsDisplayDisabled())
|
if (IsDisplayDisabled())
|
||||||
{
|
{
|
||||||
ClearDisplayTexture();
|
ClearDisplayTexture();
|
||||||
|
@ -3177,8 +3249,8 @@ void GPU_HW::UpdateDisplay()
|
||||||
(scaled_vram_offset_x + scaled_display_width) <= m_vram_texture->GetWidth() &&
|
(scaled_vram_offset_x + scaled_display_width) <= m_vram_texture->GetWidth() &&
|
||||||
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture->GetHeight())
|
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture->GetHeight())
|
||||||
{
|
{
|
||||||
SetDisplayTexture(m_vram_texture.get(), scaled_vram_offset_x, scaled_vram_offset_y, scaled_display_width,
|
SetDisplayTexture(m_vram_texture.get(), depth_source, scaled_vram_offset_x, scaled_vram_offset_y,
|
||||||
read_height);
|
scaled_display_width, read_height);
|
||||||
|
|
||||||
// Fast path if no copies are needed.
|
// Fast path if no copies are needed.
|
||||||
if (interlaced)
|
if (interlaced)
|
||||||
|
@ -3198,21 +3270,45 @@ void GPU_HW::UpdateDisplay()
|
||||||
m_vram_extract_texture->GetHeight() != read_height)
|
m_vram_extract_texture->GetHeight() != read_height)
|
||||||
{
|
{
|
||||||
if (!g_gpu_device->ResizeTexture(&m_vram_extract_texture, scaled_display_width, read_height,
|
if (!g_gpu_device->ResizeTexture(&m_vram_extract_texture, scaled_display_width, read_height,
|
||||||
GPUTexture::Type::RenderTarget, GPUTexture::Format::RGBA8)) [[unlikely]]
|
GPUTexture::Type::RenderTarget, GPUTexture::Format::RGBA8) ||
|
||||||
|
(depth_source &&
|
||||||
|
!g_gpu_device->ResizeTexture(&m_vram_extract_depth_texture, scaled_display_width, scaled_display_height,
|
||||||
|
GPUTexture::Type::RenderTarget, VRAM_DS_EXTRACT_FORMAT))) [[unlikely]]
|
||||||
{
|
{
|
||||||
ClearDisplayTexture();
|
ClearDisplayTexture();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_vram_texture->MakeReadyForSampling();
|
||||||
g_gpu_device->InvalidateRenderTarget(m_vram_extract_texture.get());
|
g_gpu_device->InvalidateRenderTarget(m_vram_extract_texture.get());
|
||||||
g_gpu_device->SetRenderTarget(m_vram_extract_texture.get());
|
|
||||||
g_gpu_device->SetPipeline(m_vram_extract_pipeline[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)].get());
|
if (depth_source)
|
||||||
g_gpu_device->SetTextureSampler(0, m_vram_texture.get(), g_gpu_device->GetNearestSampler());
|
{
|
||||||
|
depth_source->MakeReadyForSampling();
|
||||||
|
g_gpu_device->InvalidateRenderTarget(m_vram_extract_depth_texture.get());
|
||||||
|
|
||||||
|
GPUTexture* targets[] = {m_vram_extract_texture.get(), m_vram_extract_depth_texture.get()};
|
||||||
|
g_gpu_device->SetRenderTargets(targets, static_cast<u32>(std::size(targets)), nullptr);
|
||||||
|
g_gpu_device->SetPipeline(m_vram_extract_pipeline[2].get());
|
||||||
|
|
||||||
|
g_gpu_device->SetTextureSampler(0, m_vram_texture.get(), g_gpu_device->GetNearestSampler());
|
||||||
|
g_gpu_device->SetTextureSampler(1, depth_source, g_gpu_device->GetNearestSampler());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_gpu_device->SetRenderTarget(m_vram_extract_texture.get());
|
||||||
|
g_gpu_device->SetPipeline(m_vram_extract_pipeline[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)].get());
|
||||||
|
g_gpu_device->SetTextureSampler(0, m_vram_texture.get(), g_gpu_device->GetNearestSampler());
|
||||||
|
}
|
||||||
|
|
||||||
const u32 reinterpret_start_x = m_crtc_state.regs.X * resolution_scale;
|
const u32 reinterpret_start_x = m_crtc_state.regs.X * resolution_scale;
|
||||||
const u32 skip_x = (m_crtc_state.display_vram_left - m_crtc_state.regs.X) * resolution_scale;
|
const u32 skip_x = (m_crtc_state.display_vram_left - m_crtc_state.regs.X) * resolution_scale;
|
||||||
GL_INS_FMT("Convert 16bpp to 24bpp, skip_x = {}, line_skip = {}", skip_x, line_skip);
|
GL_INS_FMT("VRAM extract, depth = {}, 24bpp = {}, skip_x = {}, line_skip = {}", depth_source ? "yes" : "no",
|
||||||
|
m_GPUSTAT.display_area_color_depth_24.GetValue(), skip_x, line_skip);
|
||||||
|
GL_INS_FMT("Source: {},{} => {},{} ({}x{})", reinterpret_start_x, scaled_vram_offset_y,
|
||||||
|
reinterpret_start_x + scaled_display_width, scaled_vram_offset_y + read_height, scaled_display_width,
|
||||||
|
read_height);
|
||||||
|
|
||||||
const u32 uniforms[4] = {reinterpret_start_x, scaled_vram_offset_y, skip_x, line_skip};
|
const u32 uniforms[4] = {reinterpret_start_x, scaled_vram_offset_y, skip_x, line_skip};
|
||||||
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
|
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
|
||||||
|
@ -3221,9 +3317,17 @@ void GPU_HW::UpdateDisplay()
|
||||||
g_gpu_device->Draw(3, 0);
|
g_gpu_device->Draw(3, 0);
|
||||||
|
|
||||||
m_vram_extract_texture->MakeReadyForSampling();
|
m_vram_extract_texture->MakeReadyForSampling();
|
||||||
|
if (depth_source)
|
||||||
|
{
|
||||||
|
// Thanks DX11...
|
||||||
|
m_vram_extract_depth_texture->MakeReadyForSampling();
|
||||||
|
g_gpu_device->SetTextureSampler(1, nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
drew_anything = true;
|
drew_anything = true;
|
||||||
|
|
||||||
SetDisplayTexture(m_vram_extract_texture.get(), 0, 0, scaled_display_width, read_height);
|
SetDisplayTexture(m_vram_extract_texture.get(), depth_source ? m_vram_extract_depth_texture.get() : nullptr, 0, 0,
|
||||||
|
scaled_display_width, read_height);
|
||||||
if (g_settings.gpu_24bit_chroma_smoothing)
|
if (g_settings.gpu_24bit_chroma_smoothing)
|
||||||
{
|
{
|
||||||
if (ApplyChromaSmoothing())
|
if (ApplyChromaSmoothing())
|
||||||
|
@ -3252,6 +3356,7 @@ void GPU_HW::UpdateDisplay()
|
||||||
void GPU_HW::OnBufferSwapped()
|
void GPU_HW::OnBufferSwapped()
|
||||||
{
|
{
|
||||||
GL_INS("OnBufferSwapped()");
|
GL_INS("OnBufferSwapped()");
|
||||||
|
m_depth_was_copied = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW::DownsampleFramebuffer()
|
void GPU_HW::DownsampleFramebuffer()
|
||||||
|
@ -3383,7 +3488,7 @@ void GPU_HW::DownsampleFramebufferAdaptive(GPUTexture* source, u32 left, u32 top
|
||||||
|
|
||||||
RestoreDeviceContext();
|
RestoreDeviceContext();
|
||||||
|
|
||||||
SetDisplayTexture(m_downsample_texture.get(), 0, 0, width, height);
|
SetDisplayTexture(m_downsample_texture.get(), m_display_depth_buffer, 0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW::DownsampleFramebufferBoxFilter(GPUTexture* source, u32 left, u32 top, u32 width, u32 height)
|
void GPU_HW::DownsampleFramebufferBoxFilter(GPUTexture* source, u32 left, u32 top, u32 width, u32 height)
|
||||||
|
@ -3421,7 +3526,7 @@ void GPU_HW::DownsampleFramebufferBoxFilter(GPUTexture* source, u32 left, u32 to
|
||||||
|
|
||||||
RestoreDeviceContext();
|
RestoreDeviceContext();
|
||||||
|
|
||||||
SetDisplayTexture(m_downsample_texture.get(), 0, 0, ds_width, ds_height);
|
SetDisplayTexture(m_downsample_texture.get(), m_display_depth_buffer, 0, 0, ds_width, ds_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW::DrawRendererStats()
|
void GPU_HW::DrawRendererStats()
|
||||||
|
|
|
@ -133,6 +133,7 @@ private:
|
||||||
|
|
||||||
void UpdateVRAMReadTexture(bool drawn, bool written);
|
void UpdateVRAMReadTexture(bool drawn, bool written);
|
||||||
void UpdateDepthBufferFromMaskBit();
|
void UpdateDepthBufferFromMaskBit();
|
||||||
|
void CopyAndClearDepthBuffer();
|
||||||
void ClearDepthBuffer();
|
void ClearDepthBuffer();
|
||||||
void SetScissor();
|
void SetScissor();
|
||||||
void SetVRAMRenderTarget();
|
void SetVRAMRenderTarget();
|
||||||
|
@ -203,6 +204,7 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<GPUTexture> m_vram_texture;
|
std::unique_ptr<GPUTexture> m_vram_texture;
|
||||||
std::unique_ptr<GPUTexture> m_vram_depth_texture;
|
std::unique_ptr<GPUTexture> m_vram_depth_texture;
|
||||||
|
std::unique_ptr<GPUTexture> m_vram_depth_copy_texture;
|
||||||
std::unique_ptr<GPUTexture> m_vram_read_texture;
|
std::unique_ptr<GPUTexture> m_vram_read_texture;
|
||||||
std::unique_ptr<GPUTexture> m_vram_readback_texture;
|
std::unique_ptr<GPUTexture> m_vram_readback_texture;
|
||||||
std::unique_ptr<GPUDownloadTexture> m_vram_readback_download_texture;
|
std::unique_ptr<GPUDownloadTexture> m_vram_readback_download_texture;
|
||||||
|
@ -245,6 +247,7 @@ private:
|
||||||
bool m_allow_shader_blend : 1 = false;
|
bool m_allow_shader_blend : 1 = false;
|
||||||
bool m_prefer_shader_blend : 1 = false;
|
bool m_prefer_shader_blend : 1 = false;
|
||||||
u8 m_texpage_dirty = 0;
|
u8 m_texpage_dirty = 0;
|
||||||
|
bool m_depth_was_copied = false;
|
||||||
|
|
||||||
BatchConfig m_batch;
|
BatchConfig m_batch;
|
||||||
|
|
||||||
|
@ -272,8 +275,10 @@ private:
|
||||||
std::unique_ptr<GPUPipeline> m_vram_update_depth_pipeline;
|
std::unique_ptr<GPUPipeline> m_vram_update_depth_pipeline;
|
||||||
std::unique_ptr<GPUPipeline> m_vram_write_replacement_pipeline;
|
std::unique_ptr<GPUPipeline> m_vram_write_replacement_pipeline;
|
||||||
|
|
||||||
std::array<std::unique_ptr<GPUPipeline>, 2> m_vram_extract_pipeline; // [24bit]
|
std::array<std::unique_ptr<GPUPipeline>, 3> m_vram_extract_pipeline; // [24bit, 2=depth]
|
||||||
std::unique_ptr<GPUTexture> m_vram_extract_texture;
|
std::unique_ptr<GPUTexture> m_vram_extract_texture;
|
||||||
|
std::unique_ptr<GPUTexture> m_vram_extract_depth_texture;
|
||||||
|
std::unique_ptr<GPUPipeline> m_copy_depth_pipeline;
|
||||||
|
|
||||||
std::unique_ptr<GPUTexture> m_downsample_texture;
|
std::unique_ptr<GPUTexture> m_downsample_texture;
|
||||||
std::unique_ptr<GPUPipeline> m_downsample_first_pass_pipeline;
|
std::unique_ptr<GPUPipeline> m_downsample_first_pass_pipeline;
|
||||||
|
|
|
@ -1026,16 +1026,19 @@ float3 ApplyDebanding(float2 frag_coord)
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GPU_HW_ShaderGen::GenerateVRAMExtractFragmentShader(bool depth_24bit)
|
std::string GPU_HW_ShaderGen::GenerateVRAMExtractFragmentShader(bool color_24bit, bool depth_buffer)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
WriteHeader(ss);
|
WriteHeader(ss);
|
||||||
DefineMacro(ss, "DEPTH_24BIT", depth_24bit);
|
DefineMacro(ss, "COLOR_24BIT", color_24bit);
|
||||||
|
DefineMacro(ss, "DEPTH_BUFFER", depth_buffer);
|
||||||
DefineMacro(ss, "MULTISAMPLED", UsingMSAA());
|
DefineMacro(ss, "MULTISAMPLED", UsingMSAA());
|
||||||
|
|
||||||
WriteCommonFunctions(ss);
|
WriteCommonFunctions(ss);
|
||||||
DeclareUniformBuffer(ss, {"uint2 u_vram_offset", "uint u_skip_x", "uint u_line_skip"}, true);
|
DeclareUniformBuffer(ss, {"uint2 u_vram_offset", "uint u_skip_x", "uint u_line_skip"}, true);
|
||||||
DeclareTexture(ss, "samp0", 0, UsingMSAA());
|
DeclareTexture(ss, "samp0", 0, UsingMSAA());
|
||||||
|
if (depth_buffer)
|
||||||
|
DeclareTexture(ss, "samp1", 1, UsingMSAA());
|
||||||
|
|
||||||
ss << R"(
|
ss << R"(
|
||||||
float4 LoadVRAM(int2 coords)
|
float4 LoadVRAM(int2 coords)
|
||||||
|
@ -1051,6 +1054,22 @@ float4 LoadVRAM(int2 coords)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEPTH_BUFFER
|
||||||
|
float LoadDepth(int2 coords)
|
||||||
|
{
|
||||||
|
// Need to duplicate because different types in different languages...
|
||||||
|
#if MULTISAMPLING
|
||||||
|
float value = LOAD_TEXTURE_MS(samp1, coords, 0u).r;
|
||||||
|
FOR_UNROLL (uint sample_index = 1u; sample_index < MULTISAMPLES; sample_index++)
|
||||||
|
value += LOAD_TEXTURE_MS(samp1, coords, sample_index).r;
|
||||||
|
value /= float(MULTISAMPLES);
|
||||||
|
return value;
|
||||||
|
#else
|
||||||
|
return LOAD_TEXTURE(samp1, coords, 0).r;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
float3 SampleVRAM24(uint2 icoords)
|
float3 SampleVRAM24(uint2 icoords)
|
||||||
{
|
{
|
||||||
// load adjacent 16-bit texels
|
// load adjacent 16-bit texels
|
||||||
|
@ -1070,15 +1089,20 @@ float3 SampleVRAM24(uint2 icoords)
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
DeclareFragmentEntryPoint(ss, 0, 1, {}, true, 1);
|
DeclareFragmentEntryPoint(ss, 0, 1, {}, true, depth_buffer ? 2 : 1);
|
||||||
ss << R"(
|
ss << R"(
|
||||||
{
|
{
|
||||||
uint2 icoords = uint2(uint(v_pos.x) + u_skip_x, uint(v_pos.y) << u_line_skip);
|
uint2 icoords = uint2(uint(v_pos.x) + u_skip_x, uint(v_pos.y) << u_line_skip);
|
||||||
|
int2 wrapped_coords = int2((icoords + u_vram_offset) % VRAM_SIZE);
|
||||||
|
|
||||||
#if DEPTH_24BIT
|
#if COLOR_24BIT
|
||||||
o_col0 = float4(SampleVRAM24(icoords), 1.0);
|
o_col0 = float4(SampleVRAM24(icoords), 1.0);
|
||||||
#else
|
#else
|
||||||
o_col0 = float4(LoadVRAM(int2((icoords + u_vram_offset) % VRAM_SIZE)).rgb, 1.0);
|
o_col0 = float4(LoadVRAM(wrapped_coords).rgb, 1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DEPTH_BUFFER
|
||||||
|
o_col1 = float4(LoadDepth(wrapped_coords), 0.0, 0.0, 0.0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
|
@ -25,7 +25,7 @@ public:
|
||||||
std::string GenerateVRAMCopyFragmentShader();
|
std::string GenerateVRAMCopyFragmentShader();
|
||||||
std::string GenerateVRAMFillFragmentShader(bool wrapped, bool interlaced);
|
std::string GenerateVRAMFillFragmentShader(bool wrapped, bool interlaced);
|
||||||
std::string GenerateVRAMUpdateDepthFragmentShader();
|
std::string GenerateVRAMUpdateDepthFragmentShader();
|
||||||
std::string GenerateVRAMExtractFragmentShader(bool depth_24bit);
|
std::string GenerateVRAMExtractFragmentShader(bool color_24bit, bool depth_buffer);
|
||||||
|
|
||||||
std::string GenerateAdaptiveDownsampleVertexShader();
|
std::string GenerateAdaptiveDownsampleVertexShader();
|
||||||
std::string GenerateAdaptiveDownsampleMipFragmentShader(bool first_pass);
|
std::string GenerateAdaptiveDownsampleMipFragmentShader(bool first_pass);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
#include "gpu_shadergen.h"
|
#include "gpu_shadergen.h"
|
||||||
|
#include "common/bitutils.h"
|
||||||
|
|
||||||
GPUShaderGen::GPUShaderGen(RenderAPI render_api, bool supports_dual_source_blend, bool supports_framebuffer_fetch)
|
GPUShaderGen::GPUShaderGen(RenderAPI render_api, bool supports_dual_source_blend, bool supports_framebuffer_fetch)
|
||||||
: ShaderGen(render_api, supports_dual_source_blend, supports_framebuffer_fetch)
|
: ShaderGen(render_api, supports_dual_source_blend, supports_framebuffer_fetch)
|
||||||
|
@ -40,33 +41,45 @@ std::string GPUShaderGen::GenerateDisplayVertexShader()
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GPUShaderGen::GenerateDisplayFragmentShader(bool clamp_uv)
|
std::string GPUShaderGen::GenerateDisplayFragmentShader(bool copy_depth, bool clamp_uv)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
WriteHeader(ss);
|
WriteHeader(ss);
|
||||||
WriteDisplayUniformBuffer(ss);
|
WriteDisplayUniformBuffer(ss);
|
||||||
DeclareTexture(ss, "samp0", 0);
|
DeclareTexture(ss, "samp0", 0);
|
||||||
DeclareFragmentEntryPoint(ss, 0, 1);
|
if (copy_depth)
|
||||||
|
DeclareTexture(ss, "samp1", 1);
|
||||||
|
|
||||||
|
DeclareFragmentEntryPoint(ss, 0, 1, {}, false, 1 + BoolToUInt32(copy_depth));
|
||||||
|
ss << "{\n";
|
||||||
if (clamp_uv)
|
if (clamp_uv)
|
||||||
ss << "{\n o_col0 = float4(SAMPLE_TEXTURE(samp0, ClampUV(v_tex0)).rgb, 1.0f);\n }";
|
ss << " float2 uv = ClampUV(v_tex0);\n";
|
||||||
else
|
else
|
||||||
ss << "{\n o_col0 = float4(SAMPLE_TEXTURE(samp0, v_tex0).rgb, 1.0f);\n }";
|
ss << " float2 uv = v_tex0;\n";
|
||||||
|
|
||||||
|
ss << " o_col0 = float4(SAMPLE_TEXTURE(samp0, uv).rgb, 1.0f);\n";
|
||||||
|
if (copy_depth)
|
||||||
|
ss << " o_col1 = float4(SAMPLE_TEXTURE(samp1, uv).r, 0.0f, 0.0f, 0.0f);\n";
|
||||||
|
|
||||||
|
ss << "}\n";
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GPUShaderGen::GenerateDisplaySharpBilinearFragmentShader()
|
std::string GPUShaderGen::GenerateDisplaySharpBilinearFragmentShader(bool copy_depth)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
WriteHeader(ss);
|
WriteHeader(ss);
|
||||||
WriteDisplayUniformBuffer(ss);
|
WriteDisplayUniformBuffer(ss);
|
||||||
DeclareTexture(ss, "samp0", 0, false);
|
DeclareTexture(ss, "samp0", 0, false);
|
||||||
|
if (copy_depth)
|
||||||
|
DeclareTexture(ss, "samp1", 1);
|
||||||
|
|
||||||
// Based on
|
// Based on
|
||||||
// https://github.com/rsn8887/Sharp-Bilinear-Shaders/blob/master/Copy_To_RetroPie/shaders/sharp-bilinear-simple.glsl
|
// https://github.com/rsn8887/Sharp-Bilinear-Shaders/blob/master/Copy_To_RetroPie/shaders/sharp-bilinear-simple.glsl
|
||||||
DeclareFragmentEntryPoint(ss, 0, 1);
|
DeclareFragmentEntryPoint(ss, 0, 1, {}, false, 1 + BoolToUInt32(copy_depth));
|
||||||
|
ss << "{\n";
|
||||||
ss << R"(
|
ss << R"(
|
||||||
{
|
|
||||||
float2 scale = u_params.xy;
|
float2 scale = u_params.xy;
|
||||||
float2 region_range = u_params.zw;
|
float2 region_range = u_params.zw;
|
||||||
|
|
||||||
|
@ -78,8 +91,13 @@ std::string GPUShaderGen::GenerateDisplaySharpBilinearFragmentShader()
|
||||||
float2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5;
|
float2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5;
|
||||||
float2 mod_texel = texel_floored + f;
|
float2 mod_texel = texel_floored + f;
|
||||||
|
|
||||||
o_col0 = float4(SAMPLE_TEXTURE(samp0, ClampUV(mod_texel * u_src_size.zw)).rgb, 1.0f);
|
float2 uv = ClampUV(mod_texel * u_src_size.zw);
|
||||||
})";
|
o_col0 = float4(SAMPLE_TEXTURE(samp0, uv).rgb, 1.0f);
|
||||||
|
)";
|
||||||
|
if (copy_depth)
|
||||||
|
ss << " o_col1 = float4(SAMPLE_TEXTURE(samp1, uv).r, 0.0f, 0.0f, 0.0f);\n";
|
||||||
|
|
||||||
|
ss << "}\n";
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ public:
|
||||||
~GPUShaderGen();
|
~GPUShaderGen();
|
||||||
|
|
||||||
std::string GenerateDisplayVertexShader();
|
std::string GenerateDisplayVertexShader();
|
||||||
std::string GenerateDisplayFragmentShader(bool clamp_uv);
|
std::string GenerateDisplayFragmentShader(bool copy_depth, bool clamp_uv);
|
||||||
std::string GenerateDisplaySharpBilinearFragmentShader();
|
std::string GenerateDisplaySharpBilinearFragmentShader(bool copy_depth);
|
||||||
|
|
||||||
std::string GenerateInterleavedFieldExtractFragmentShader();
|
std::string GenerateInterleavedFieldExtractFragmentShader();
|
||||||
std::string GenerateDeinterlaceWeaveFragmentShader();
|
std::string GenerateDeinterlaceWeaveFragmentShader();
|
||||||
|
|
|
@ -490,7 +490,7 @@ void GPU_SW::UpdateDisplay()
|
||||||
const u32 line_skip = m_GPUSTAT.vertical_resolution;
|
const u32 line_skip = m_GPUSTAT.vertical_resolution;
|
||||||
if (CopyOut(vram_offset_x, vram_offset_y, skip_x, read_width, read_height, line_skip, is_24bit))
|
if (CopyOut(vram_offset_x, vram_offset_y, skip_x, read_width, read_height, line_skip, is_24bit))
|
||||||
{
|
{
|
||||||
SetDisplayTexture(m_upload_texture.get(), 0, 0, read_width, read_height);
|
SetDisplayTexture(m_upload_texture.get(), nullptr, 0, 0, read_width, read_height);
|
||||||
if (is_24bit && g_settings.gpu_24bit_chroma_smoothing)
|
if (is_24bit && g_settings.gpu_24bit_chroma_smoothing)
|
||||||
{
|
{
|
||||||
if (ApplyChromaSmoothing())
|
if (ApplyChromaSmoothing())
|
||||||
|
@ -506,7 +506,7 @@ void GPU_SW::UpdateDisplay()
|
||||||
{
|
{
|
||||||
if (CopyOut(vram_offset_x, vram_offset_y, skip_x, read_width, read_height, 0, is_24bit))
|
if (CopyOut(vram_offset_x, vram_offset_y, skip_x, read_width, read_height, 0, is_24bit))
|
||||||
{
|
{
|
||||||
SetDisplayTexture(m_upload_texture.get(), 0, 0, read_width, read_height);
|
SetDisplayTexture(m_upload_texture.get(), nullptr, 0, 0, read_width, read_height);
|
||||||
if (is_24bit && g_settings.gpu_24bit_chroma_smoothing)
|
if (is_24bit && g_settings.gpu_24bit_chroma_smoothing)
|
||||||
ApplyChromaSmoothing();
|
ApplyChromaSmoothing();
|
||||||
}
|
}
|
||||||
|
@ -517,7 +517,7 @@ void GPU_SW::UpdateDisplay()
|
||||||
SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
||||||
if (CopyOut(0, 0, 0, VRAM_WIDTH, VRAM_HEIGHT, 0, false))
|
if (CopyOut(0, 0, 0, VRAM_WIDTH, VRAM_HEIGHT, 0, false))
|
||||||
SetDisplayTexture(m_upload_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT);
|
SetDisplayTexture(m_upload_texture.get(), nullptr, 0, 0, VRAM_WIDTH, VRAM_HEIGHT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue