From 7b6d30a99459b6852f2cc08c822a4496495577ac Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Tue, 15 Dec 2020 02:19:28 +1000 Subject: [PATCH] GPU/HW: Fix possible VRAM corruption when live switching resolutions Mask bit was getting lost based on guest state. --- src/core/gpu.cpp | 19 ++++++------------- src/core/gpu.h | 2 +- src/core/gpu_commands.cpp | 8 +++++--- src/core/gpu_hw.cpp | 19 +++++++------------ src/core/gpu_hw.h | 5 +++-- src/core/gpu_hw_d3d11.cpp | 14 +++++++------- src/core/gpu_hw_d3d11.h | 2 +- src/core/gpu_hw_opengl.cpp | 22 ++++++++++++---------- src/core/gpu_hw_opengl.h | 2 +- src/core/gpu_hw_vulkan.cpp | 16 ++++++++-------- src/core/gpu_hw_vulkan.h | 2 +- src/core/gpu_sw.cpp | 4 +++- src/core/gpu_sw.h | 2 +- 13 files changed, 56 insertions(+), 61 deletions(-) diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 69af1826c..a3de0ea2d 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -213,18 +213,10 @@ bool GPU::DoState(StateWrapper& sw, bool update_display) if (sw.IsReading()) { - // Need to clear the mask bits since we want to pull it in from the copy. - const u32 old_GPUSTAT = m_GPUSTAT.bits; - m_GPUSTAT.check_mask_before_draw = false; - m_GPUSTAT.set_mask_while_drawing = false; - // Still need a temporary here. HeapArray temp; sw.DoBytes(temp.data(), VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16)); - UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, temp.data()); - - // Restore mask setting. - m_GPUSTAT.bits = old_GPUSTAT; + UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, temp.data(), false, false); UpdateCRTCConfig(); if (update_display) @@ -1224,10 +1216,10 @@ void GPU::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) } } -void GPU::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) +void GPU::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) { // Fast path when the copy is not oversized. - if ((x + width) <= VRAM_WIDTH && (y + height) <= VRAM_HEIGHT && !m_GPUSTAT.IsMaskingEnabled()) + if ((x + width) <= VRAM_WIDTH && (y + height) <= VRAM_HEIGHT && !set_mask && !check_mask) { const u16* src_ptr = static_cast(data); u16* dst_ptr = &m_vram_ptr[y * VRAM_WIDTH + x]; @@ -1241,9 +1233,10 @@ void GPU::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) else { // Slow path when we need to handle wrap-around. + // During transfer/render operations, if ((dst_pixel & mask_and) == 0) { pixel = src_pixel | mask_or } const u16* src_ptr = static_cast(data); - const u16 mask_and = m_GPUSTAT.GetMaskAND(); - const u16 mask_or = m_GPUSTAT.GetMaskOR(); + const u16 mask_and = check_mask ? 0x8000 : 0; + const u16 mask_or = set_mask ? 0x8000 : 0; for (u32 row = 0; row < height;) { diff --git a/src/core/gpu.h b/src/core/gpu.h index bc2dd43a5..7873f52a1 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -273,7 +273,7 @@ protected: // Rendering in the backend virtual void ReadVRAM(u32 x, u32 y, u32 width, u32 height); virtual void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color); - virtual void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data); + virtual void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask); virtual void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height); virtual void DispatchRenderCommand(); virtual void FlushRender(); diff --git a/src/core/gpu_commands.cpp b/src/core/gpu_commands.cpp index 6c81084be..e027d0775 100644 --- a/src/core/gpu_commands.cpp +++ b/src/core/gpu_commands.cpp @@ -512,7 +512,7 @@ void GPU::FinishVRAMWrite() if (m_blit_remaining_words == 0) { UpdateVRAM(m_vram_transfer.x, m_vram_transfer.y, m_vram_transfer.width, m_vram_transfer.height, - m_blit_buffer.data()); + m_blit_buffer.data(), m_GPUSTAT.set_mask_while_drawing, m_GPUSTAT.check_mask_before_draw); } else { @@ -530,12 +530,14 @@ void GPU::FinishVRAMWrite() const u8* blit_ptr = reinterpret_cast(m_blit_buffer.data()); if (transferred_full_rows > 0) { - UpdateVRAM(m_vram_transfer.x, m_vram_transfer.y, m_vram_transfer.width, transferred_full_rows, blit_ptr); + UpdateVRAM(m_vram_transfer.x, m_vram_transfer.y, m_vram_transfer.width, transferred_full_rows, blit_ptr, + m_GPUSTAT.set_mask_while_drawing, m_GPUSTAT.check_mask_before_draw); blit_ptr += (ZeroExtend32(m_vram_transfer.width) * transferred_full_rows) * sizeof(u16); } if (transferred_width_last_row > 0) { - UpdateVRAM(m_vram_transfer.x, m_vram_transfer.y + transferred_full_rows, transferred_width_last_row, 1, blit_ptr); + UpdateVRAM(m_vram_transfer.x, m_vram_transfer.y + transferred_full_rows, transferred_width_last_row, 1, blit_ptr, + m_GPUSTAT.set_mask_while_drawing, m_GPUSTAT.check_mask_before_draw); } } diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index d42f34955..b01c955c5 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -780,17 +780,12 @@ Common::Rectangle GPU_HW::GetVRAMTransferBounds(u32 x, u32 y, u32 width, u3 return out_rc; } -GPU_HW::VRAMWriteUBOData GPU_HW::GetVRAMWriteUBOData(u32 x, u32 y, u32 width, u32 height, u32 buffer_offset) const +GPU_HW::VRAMWriteUBOData GPU_HW::GetVRAMWriteUBOData(u32 x, u32 y, u32 width, u32 height, u32 buffer_offset, + bool set_mask, bool check_mask) const { - const VRAMWriteUBOData uniforms = {(x % VRAM_WIDTH), - (y % VRAM_HEIGHT), - ((x + width) % VRAM_WIDTH), - ((y + height) % VRAM_HEIGHT), - width, - height, - buffer_offset, - m_GPUSTAT.set_mask_while_drawing ? 0x8000u : 0x00, - GetCurrentNormalizedVertexDepth()}; + const VRAMWriteUBOData uniforms = { + (x % VRAM_WIDTH), (y % VRAM_HEIGHT), ((x + width) % VRAM_WIDTH), ((y + height) % VRAM_HEIGHT), width, + height, buffer_offset, (set_mask) ? 0x8000u : 0x00, GetCurrentNormalizedVertexDepth()}; return uniforms; } @@ -897,12 +892,12 @@ void GPU_HW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) Common::Rectangle::FromExtents(x, y, width, height).Clamped(0, 0, VRAM_WIDTH, VRAM_HEIGHT)); } -void GPU_HW::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) +void GPU_HW::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) { DebugAssert((x + width) <= VRAM_WIDTH && (y + height) <= VRAM_HEIGHT); IncludeVRAMDityRectangle(Common::Rectangle::FromExtents(x, y, width, height)); - if (m_GPUSTAT.check_mask_before_draw) + if (check_mask) { // set new vertex counter since we want this to take into consideration previous masked pixels m_current_depth++; diff --git a/src/core/gpu_hw.h b/src/core/gpu_hw.h index 583d2af94..5fc0f1554 100644 --- a/src/core/gpu_hw.h +++ b/src/core/gpu_hw.h @@ -248,7 +248,7 @@ protected: } void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override; - void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) override; + void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) override; void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override; void DispatchRenderCommand() override; void FlushRender() override; @@ -268,7 +268,8 @@ protected: bool UseVRAMCopyShader(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) const; VRAMFillUBOData GetVRAMFillUBOData(u32 x, u32 y, u32 width, u32 height, u32 color) const; - VRAMWriteUBOData GetVRAMWriteUBOData(u32 x, u32 y, u32 width, u32 height, u32 buffer_offset) const; + VRAMWriteUBOData GetVRAMWriteUBOData(u32 x, u32 y, u32 width, u32 height, u32 buffer_offset, bool set_mask, + bool check_mask) const; VRAMCopyUBOData GetVRAMCopyUBOData(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) const; /// Expands a line into two triangles. diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp index ba46706dd..3d81b47d6 100644 --- a/src/core/gpu_hw_d3d11.cpp +++ b/src/core/gpu_hw_d3d11.cpp @@ -142,7 +142,7 @@ void GPU_HW_D3D11::UpdateSettings() if (framebuffer_changed) { RestoreGraphicsAPIState(); - UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr); + UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr, false, false); UpdateDepthBufferFromMaskBit(); UpdateDisplay(); ResetGraphicsAPIState(); @@ -767,7 +767,7 @@ void GPU_HW_D3D11::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) Log_WarningPrintf("Oversized VRAM fill (%u-%u, %u-%u), CPU round trip", x, x + width, y, y + height); ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT); GPU::FillVRAM(x, y, width, height, color); - UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_shadow.data()); + UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_shadow.data(), false, false); return; } @@ -786,19 +786,19 @@ void GPU_HW_D3D11::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) RestoreGraphicsAPIState(); } -void GPU_HW_D3D11::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) +void GPU_HW_D3D11::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) { const Common::Rectangle bounds = GetVRAMTransferBounds(x, y, width, height); - GPU_HW::UpdateVRAM(bounds.left, bounds.top, bounds.GetWidth(), bounds.GetHeight(), data); + GPU_HW::UpdateVRAM(bounds.left, bounds.top, bounds.GetWidth(), bounds.GetHeight(), data, set_mask, check_mask); const u32 num_pixels = width * height; const auto map_result = m_texture_stream_buffer.Map(m_context.Get(), sizeof(u16), num_pixels * sizeof(u16)); std::memcpy(map_result.pointer, data, num_pixels * sizeof(u16)); m_texture_stream_buffer.Unmap(m_context.Get(), num_pixels * sizeof(u16)); - const VRAMWriteUBOData uniforms = GetVRAMWriteUBOData(x, y, width, height, map_result.index_aligned); - m_context->OMSetDepthStencilState( - m_GPUSTAT.check_mask_before_draw ? m_depth_test_less_state.Get() : m_depth_test_always_state.Get(), 0); + const VRAMWriteUBOData uniforms = + GetVRAMWriteUBOData(x, y, width, height, map_result.index_aligned, set_mask, check_mask); + m_context->OMSetDepthStencilState(check_mask ? m_depth_test_less_state.Get() : m_depth_test_always_state.Get(), 0); m_context->PSSetShaderResources(0, 1, m_texture_stream_buffer_srv_r16ui.GetAddressOf()); // the viewport should already be set to the full vram, so just adjust the scissor diff --git a/src/core/gpu_hw_d3d11.h b/src/core/gpu_hw_d3d11.h index 3c0fb5989..c5634d621 100644 --- a/src/core/gpu_hw_d3d11.h +++ b/src/core/gpu_hw_d3d11.h @@ -31,7 +31,7 @@ protected: void UpdateDisplay() override; void ReadVRAM(u32 x, u32 y, u32 width, u32 height) override; void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override; - void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) override; + void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) override; void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override; void UpdateVRAMReadTexture() override; void UpdateDepthBufferFromMaskBit() override; diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp index bc22de507..4f90518a7 100644 --- a/src/core/gpu_hw_opengl.cpp +++ b/src/core/gpu_hw_opengl.cpp @@ -150,7 +150,7 @@ void GPU_HW_OpenGL::UpdateSettings() if (framebuffer_changed) { RestoreGraphicsAPIState(); - UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr); + UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr, false, false); UpdateDepthBufferFromMaskBit(); UpdateDisplay(); ResetGraphicsAPIState(); @@ -258,7 +258,8 @@ void GPU_HW_OpenGL::SetCapabilities(HostDisplay* host_display) if (!m_supports_dual_source_blend) Log_WarningPrintf("Dual-source blending is not supported, this may break some mask effects."); - m_supports_geometry_shaders = GLAD_GL_VERSION_3_2 || GLAD_GL_ARB_geometry_shader4 || GLAD_GL_OES_geometry_shader || GLAD_GL_ES_VERSION_3_2; + m_supports_geometry_shaders = + GLAD_GL_VERSION_3_2 || GLAD_GL_ARB_geometry_shader4 || GLAD_GL_OES_geometry_shader || GLAD_GL_ES_VERSION_3_2; if (!m_supports_geometry_shaders) { Log_WarningPrintf("Geometry shaders are not supported, line rendering at higher resolutions may be incorrect. We " @@ -799,7 +800,7 @@ void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) Log_WarningPrintf("Oversized VRAM fill (%u-%u, %u-%u), CPU round trip", x, x + width, y, y + height); ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT); GPU::FillVRAM(x, y, width, height, color); - UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_shadow.data()); + UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_shadow.data(), false, false); return; } @@ -837,13 +838,13 @@ void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) } } -void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) +void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) { const u32 num_pixels = width * height; if (num_pixels < m_max_texture_buffer_size || m_use_ssbo_for_vram_writes) { const Common::Rectangle bounds = GetVRAMTransferBounds(x, y, width, height); - GPU_HW::UpdateVRAM(bounds.left, bounds.top, bounds.GetWidth(), bounds.GetHeight(), data); + GPU_HW::UpdateVRAM(bounds.left, bounds.top, bounds.GetWidth(), bounds.GetHeight(), data, set_mask, check_mask); const auto map_result = m_texture_stream_buffer->Map(sizeof(u16), num_pixels * sizeof(u16)); std::memcpy(map_result.pointer, data, num_pixels * sizeof(u16)); @@ -851,7 +852,7 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* m_texture_stream_buffer->Unbind(); glDisable(GL_BLEND); - glDepthFunc(m_GPUSTAT.check_mask_before_draw ? GL_GEQUAL : GL_ALWAYS); + glDepthFunc(check_mask ? GL_GEQUAL : GL_ALWAYS); m_vram_write_program.Bind(); if (m_use_ssbo_for_vram_writes) @@ -859,7 +860,8 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* else glBindTexture(GL_TEXTURE_BUFFER, m_texture_buffer_r16ui_texture); - const VRAMWriteUBOData uniforms = GetVRAMWriteUBOData(x, y, width, height, map_result.index_aligned); + const VRAMWriteUBOData uniforms = + GetVRAMWriteUBOData(x, y, width, height, map_result.index_aligned, set_mask, check_mask); UploadUniformBuffer(&uniforms, sizeof(uniforms)); // the viewport should already be set to the full vram, so just adjust the scissor @@ -879,12 +881,12 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* // CPU round trip if oversized for now. Log_WarningPrintf("Oversized VRAM update (%u-%u, %u-%u), CPU round trip", x, x + width, y, y + height); ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT); - GPU::UpdateVRAM(x, y, width, height, data); - UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_shadow.data()); + GPU::UpdateVRAM(x, y, width, height, data, set_mask, check_mask); + UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_shadow.data(), false, false); return; } - GPU_HW::UpdateVRAM(x, y, width, height, data); + GPU_HW::UpdateVRAM(x, y, width, height, data, set_mask, check_mask); const auto map_result = m_texture_stream_buffer->Map(sizeof(u32), num_pixels * sizeof(u32)); diff --git a/src/core/gpu_hw_opengl.h b/src/core/gpu_hw_opengl.h index d9528d706..8b5d87fb6 100644 --- a/src/core/gpu_hw_opengl.h +++ b/src/core/gpu_hw_opengl.h @@ -27,7 +27,7 @@ protected: void UpdateDisplay() override; void ReadVRAM(u32 x, u32 y, u32 width, u32 height) override; void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override; - void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) override; + void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) override; void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override; void UpdateVRAMReadTexture() override; void UpdateDepthBufferFromMaskBit() override; diff --git a/src/core/gpu_hw_vulkan.cpp b/src/core/gpu_hw_vulkan.cpp index 90724b8bc..7f94a6b6c 100644 --- a/src/core/gpu_hw_vulkan.cpp +++ b/src/core/gpu_hw_vulkan.cpp @@ -147,7 +147,7 @@ void GPU_HW_Vulkan::UpdateSettings() if (framebuffer_changed) { RestoreGraphicsAPIState(); - UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr); + UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr, false, false); UpdateDepthBufferFromMaskBit(); UpdateDisplay(); ResetGraphicsAPIState(); @@ -705,7 +705,8 @@ bool GPU_HW_Vulkan::CompilePipelines() gpbuilder.SetBlendAttachment( 0, true, VK_BLEND_FACTOR_ONE, m_supports_dual_source_blend ? VK_BLEND_FACTOR_SRC1_ALPHA : VK_BLEND_FACTOR_SRC_ALPHA, - (static_cast(transparency_mode) == GPUTransparencyMode::BackgroundMinusForeground && + (static_cast(transparency_mode) == + GPUTransparencyMode::BackgroundMinusForeground && static_cast(render_mode) != BatchRenderMode::TransparencyDisabled && static_cast(render_mode) != BatchRenderMode::OnlyOpaque) ? VK_BLEND_OP_REVERSE_SUBTRACT : @@ -1115,7 +1116,7 @@ void GPU_HW_Vulkan::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) Log_WarningPrintf("Oversized VRAM fill (%u-%u, %u-%u), CPU round trip", x, x + width, y, y + height); ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT); GPU::FillVRAM(x, y, width, height, color); - UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_shadow.data()); + UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_shadow.data(), false, false); return; } @@ -1140,10 +1141,10 @@ void GPU_HW_Vulkan::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) RestoreGraphicsAPIState(); } -void GPU_HW_Vulkan::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) +void GPU_HW_Vulkan::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) { const Common::Rectangle bounds = GetVRAMTransferBounds(x, y, width, height); - GPU_HW::UpdateVRAM(bounds.left, bounds.top, bounds.GetWidth(), bounds.GetHeight(), data); + GPU_HW::UpdateVRAM(bounds.left, bounds.top, bounds.GetWidth(), bounds.GetHeight(), data, set_mask, check_mask); const u32 data_size = width * height * sizeof(u16); const u32 alignment = std::max(sizeof(u16), static_cast(g_vulkan_context->GetTexelBufferAlignment())); @@ -1167,11 +1168,10 @@ void GPU_HW_Vulkan::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* BeginVRAMRenderPass(); VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer(); - const VRAMWriteUBOData uniforms = GetVRAMWriteUBOData(x, y, width, height, start_index); + const VRAMWriteUBOData uniforms = GetVRAMWriteUBOData(x, y, width, height, start_index, set_mask, check_mask); vkCmdPushConstants(cmdbuf, m_vram_write_pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(uniforms), &uniforms); - vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, - m_vram_write_pipelines[BoolToUInt8(m_GPUSTAT.check_mask_before_draw)]); + vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_vram_write_pipelines[BoolToUInt8(check_mask)]); vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_vram_write_pipeline_layout, 0, 1, &m_vram_write_descriptor_set, 0, nullptr); diff --git a/src/core/gpu_hw_vulkan.h b/src/core/gpu_hw_vulkan.h index 24a6863c0..e58ca2247 100644 --- a/src/core/gpu_hw_vulkan.h +++ b/src/core/gpu_hw_vulkan.h @@ -26,7 +26,7 @@ protected: void UpdateDisplay() override; void ReadVRAM(u32 x, u32 y, u32 width, u32 height) override; void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override; - void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) override; + void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) override; void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override; void UpdateVRAMReadTexture() override; void UpdateDepthBufferFromMaskBit() override; diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index 7fa21e39a..3fe04ad64 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -848,11 +848,13 @@ void GPU_SW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) m_backend.PushCommand(cmd); } -void GPU_SW::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) +void GPU_SW::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) { const u32 num_words = width * height; GPUBackendUpdateVRAMCommand* cmd = m_backend.NewUpdateVRAMCommand(num_words); FillBackendCommandParameters(cmd); + cmd->params.set_mask_while_drawing = set_mask; + cmd->params.check_mask_before_draw = check_mask; cmd->x = static_cast(x); cmd->y = static_cast(y); cmd->width = static_cast(width); diff --git a/src/core/gpu_sw.h b/src/core/gpu_sw.h index f9b910154..dc69693f7 100644 --- a/src/core/gpu_sw.h +++ b/src/core/gpu_sw.h @@ -24,7 +24,7 @@ public: protected: void ReadVRAM(u32 x, u32 y, u32 width, u32 height) override; void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override; - void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) override; + void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) override; void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override; template