From c5bd4101b3bad2bb5b73eb13dd612707d0820cce Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 30 Dec 2024 14:36:14 +1000 Subject: [PATCH] GPU: Refactor and simplify deinterlacing Both HW and SW deal with half-height buffers coming in now. --- src/core/gpu.cpp | 13 +-- src/core/gpu_backend.cpp | 136 +++++++++++--------------------- src/core/gpu_backend.h | 4 +- src/core/gpu_hw.cpp | 28 +++---- src/core/gpu_hw_shadergen.cpp | 4 +- src/core/gpu_shadergen.cpp | 22 +----- src/core/gpu_shadergen.h | 1 - src/core/gpu_sw.cpp | 25 +++--- src/core/shader_cache_version.h | 2 +- 9 files changed, 86 insertions(+), 149 deletions(-) diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index e3fb627c8..e8a1f7794 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -1883,19 +1883,22 @@ void GPU::ClearDisplay() void GPU::UpdateDisplay(bool submit_frame) { + const bool interlaced = IsInterlacedDisplayEnabled(); + const u8 interlaced_field = GetInterlacedDisplayField(); + const bool line_skip = (interlaced && m_GPUSTAT.vertical_resolution); GPUBackendUpdateDisplayCommand* cmd = GPUBackend::NewUpdateDisplayCommand(); cmd->display_width = m_crtc_state.display_width; cmd->display_height = m_crtc_state.display_height; cmd->display_origin_left = m_crtc_state.display_origin_left; cmd->display_origin_top = m_crtc_state.display_origin_top; cmd->display_vram_left = m_crtc_state.display_vram_left; - cmd->display_vram_top = m_crtc_state.display_vram_top; + cmd->display_vram_top = m_crtc_state.display_vram_top + (interlaced_field & BoolToUInt8(line_skip)); cmd->display_vram_width = m_crtc_state.display_vram_width; - cmd->display_vram_height = m_crtc_state.display_vram_height; + cmd->display_vram_height = m_crtc_state.display_vram_height >> BoolToUInt8(interlaced); cmd->X = m_crtc_state.regs.X; - cmd->interlaced_display_enabled = IsInterlacedDisplayEnabled(); - cmd->interlaced_display_field = ConvertToBoolUnchecked(GetInterlacedDisplayField()); - cmd->interlaced_display_interleaved = cmd->interlaced_display_enabled && m_GPUSTAT.vertical_resolution; + cmd->interlaced_display_enabled = interlaced; + cmd->interlaced_display_field = ConvertToBoolUnchecked(interlaced_field); + cmd->interlaced_display_interleaved = line_skip; cmd->display_24bit = m_GPUSTAT.display_area_color_depth_24; cmd->display_disabled = IsDisplayDisabled(); cmd->display_pixel_aspect_ratio = ComputePixelAspectRatio(); diff --git a/src/core/gpu_backend.cpp b/src/core/gpu_backend.cpp index 1b1c9c4d3..d2c2e9b34 100644 --- a/src/core/gpu_backend.cpp +++ b/src/core/gpu_backend.cpp @@ -578,30 +578,15 @@ bool GPUBackend::CompileDisplayPipelines(bool display, bool deinterlace, bool ch if (deinterlace) { - plconfig.SetTargetFormats(GPUTexture::Format::RGBA8); - std::unique_ptr vso = g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(), shadergen.GenerateScreenQuadVertexShader(), error); if (!vso) return false; GL_OBJECT_NAME(vso, "Deinterlace Vertex Shader"); - std::unique_ptr fso; - if (!(fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), - shadergen.GenerateInterleavedFieldExtractFragmentShader(), error))) - { - return false; - } - - GL_OBJECT_NAME(fso, "Deinterlace Field Extract Fragment Shader"); - plconfig.layout = GPUPipeline::Layout::SingleTextureAndPushConstants; plconfig.vertex_shader = vso.get(); - plconfig.fragment_shader = fso.get(); - if (!(m_deinterlace_extract_pipeline = g_gpu_device->CreatePipeline(plconfig, error))) - return false; - - GL_OBJECT_NAME(m_deinterlace_extract_pipeline, "Deinterlace Field Extract Pipeline"); + plconfig.SetTargetFormats(GPUTexture::Format::RGBA8); switch (g_gpu_settings.display_deinterlacing_mode) { @@ -611,11 +596,10 @@ bool GPUBackend::CompileDisplayPipelines(bool display, bool deinterlace, bool ch case DisplayDeinterlacingMode::Weave: { - if (!(fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), - shadergen.GenerateDeinterlaceWeaveFragmentShader(), error))) - { + std::unique_ptr fso = g_gpu_device->CreateShader( + GPUShaderStage::Fragment, shadergen.GetLanguage(), shadergen.GenerateDeinterlaceWeaveFragmentShader(), error); + if (!fso) return false; - } GL_OBJECT_NAME(fso, "Weave Deinterlace Fragment Shader"); @@ -631,11 +615,10 @@ bool GPUBackend::CompileDisplayPipelines(bool display, bool deinterlace, bool ch case DisplayDeinterlacingMode::Blend: { - if (!(fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), - shadergen.GenerateDeinterlaceBlendFragmentShader(), error))) - { + std::unique_ptr fso = g_gpu_device->CreateShader( + GPUShaderStage::Fragment, shadergen.GetLanguage(), shadergen.GenerateDeinterlaceBlendFragmentShader(), error); + if (!fso) return false; - } GL_OBJECT_NAME(fso, "Blend Deinterlace Fragment Shader"); @@ -651,8 +634,9 @@ bool GPUBackend::CompileDisplayPipelines(bool display, bool deinterlace, bool ch case DisplayDeinterlacingMode::Adaptive: { - fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), - shadergen.GenerateFastMADReconstructFragmentShader(), error); + std::unique_ptr fso = + g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), + shadergen.GenerateFastMADReconstructFragmentShader(), error); if (!fso) return false; @@ -704,13 +688,14 @@ bool GPUBackend::CompileDisplayPipelines(bool display, bool deinterlace, bool ch void GPUBackend::HandleUpdateDisplayCommand(const GPUBackendUpdateDisplayCommand* cmd) { + // Height has to be doubled because we halved it on the GPU side. const GPUBackendUpdateDisplayCommand* ccmd = static_cast(cmd); m_display_width = ccmd->display_width; m_display_height = ccmd->display_height; m_display_origin_left = ccmd->display_origin_left; m_display_origin_top = ccmd->display_origin_top; m_display_vram_width = ccmd->display_vram_width; - m_display_vram_height = ccmd->display_vram_height; + m_display_vram_height = (ccmd->display_vram_height << BoolToUInt32(ccmd->interlaced_display_enabled)); m_display_pixel_aspect_ratio = ccmd->display_pixel_aspect_ratio; UpdateDisplay(ccmd); @@ -1022,7 +1007,7 @@ void GPUBackend::DestroyDeinterlaceTextures() m_current_deinterlace_buffer = 0; } -bool GPUBackend::Deinterlace(u32 field, u32 line_skip) +bool GPUBackend::Deinterlace(u32 field) { GPUTexture* src = m_display_texture; const u32 x = m_display_texture_view_x; @@ -1030,24 +1015,39 @@ bool GPUBackend::Deinterlace(u32 field, u32 line_skip) const u32 width = m_display_texture_view_width; const u32 height = m_display_texture_view_height; + const auto copy_to_field_buffer = [&](u32 buffer) { + if (!m_deinterlace_buffers[buffer] || m_deinterlace_buffers[buffer]->GetWidth() != width || + m_deinterlace_buffers[buffer]->GetHeight() != height || + m_deinterlace_buffers[buffer]->GetFormat() != src->GetFormat()) + { + if (!g_gpu_device->ResizeTexture(&m_deinterlace_buffers[buffer], width, height, GPUTexture::Type::Texture, + src->GetFormat(), GPUTexture::Flags::None, false)) [[unlikely]] + { + return false; + } + + GL_OBJECT_NAME_FMT(m_deinterlace_buffers[buffer], "Blend Deinterlace Buffer {}", buffer); + } + + GL_INS_FMT("Copy {}x{} from {},{} to field buffer {}", width, height, x, y, buffer); + g_gpu_device->CopyTextureRegion(m_deinterlace_buffers[buffer].get(), 0, 0, 0, 0, m_display_texture, x, y, 0, 0, + width, height); + return true; + }; + + src->MakeReadyForSampling(); + switch (g_gpu_settings.display_deinterlacing_mode) { case DisplayDeinterlacingMode::Disabled: { - if (line_skip == 0) - return true; - - // Still have to extract the field. - if (!DeinterlaceExtractField(0, src, x, y, width, height, line_skip)) [[unlikely]] - return false; - - SetDisplayTexture(m_deinterlace_buffers[0].get(), m_display_depth_buffer, 0, 0, width, height); + GL_INS("Deinterlacing disabled, displaying field texture"); return true; } case DisplayDeinterlacingMode::Weave: { - GL_SCOPE_FMT("DeinterlaceWeave({{{},{}}}, {}x{}, field={}, line_skip={})", x, y, width, height, field, line_skip); + GL_SCOPE_FMT("DeinterlaceWeave({{{},{}}}, {}x{}, field={})", x, y, width, height, field); const u32 full_height = height * 2; if (!DeinterlaceSetTargetSize(width, full_height, true)) [[unlikely]] @@ -1061,7 +1061,7 @@ bool GPUBackend::Deinterlace(u32 field, u32 line_skip) g_gpu_device->SetRenderTarget(m_deinterlace_texture.get()); g_gpu_device->SetPipeline(m_deinterlace_pipeline.get()); g_gpu_device->SetTextureSampler(0, src, g_gpu_device->GetNearestSampler()); - const u32 uniforms[] = {x, y, field, line_skip}; + const u32 uniforms[4] = {x, y, field, 0}; g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms)); g_gpu_device->SetViewportAndScissor(0, 0, width, full_height); g_gpu_device->Draw(3, 0); @@ -1075,20 +1075,20 @@ bool GPUBackend::Deinterlace(u32 field, u32 line_skip) { constexpr u32 NUM_BLEND_BUFFERS = 2; - GL_SCOPE_FMT("DeinterlaceBlend({{{},{}}}, {}x{}, field={}, line_skip={})", x, y, width, height, field, line_skip); + GL_SCOPE_FMT("DeinterlaceBlend({{{},{}}}, {}x{}, field={})", x, y, width, height, field); const u32 this_buffer = m_current_deinterlace_buffer; m_current_deinterlace_buffer = (m_current_deinterlace_buffer + 1u) % NUM_BLEND_BUFFERS; GL_INS_FMT("Current buffer: {}", this_buffer); - if (!DeinterlaceExtractField(this_buffer, src, x, y, width, height, line_skip) || - !DeinterlaceSetTargetSize(width, height, false)) [[unlikely]] + if (!DeinterlaceSetTargetSize(width, height, false) || !copy_to_field_buffer(this_buffer)) [[unlikely]] { ClearDisplayTexture(); return false; } - // TODO: could be implemented with alpha blending instead.. + copy_to_field_buffer(this_buffer); + // TODO: could be implemented with alpha blending instead.. g_gpu_device->InvalidateRenderTarget(m_deinterlace_texture.get()); g_gpu_device->SetRenderTarget(m_deinterlace_texture.get()); g_gpu_device->SetPipeline(m_deinterlace_pipeline.get()); @@ -1105,15 +1105,13 @@ bool GPUBackend::Deinterlace(u32 field, u32 line_skip) case DisplayDeinterlacingMode::Adaptive: { - GL_SCOPE_FMT("DeinterlaceAdaptive({{{},{}}}, {}x{}, field={}, line_skip={})", x, y, width, height, field, - line_skip); + GL_SCOPE_FMT("DeinterlaceAdaptive({{{},{}}}, {}x{}, field={})", x, y, width, height, field); - const u32 full_height = height * 2; const u32 this_buffer = m_current_deinterlace_buffer; + const u32 full_height = height * 2; m_current_deinterlace_buffer = (m_current_deinterlace_buffer + 1u) % DEINTERLACE_BUFFER_COUNT; GL_INS_FMT("Current buffer: {}", this_buffer); - if (!DeinterlaceExtractField(this_buffer, src, x, y, width, height, line_skip) || - !DeinterlaceSetTargetSize(width, full_height, false)) [[unlikely]] + if (!DeinterlaceSetTargetSize(width, full_height, false) || !copy_to_field_buffer(this_buffer)) [[unlikely]] { ClearDisplayTexture(); return false; @@ -1143,50 +1141,6 @@ bool GPUBackend::Deinterlace(u32 field, u32 line_skip) } } -bool GPUBackend::DeinterlaceExtractField(u32 dst_bufidx, GPUTexture* src, u32 x, u32 y, u32 width, u32 height, - u32 line_skip) -{ - if (!m_deinterlace_buffers[dst_bufidx] || m_deinterlace_buffers[dst_bufidx]->GetWidth() != width || - m_deinterlace_buffers[dst_bufidx]->GetHeight() != height) - { - if (!g_gpu_device->ResizeTexture(&m_deinterlace_buffers[dst_bufidx], width, height, GPUTexture::Type::RenderTarget, - GPUTexture::Format::RGBA8, GPUTexture::Flags::None, false)) [[unlikely]] - { - return false; - } - - GL_OBJECT_NAME_FMT(m_deinterlace_buffers[dst_bufidx], "Blend Deinterlace Buffer {}", dst_bufidx); - } - - GPUTexture* dst = m_deinterlace_buffers[dst_bufidx].get(); - g_gpu_device->InvalidateRenderTarget(dst); - - // If we're not skipping lines, then we can simply copy the texture. - if (line_skip == 0 && src->GetFormat() == dst->GetFormat()) - { - GL_INS_FMT("DeinterlaceExtractField({{{},{}}} {}x{} line_skip={}) => copy direct", x, y, width, height, line_skip); - g_gpu_device->CopyTextureRegion(dst, 0, 0, 0, 0, src, x, y, 0, 0, width, height); - } - else - { - GL_SCOPE_FMT("DeinterlaceExtractField({{{},{}}} {}x{} line_skip={}) => shader copy", x, y, width, height, - line_skip); - - // Otherwise, we need to extract every other line from the texture. - src->MakeReadyForSampling(); - g_gpu_device->SetRenderTarget(dst); - g_gpu_device->SetPipeline(m_deinterlace_extract_pipeline.get()); - g_gpu_device->SetTextureSampler(0, src, g_gpu_device->GetNearestSampler()); - const u32 uniforms[] = {x, y, line_skip}; - g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms)); - g_gpu_device->SetViewportAndScissor(0, 0, width, height); - g_gpu_device->Draw(3, 0); - } - - dst->MakeReadyForSampling(); - return true; -} - bool GPUBackend::DeinterlaceSetTargetSize(u32 width, u32 height, bool preserve) { if (!m_deinterlace_texture || m_deinterlace_texture->GetWidth() != width || diff --git a/src/core/gpu_backend.h b/src/core/gpu_backend.h index 1314ffa9a..223a44da1 100644 --- a/src/core/gpu_backend.h +++ b/src/core/gpu_backend.h @@ -167,8 +167,7 @@ protected: /// Sends the current frame to media capture. void SendDisplayToMediaCapture(MediaCapture* cap); - bool Deinterlace(u32 field, u32 line_skip); - bool DeinterlaceExtractField(u32 dst_bufidx, GPUTexture* src, u32 x, u32 y, u32 width, u32 height, u32 line_skip); + bool Deinterlace(u32 field); bool DeinterlaceSetTargetSize(u32 width, u32 height, bool preserve); void DestroyDeinterlaceTextures(); bool ApplyChromaSmoothing(); @@ -185,7 +184,6 @@ protected: u32 m_current_deinterlace_buffer = 0; std::unique_ptr m_deinterlace_pipeline; - std::unique_ptr m_deinterlace_extract_pipeline; std::array, DEINTERLACE_BUFFER_COUNT> m_deinterlace_buffers; std::unique_ptr m_deinterlace_texture; diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index a6ed0a567..9e600cb10 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -3843,14 +3843,12 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd) const bool interlaced = cmd->interlaced_display_enabled; const u32 interlaced_field = BoolToUInt32(cmd->interlaced_display_field); + const u32 line_skip = BoolToUInt32(cmd->interlaced_display_interleaved); const u32 resolution_scale = cmd->display_24bit ? 1 : m_resolution_scale; const u32 scaled_vram_offset_x = cmd->display_vram_left * resolution_scale; - const u32 scaled_vram_offset_y = (cmd->display_vram_top * resolution_scale) + - ((interlaced && cmd->interlaced_display_interleaved) ? interlaced_field : 0); + const u32 scaled_vram_offset_y = cmd->display_vram_top * resolution_scale; const u32 scaled_display_width = cmd->display_vram_width * resolution_scale; const u32 scaled_display_height = cmd->display_vram_height * resolution_scale; - const u32 read_height = interlaced ? (scaled_display_height / 2u) : scaled_display_height; - const u32 line_skip = cmd->interlaced_display_interleaved; bool drew_anything = false; // Don't bother grabbing depth if postfx doesn't need it. @@ -3864,20 +3862,20 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd) ClearDisplayTexture(); return; } - else if (!cmd->display_24bit && !IsUsingMultisampling() && + else if (!cmd->display_24bit && line_skip == 0 && !IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture->GetWidth() && (scaled_vram_offset_y + scaled_display_height) <= m_vram_texture->GetHeight() && !PostProcessing::InternalChain.IsActive()) { SetDisplayTexture(m_vram_texture.get(), depth_source, scaled_vram_offset_x, scaled_vram_offset_y, - scaled_display_width, read_height); + scaled_display_width, scaled_display_height); // Fast path if no copies are needed. if (interlaced) { GL_INS("Deinterlace fast path"); drew_anything = true; - Deinterlace(interlaced_field, line_skip); + Deinterlace(interlaced_field); } else { @@ -3887,9 +3885,9 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd) else { if (!m_vram_extract_texture || m_vram_extract_texture->GetWidth() != scaled_display_width || - m_vram_extract_texture->GetHeight() != read_height) + m_vram_extract_texture->GetHeight() != scaled_display_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, scaled_display_height, GPUTexture::Type::RenderTarget, GPUTexture::Format::RGBA8, GPUTexture::Flags::None)) [[unlikely]] { @@ -3929,8 +3927,8 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd) GL_INS_FMT("VRAM extract, depth = {}, 24bpp = {}, skip_x = {}, line_skip = {}", depth_source ? "yes" : "no", cmd->display_24bit, 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); + reinterpret_start_x + scaled_display_width, (scaled_vram_offset_y + scaled_display_height) << line_skip, + scaled_display_width, scaled_display_height); struct ExtractUniforms { @@ -3943,7 +3941,7 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd) static_cast(line_skip ? 2 : 1)}; g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms)); - g_gpu_device->SetViewportAndScissor(0, 0, scaled_display_width, read_height); + g_gpu_device->SetViewportAndScissor(0, 0, scaled_display_width, scaled_display_height); g_gpu_device->Draw(3, 0); m_vram_extract_texture->MakeReadyForSampling(); @@ -3957,19 +3955,19 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd) drew_anything = true; SetDisplayTexture(m_vram_extract_texture.get(), depth_source ? m_vram_extract_depth_texture.get() : nullptr, 0, 0, - scaled_display_width, read_height); + scaled_display_width, scaled_display_height); if (g_settings.display_24bit_chroma_smoothing) { if (ApplyChromaSmoothing()) { if (interlaced) - Deinterlace(interlaced_field, 0); + Deinterlace(interlaced_field); } } else { if (interlaced) - Deinterlace(interlaced_field, 0); + Deinterlace(interlaced_field); } } diff --git a/src/core/gpu_hw_shadergen.cpp b/src/core/gpu_hw_shadergen.cpp index b3fd5fdd7..83fe2dd10 100644 --- a/src/core/gpu_hw_shadergen.cpp +++ b/src/core/gpu_hw_shadergen.cpp @@ -1266,7 +1266,9 @@ float3 SampleVRAM24(uint2 icoords) DeclareFragmentEntryPoint(ss, 0, 1, {}, true, depth_buffer ? 2 : 1); ss << R"( { - uint2 icoords = uint2(v_pos.x + u_skip_x, v_pos.y * u_line_skip); + // Have to floor because SV_Position is at the pixel center. + float2 v_pos_floored = floor(v_pos.xy); + uint2 icoords = uint2(v_pos_floored.x + u_skip_x, v_pos_floored.y * u_line_skip); int2 wrapped_coords = int2((icoords + u_vram_offset) % VRAM_SIZE); #if COLOR_24BIT diff --git a/src/core/gpu_shadergen.cpp b/src/core/gpu_shadergen.cpp index 6f43c3ee4..4e275d4ab 100644 --- a/src/core/gpu_shadergen.cpp +++ b/src/core/gpu_shadergen.cpp @@ -102,29 +102,11 @@ std::string GPUShaderGen::GenerateDisplaySharpBilinearFragmentShader() const return ss.str(); } -std::string GPUShaderGen::GenerateInterleavedFieldExtractFragmentShader() const -{ - std::stringstream ss; - WriteHeader(ss); - DeclareUniformBuffer(ss, {"uint2 u_src_offset", "uint u_line_skip"}, true); - DeclareTexture(ss, "samp0", 0, false); - - DeclareFragmentEntryPoint(ss, 0, 1, {}, true); - ss << R"( -{ - uint2 tcoord = u_src_offset + uint2(uint(v_pos.x), uint(v_pos.y) << u_line_skip); - o_col0 = LOAD_TEXTURE(samp0, int2(tcoord), 0); -} -)"; - - return ss.str(); -} - std::string GPUShaderGen::GenerateDeinterlaceWeaveFragmentShader() const { std::stringstream ss; WriteHeader(ss); - DeclareUniformBuffer(ss, {"uint2 u_src_offset", "uint u_render_field", "uint u_line_skip"}, true); + DeclareUniformBuffer(ss, {"uint2 u_src_offset", "uint u_render_field"}, true); DeclareTexture(ss, "samp0", 0, false); DeclareFragmentEntryPoint(ss, 0, 1, {}, true); @@ -134,7 +116,7 @@ std::string GPUShaderGen::GenerateDeinterlaceWeaveFragmentShader() const if ((fcoord.y & 1) != u_render_field) discard; - uint2 tcoord = u_src_offset + uint2(fcoord.x, (fcoord.y / 2u) << u_line_skip); + uint2 tcoord = u_src_offset + uint2(fcoord.x, (fcoord.y / 2u)); o_col0 = LOAD_TEXTURE(samp0, int2(tcoord), 0); })"; diff --git a/src/core/gpu_shadergen.h b/src/core/gpu_shadergen.h index 5a912ed68..cb742f75f 100644 --- a/src/core/gpu_shadergen.h +++ b/src/core/gpu_shadergen.h @@ -15,7 +15,6 @@ public: std::string GenerateDisplayFragmentShader(bool clamp_uv, bool nearest) const; std::string GenerateDisplaySharpBilinearFragmentShader() const; - std::string GenerateInterleavedFieldExtractFragmentShader() const; std::string GenerateDeinterlaceWeaveFragmentShader() const; std::string GenerateDeinterlaceBlendFragmentShader() const; std::string GenerateFastMADReconstructFragmentShader() const; diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index 67ea20b67..86e7840eb 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -393,36 +393,37 @@ void GPU_SW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd) } const bool is_24bit = cmd->display_24bit; - const bool interlaced = cmd->interlaced_display_enabled; const u32 field = BoolToUInt32(cmd->interlaced_display_field); - const u32 vram_offset_x = is_24bit ? cmd->X : cmd->display_vram_left; - const u32 vram_offset_y = cmd->display_vram_top + ((interlaced && cmd->interlaced_display_interleaved) ? field : 0); + const u32 line_skip = BoolToUInt32(cmd->interlaced_display_interleaved); + const u32 src_x = is_24bit ? cmd->X : cmd->display_vram_left; const u32 skip_x = is_24bit ? (cmd->display_vram_left - cmd->X) : 0; - const u32 read_width = cmd->display_vram_width; - const u32 read_height = interlaced ? (cmd->display_vram_height / 2) : cmd->display_vram_height; + const u32 src_y = cmd->display_vram_top; + const u32 width = cmd->display_vram_width; + const u32 height = cmd->display_vram_height; + + GL_INS_FMT("Software scanout {}x{} from {},{} line_skip={}", width, height, src_x, src_y, line_skip); if (cmd->interlaced_display_enabled) { - const u32 line_skip = cmd->interlaced_display_interleaved; - if (CopyOut(vram_offset_x, vram_offset_y, skip_x, read_width, read_height, line_skip, is_24bit)) + if (CopyOut(src_x, src_y, skip_x, width, height, line_skip, is_24bit)) { - SetDisplayTexture(m_upload_texture.get(), nullptr, 0, 0, read_width, read_height); + SetDisplayTexture(m_upload_texture.get(), nullptr, 0, 0, width, height); if (is_24bit && g_settings.display_24bit_chroma_smoothing) { if (ApplyChromaSmoothing()) - Deinterlace(field, 0); + Deinterlace(field); } else { - Deinterlace(field, 0); + Deinterlace(field); } } } else { - if (CopyOut(vram_offset_x, vram_offset_y, skip_x, read_width, read_height, 0, is_24bit)) + if (CopyOut(src_x, src_y, skip_x, width, height, 0, is_24bit)) { - SetDisplayTexture(m_upload_texture.get(), nullptr, 0, 0, read_width, read_height); + SetDisplayTexture(m_upload_texture.get(), nullptr, 0, 0, width, height); if (is_24bit && g_settings.display_24bit_chroma_smoothing) ApplyChromaSmoothing(); } diff --git a/src/core/shader_cache_version.h b/src/core/shader_cache_version.h index dd969ce79..1719cb047 100644 --- a/src/core/shader_cache_version.h +++ b/src/core/shader_cache_version.h @@ -5,4 +5,4 @@ #include "common/types.h" -static constexpr u32 SHADER_CACHE_VERSION = 24; +static constexpr u32 SHADER_CACHE_VERSION = 25;