GPU/HW: Track dirty area of VRAM shadow texture via drawing area

This commit is contained in:
Connor McLaughlin 2019-11-05 19:19:49 +10:00
parent 65197d4350
commit afbec85f89
9 changed files with 95 additions and 117 deletions

View File

@ -38,8 +38,10 @@ void GPU::Reset()
void GPU::SoftReset() void GPU::SoftReset()
{ {
m_GPUSTAT.bits = 0x14802000; m_GPUSTAT.bits = 0x14802000;
m_drawing_area = {}; m_drawing_area.Set(0, 0, 0, 0);
m_drawing_area_changed = true;
m_drawing_offset = {}; m_drawing_offset = {};
m_drawing_offset_changed = true;
std::memset(&m_crtc_state, 0, sizeof(m_crtc_state)); std::memset(&m_crtc_state, 0, sizeof(m_crtc_state));
m_crtc_state.regs.display_address_start = 0; m_crtc_state.regs.display_address_start = 0;
m_crtc_state.regs.horizontal_display_range = 0xC60260; m_crtc_state.regs.horizontal_display_range = 0xC60260;
@ -50,8 +52,6 @@ void GPU::SoftReset()
m_render_state.texture_page_changed = true; m_render_state.texture_page_changed = true;
UpdateGPUSTAT(); UpdateGPUSTAT();
UpdateCRTCConfig(); UpdateCRTCConfig();
UpdateDrawingArea();
UpdateDrawingOffset();
} }
bool GPU::DoState(StateWrapper& sw) bool GPU::DoState(StateWrapper& sw)
@ -115,8 +115,8 @@ bool GPU::DoState(StateWrapper& sw)
{ {
m_render_state.texture_page_changed = true; m_render_state.texture_page_changed = true;
m_render_state.texture_window_changed = true; m_render_state.texture_window_changed = true;
UpdateDrawingArea(); m_drawing_area_changed = true;
UpdateDrawingOffset(); m_drawing_offset_changed = true;
UpdateGPUSTAT(); UpdateGPUSTAT();
} }
@ -665,10 +665,6 @@ void GPU::HandleGetGPUInfoCommand(u32 value)
void GPU::UpdateDisplay() {} void GPU::UpdateDisplay() {}
void GPU::UpdateDrawingArea() {}
void GPU::UpdateDrawingOffset() {}
void GPU::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) {} void GPU::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) {}
void GPU::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) {} void GPU::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) {}

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "common/bitfield.h" #include "common/bitfield.h"
#include "common/rectangle.h"
#include "timers.h" #include "timers.h"
#include "types.h" #include "types.h"
#include <array> #include <array>
@ -289,8 +290,6 @@ protected:
// Rendering in the backend // Rendering in the backend
virtual void UpdateDisplay(); virtual void UpdateDisplay();
virtual void UpdateDrawingArea();
virtual void UpdateDrawingOffset();
virtual void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer); virtual void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer);
virtual void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color); 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);
@ -370,6 +369,21 @@ protected:
(static_cast<u8>(TextureMode::Palette4Bit) | static_cast<u8>(TextureMode::Palette8Bit))) != 0; (static_cast<u8>(TextureMode::Palette4Bit) | static_cast<u8>(TextureMode::Palette8Bit))) != 0;
} }
/// Returns a rectangle comprising the texture page area.
Common::Rectangle<u32> GetTexturePageRectangle() const
{
return Common::Rectangle<u32>::FromExtents(texture_page_x, texture_page_y, TEXTURE_PAGE_WIDTH,
TEXTURE_PAGE_HEIGHT);
}
/// Returns a rectangle comprising the texture palette area.
Common::Rectangle<u32> GetTexturePaletteRectangle() const
{
static constexpr std::array<u32, 4> palette_widths = {{16, 256, 0, 0}};
return Common::Rectangle<u32>::FromExtents(texture_palette_x, texture_palette_y,
palette_widths[static_cast<u8>(texture_mode) & 3], 1);
}
bool IsTexturePageChanged() const { return texture_page_changed; } bool IsTexturePageChanged() const { return texture_page_changed; }
void ClearTexturePageChangedFlag() { texture_page_changed = false; } void ClearTexturePageChangedFlag() { texture_page_changed = false; }
@ -384,11 +398,7 @@ protected:
void SetTextureWindow(u32 value); void SetTextureWindow(u32 value);
} m_render_state = {}; } m_render_state = {};
struct DrawingArea Common::Rectangle<u32> m_drawing_area;
{
u32 left, top;
u32 right, bottom;
} m_drawing_area = {};
struct DrawingOffset struct DrawingOffset
{ {
@ -396,6 +406,9 @@ protected:
s32 y; s32 y;
} m_drawing_offset = {}; } m_drawing_offset = {};
bool m_drawing_area_changed = false;
bool m_drawing_offset_changed = false;
struct CRTCState struct CRTCState
{ {
struct Regs struct Regs

View File

@ -110,11 +110,9 @@ bool GPU::HandleSetDrawingAreaTopLeftCommand(const u32*& command_ptr, u32 comman
Log_DebugPrintf("Set drawing area top-left: (%u, %u)", left, top); Log_DebugPrintf("Set drawing area top-left: (%u, %u)", left, top);
if (m_drawing_area.left != left || m_drawing_area.top != top) if (m_drawing_area.left != left || m_drawing_area.top != top)
{ {
FlushRender();
m_drawing_area.left = left; m_drawing_area.left = left;
m_drawing_area.top = top; m_drawing_area.top = top;
UpdateDrawingArea(); m_drawing_area_changed = true;
} }
return true; return true;
@ -129,11 +127,9 @@ bool GPU::HandleSetDrawingAreaBottomRightCommand(const u32*& command_ptr, u32 co
Log_DebugPrintf("Set drawing area bottom-right: (%u, %u)", m_drawing_area.right, m_drawing_area.bottom); Log_DebugPrintf("Set drawing area bottom-right: (%u, %u)", m_drawing_area.right, m_drawing_area.bottom);
if (m_drawing_area.right != right || m_drawing_area.bottom != bottom) if (m_drawing_area.right != right || m_drawing_area.bottom != bottom)
{ {
FlushRender();
m_drawing_area.right = right; m_drawing_area.right = right;
m_drawing_area.bottom = bottom; m_drawing_area.bottom = bottom;
UpdateDrawingArea(); m_drawing_area_changed = true;
} }
return true; return true;
@ -147,11 +143,9 @@ bool GPU::HandleSetDrawingOffsetCommand(const u32*& command_ptr, u32 command_siz
Log_DebugPrintf("Set drawing offset (%d, %d)", m_drawing_offset.x, m_drawing_offset.y); Log_DebugPrintf("Set drawing offset (%d, %d)", m_drawing_offset.x, m_drawing_offset.y);
if (m_drawing_offset.x != x || m_drawing_offset.y != y) if (m_drawing_offset.x != x || m_drawing_offset.y != y)
{ {
FlushRender();
m_drawing_offset.x = x; m_drawing_offset.x = x;
m_drawing_offset.y = y; m_drawing_offset.y = y;
UpdateDrawingOffset(); m_drawing_offset_changed = true;
} }
return true; return true;
} }

View File

@ -41,15 +41,6 @@ void GPU_HW::UpdateSettings()
m_true_color = m_system->GetSettings().gpu_true_color; m_true_color = m_system->GetSettings().gpu_true_color;
} }
void GPU_HW::UpdateDrawingOffset()
{
GPU::UpdateDrawingOffset();
m_batch_ubo_data.u_pos_offset[0] = m_drawing_offset.x;
m_batch_ubo_data.u_pos_offset[1] = m_drawing_offset.y;
m_batch_ubo_dirty = true;
}
void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command_ptr) void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command_ptr)
{ {
const u32 texpage = const u32 texpage =
@ -231,28 +222,14 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
if (m_render_state.IsTexturePageChanged()) if (m_render_state.IsTexturePageChanged())
{ {
m_render_state.ClearTexturePageChangedFlag(); m_render_state.ClearTexturePageChangedFlag();
if (m_vram_dirty_rect.Valid() && (m_render_state.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) ||
const u32 texture_page_left = m_render_state.texture_page_x; m_render_state.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect)))
const u32 texture_page_right = m_render_state.texture_page_y + TEXTURE_PAGE_WIDTH;
const u32 texture_page_top = m_render_state.texture_page_y;
const u32 texture_page_bottom = texture_page_top + TEXTURE_PAGE_HEIGHT;
const bool texture_page_overlaps =
(texture_page_left < m_drawing_area.right && texture_page_right > m_drawing_area.left &&
texture_page_top > m_drawing_area.bottom && texture_page_bottom < m_drawing_area.top);
const u32 texture_palette_left = m_render_state.texture_palette_x;
const u32 texture_palette_right = m_render_state.texture_palette_x + 256;
const bool texture_palette_overlaps =
m_render_state.IsUsingPalette() && texture_palette_left < m_drawing_area.right &&
texture_palette_right > m_drawing_area.left && m_render_state.texture_palette_y < m_drawing_area.bottom &&
m_render_state.texture_palette_y >= m_drawing_area.top;
// we only need to update the copy texture if the render area intersects with the texture page
if (texture_page_overlaps || texture_palette_overlaps)
{ {
Log_WarningPrintf("Invalidating VRAM read cache due to drawing area overlap");
if (!IsFlushed()) if (!IsFlushed())
FlushRender(); FlushRender();
InvalidateVRAMReadCache();
Log_WarningPrintf("Invalidating VRAM read cache due to drawing area overlap");
m_vram_read_texture_dirty = true;
} }
} }
@ -267,7 +244,8 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
const bool buffer_overflow = GetBatchVertexSpace() < max_added_vertices; const bool buffer_overflow = GetBatchVertexSpace() < max_added_vertices;
if (buffer_overflow || rc_primitive == BatchPrimitive::LineStrip || m_batch.texture_mode != texture_mode || if (buffer_overflow || rc_primitive == BatchPrimitive::LineStrip || m_batch.texture_mode != texture_mode ||
m_batch.transparency_mode != transparency_mode || m_batch.primitive != rc_primitive || m_batch.transparency_mode != transparency_mode || m_batch.primitive != rc_primitive ||
dithering_enable != m_batch.dithering || m_render_state.IsTextureWindowChanged()) dithering_enable != m_batch.dithering || m_drawing_area_changed || m_drawing_offset_changed ||
m_render_state.IsTextureWindowChanged())
{ {
FlushRender(); FlushRender();
} }
@ -282,6 +260,14 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
m_batch_ubo_dirty = true; m_batch_ubo_dirty = true;
} }
if (m_drawing_offset_changed)
{
m_drawing_offset_changed = false;
m_batch_ubo_data.u_pos_offset[0] = m_drawing_offset.x;
m_batch_ubo_data.u_pos_offset[1] = m_drawing_offset.y;
m_batch_ubo_dirty = true;
}
// map buffer if it's not already done // map buffer if it's not already done
if (!m_batch_current_vertex_ptr) if (!m_batch_current_vertex_ptr)
MapBatchVertexPointer(max_added_vertices); MapBatchVertexPointer(max_added_vertices);

View File

@ -102,12 +102,10 @@ protected:
static_cast<float>(rgba >> 24) * (1.0f / 255.0f)); static_cast<float>(rgba >> 24) * (1.0f / 255.0f));
} }
virtual void UpdateDrawingOffset() override;
virtual void InvalidateVRAMReadCache() = 0;
virtual void MapBatchVertexPointer(u32 required_vertices) = 0; virtual void MapBatchVertexPointer(u32 required_vertices) = 0;
void InvalidateVRAMReadTexture() { m_vram_read_texture_dirty = true; }
u32 GetBatchVertexSpace() const { return static_cast<u32>(m_batch_end_vertex_ptr - m_batch_current_vertex_ptr); } u32 GetBatchVertexSpace() const { return static_cast<u32>(m_batch_end_vertex_ptr - m_batch_current_vertex_ptr); }
u32 GetBatchVertexCount() const { return static_cast<u32>(m_batch_current_vertex_ptr - m_batch_start_vertex_ptr); } u32 GetBatchVertexCount() const { return static_cast<u32>(m_batch_current_vertex_ptr - m_batch_start_vertex_ptr); }
@ -135,6 +133,10 @@ protected:
BatchUBOData m_batch_ubo_data = {}; BatchUBOData m_batch_ubo_data = {};
bool m_batch_ubo_dirty = true; bool m_batch_ubo_dirty = true;
// Bounding box of VRAM area that the GPU has drawn into.
Common::Rectangle<u32> m_vram_dirty_rect;
bool m_vram_read_texture_dirty = false;
private: private:
static BatchPrimitive GetPrimitiveForCommand(RenderCommand rc); static BatchPrimitive GetPrimitiveForCommand(RenderCommand rc);

View File

@ -107,7 +107,7 @@ void GPU_HW_D3D11::RestoreGraphicsAPIState()
m_context->OMSetRenderTargets(1, m_vram_texture.GetD3DRTVArray(), nullptr); m_context->OMSetRenderTargets(1, m_vram_texture.GetD3DRTVArray(), nullptr);
m_context->RSSetState(m_cull_none_rasterizer_state.Get()); m_context->RSSetState(m_cull_none_rasterizer_state.Get());
SetViewport(0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight()); SetViewport(0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
m_drawing_area_changed = true; SetScissorFromDrawingArea();
m_batch_ubo_dirty = true; m_batch_ubo_dirty = true;
} }
@ -172,11 +172,6 @@ void GPU_HW_D3D11::DrawRendererStatsWindow()
ImGui::End(); ImGui::End();
} }
void GPU_HW_D3D11::InvalidateVRAMReadCache()
{
m_vram_read_texture_dirty = true;
}
void GPU_HW_D3D11::MapBatchVertexPointer(u32 required_vertices) void GPU_HW_D3D11::MapBatchVertexPointer(u32 required_vertices)
{ {
Assert(!m_batch_start_vertex_ptr); Assert(!m_batch_start_vertex_ptr);
@ -536,12 +531,8 @@ void GPU_HW_D3D11::SetDrawState(BatchRenderMode render_mode)
if (m_drawing_area_changed) if (m_drawing_area_changed)
{ {
m_drawing_area_changed = false; m_drawing_area_changed = false;
m_vram_dirty_rect.Include(m_drawing_area);
int left, top, right, bottom; SetScissorFromDrawingArea();
CalcScissorRect(&left, &top, &right, &bottom);
CD3D11_RECT rc(left, top, right, bottom);
m_context->RSSetScissorRects(1, &rc);
} }
if (m_batch_ubo_dirty) if (m_batch_ubo_dirty)
@ -549,11 +540,18 @@ void GPU_HW_D3D11::SetDrawState(BatchRenderMode render_mode)
UploadUniformBlock(&m_batch_ubo_data, sizeof(m_batch_ubo_data)); UploadUniformBlock(&m_batch_ubo_data, sizeof(m_batch_ubo_data));
m_batch_ubo_dirty = false; m_batch_ubo_dirty = false;
} }
if (m_vram_read_texture_dirty)
UpdateVRAMReadTexture();
} }
void GPU_HW_D3D11::UpdateDrawingArea() void GPU_HW_D3D11::SetScissorFromDrawingArea()
{ {
m_drawing_area_changed = true; int left, top, right, bottom;
CalcScissorRect(&left, &top, &right, &bottom);
CD3D11_RECT rc(left, top, right, bottom);
m_context->RSSetScissorRects(1, &rc);
} }
void GPU_HW_D3D11::UpdateDisplay() void GPU_HW_D3D11::UpdateDisplay()
@ -659,7 +657,7 @@ void GPU_HW_D3D11::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
DrawUtilityShader(m_fill_pixel_shader.Get(), uniforms, sizeof(uniforms)); DrawUtilityShader(m_fill_pixel_shader.Get(), uniforms, sizeof(uniforms));
RestoreGraphicsAPIState(); RestoreGraphicsAPIState();
InvalidateVRAMReadCache(); InvalidateVRAMReadTexture();
} }
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)
@ -678,7 +676,7 @@ void GPU_HW_D3D11::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* d
DrawUtilityShader(m_vram_write_pixel_shader.Get(), uniforms, sizeof(uniforms)); DrawUtilityShader(m_vram_write_pixel_shader.Get(), uniforms, sizeof(uniforms));
RestoreGraphicsAPIState(); RestoreGraphicsAPIState();
InvalidateVRAMReadCache(); InvalidateVRAMReadTexture();
m_stats.num_vram_writes++; m_stats.num_vram_writes++;
} }
@ -693,13 +691,14 @@ void GPU_HW_D3D11::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 widt
const CD3D11_BOX src_box(src_x, src_y, 0, src_x + width, src_y + height, 1); const CD3D11_BOX src_box(src_x, src_y, 0, src_x + width, src_y + height, 1);
m_context->CopySubresourceRegion(m_vram_texture, 0, dst_x, dst_y, 0, m_vram_texture, 0, &src_box); m_context->CopySubresourceRegion(m_vram_texture, 0, dst_x, dst_y, 0, m_vram_texture, 0, &src_box);
InvalidateVRAMReadCache(); InvalidateVRAMReadTexture();
} }
void GPU_HW_D3D11::UpdateVRAMReadTexture() void GPU_HW_D3D11::UpdateVRAMReadTexture()
{ {
m_stats.num_vram_read_texture_updates++; m_stats.num_vram_read_texture_updates++;
m_vram_read_texture_dirty = false; m_vram_read_texture_dirty = false;
m_vram_dirty_rect.SetInvalid();
const CD3D11_BOX src_box(0, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1); const CD3D11_BOX src_box(0, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1);
m_context->CopySubresourceRegion(m_vram_read_texture, 0, 0, 0, 0, m_vram_texture, 0, &src_box); m_context->CopySubresourceRegion(m_vram_read_texture, 0, 0, 0, 0, m_vram_texture, 0, &src_box);
@ -711,9 +710,6 @@ void GPU_HW_D3D11::FlushRender()
if (vertex_count == 0) if (vertex_count == 0)
return; return;
if (m_vram_read_texture_dirty)
UpdateVRAMReadTexture();
m_stats.num_batches++; m_stats.num_batches++;
m_stats.num_vertices += vertex_count; m_stats.num_vertices += vertex_count;

View File

@ -30,13 +30,11 @@ public:
protected: protected:
void UpdateDisplay() override; void UpdateDisplay() override;
void UpdateDrawingArea() override;
void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) override; void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) override;
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) 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) override;
void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override; void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override;
void FlushRender() override; void FlushRender() override;
void InvalidateVRAMReadCache() override;
void MapBatchVertexPointer(u32 required_vertices) override; void MapBatchVertexPointer(u32 required_vertices) override;
private: private:
@ -64,6 +62,7 @@ private:
bool CompileShaders(); bool CompileShaders();
void SetDrawState(BatchRenderMode render_mode); void SetDrawState(BatchRenderMode render_mode);
void SetScissorFromDrawingArea();
void UploadUniformBlock(const void* data, u32 data_size); void UploadUniformBlock(const void* data, u32 data_size);
void SetViewport(u32 x, u32 y, u32 width, u32 height); void SetViewport(u32 x, u32 y, u32 width, u32 height);
void SetScissor(u32 x, u32 y, u32 width, u32 height); void SetScissor(u32 x, u32 y, u32 width, u32 height);
@ -117,7 +116,5 @@ private:
GLStats m_stats = {}; GLStats m_stats = {};
GLStats m_last_stats = {}; GLStats m_last_stats = {};
bool m_vram_read_texture_dirty = true;
bool m_drawing_area_changed = true;
bool m_show_renderer_statistics = false; bool m_show_renderer_statistics = false;
}; };

View File

@ -73,9 +73,10 @@ void GPU_HW_OpenGL::RestoreGraphicsAPIState()
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
glLineWidth(static_cast<float>(m_resolution_scale)); glLineWidth(static_cast<float>(m_resolution_scale));
UpdateDrawingArea();
glBindVertexArray(m_vao_id); glBindVertexArray(m_vao_id);
SetScissorFromDrawingArea();
m_batch_ubo_dirty = true;
} }
void GPU_HW_OpenGL::UpdateSettings() void GPU_HW_OpenGL::UpdateSettings()
@ -139,11 +140,6 @@ void GPU_HW_OpenGL::DrawRendererStatsWindow()
ImGui::End(); ImGui::End();
} }
void GPU_HW_OpenGL::InvalidateVRAMReadCache()
{
m_vram_read_texture_dirty = true;
}
void GPU_HW_OpenGL::MapBatchVertexPointer(u32 required_vertices) void GPU_HW_OpenGL::MapBatchVertexPointer(u32 required_vertices)
{ {
Assert(!m_batch_start_vertex_ptr); Assert(!m_batch_start_vertex_ptr);
@ -397,7 +393,22 @@ void GPU_HW_OpenGL::SetDrawState(BatchRenderMode render_mode)
if (m_drawing_area_changed) if (m_drawing_area_changed)
{ {
m_drawing_area_changed = false; m_drawing_area_changed = false;
m_vram_dirty_rect.Include(m_drawing_area);
SetScissorFromDrawingArea();
}
if (m_batch_ubo_dirty)
{
UploadUniformBlock(&m_batch_ubo_data, sizeof(m_batch_ubo_data));
m_batch_ubo_dirty = false;
}
if (m_vram_read_texture_dirty)
UpdateVRAMReadTexture();
}
void GPU_HW_OpenGL::SetScissorFromDrawingArea()
{
int left, top, right, bottom; int left, top, right, bottom;
CalcScissorRect(&left, &top, &right, &bottom); CalcScissorRect(&left, &top, &right, &bottom);
@ -408,13 +419,6 @@ void GPU_HW_OpenGL::SetDrawState(BatchRenderMode render_mode)
Log_DebugPrintf("SetScissor: (%d-%d, %d-%d)", x, x + width, y, y + height); Log_DebugPrintf("SetScissor: (%d-%d, %d-%d)", x, x + width, y, y + height);
glScissor(x, y, width, height); glScissor(x, y, width, height);
}
if (m_batch_ubo_dirty)
{
UploadUniformBlock(&m_batch_ubo_data, sizeof(m_batch_ubo_data));
m_batch_ubo_dirty = false;
}
} }
void GPU_HW_OpenGL::UploadUniformBlock(const void* data, u32 data_size) void GPU_HW_OpenGL::UploadUniformBlock(const void* data, u32 data_size)
@ -428,11 +432,6 @@ void GPU_HW_OpenGL::UploadUniformBlock(const void* data, u32 data_size)
m_stats.num_uniform_buffer_updates++; m_stats.num_uniform_buffer_updates++;
} }
void GPU_HW_OpenGL::UpdateDrawingArea()
{
m_drawing_area_changed = true;
}
void GPU_HW_OpenGL::UpdateDisplay() void GPU_HW_OpenGL::UpdateDisplay()
{ {
GPU_HW::UpdateDisplay(); GPU_HW::UpdateDisplay();
@ -616,8 +615,8 @@ void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
glClearColor(r, g, b, a); glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
UpdateDrawingArea(); SetScissorFromDrawingArea();
InvalidateVRAMReadCache(); InvalidateVRAMReadTexture();
} }
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)
@ -700,10 +699,10 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void*
glDrawArrays(GL_TRIANGLES, 0, 3); glDrawArrays(GL_TRIANGLES, 0, 3);
UpdateDrawingArea(); SetScissorFromDrawingArea();
#endif #endif
InvalidateVRAMReadCache(); InvalidateVRAMReadTexture();
m_stats.num_vram_writes++; m_stats.num_vram_writes++;
} }
@ -726,13 +725,14 @@ void GPU_HW_OpenGL::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 wid
GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_COLOR_BUFFER_BIT, GL_NEAREST);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
InvalidateVRAMReadCache(); InvalidateVRAMReadTexture();
} }
void GPU_HW_OpenGL::UpdateVRAMReadTexture() void GPU_HW_OpenGL::UpdateVRAMReadTexture()
{ {
m_stats.num_vram_read_texture_updates++; m_stats.num_vram_read_texture_updates++;
m_vram_read_texture_dirty = false; m_vram_read_texture_dirty = false;
m_vram_dirty_rect.SetInvalid();
// TODO: Fallback blit path, and partial updates. // TODO: Fallback blit path, and partial updates.
glCopyImageSubData(m_vram_texture->GetGLId(), GL_TEXTURE_2D, 0, 0, 0, 0, m_vram_read_texture->GetGLId(), glCopyImageSubData(m_vram_texture->GetGLId(), GL_TEXTURE_2D, 0, 0, 0, 0, m_vram_read_texture->GetGLId(),
@ -745,9 +745,6 @@ void GPU_HW_OpenGL::FlushRender()
if (vertex_count == 0) if (vertex_count == 0)
return; return;
if (m_vram_read_texture_dirty)
UpdateVRAMReadTexture();
m_stats.num_batches++; m_stats.num_batches++;
m_stats.num_vertices += vertex_count; m_stats.num_vertices += vertex_count;

View File

@ -26,13 +26,11 @@ public:
protected: protected:
void UpdateDisplay() override; void UpdateDisplay() override;
void UpdateDrawingArea() override;
void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) override; void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) override;
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) 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) override;
void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override; void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override;
void FlushRender() override; void FlushRender() override;
void InvalidateVRAMReadCache() override;
void MapBatchVertexPointer(u32 required_vertices) override; void MapBatchVertexPointer(u32 required_vertices) override;
private: private:
@ -60,6 +58,7 @@ private:
bool CompilePrograms(); bool CompilePrograms();
void SetDrawState(BatchRenderMode render_mode); void SetDrawState(BatchRenderMode render_mode);
void SetScissorFromDrawingArea();
void UploadUniformBlock(const void* data, u32 data_size); void UploadUniformBlock(const void* data, u32 data_size);
// downsample texture - used for readbacks at >1xIR. // downsample texture - used for readbacks at >1xIR.
@ -86,7 +85,5 @@ private:
GLStats m_stats = {}; GLStats m_stats = {};
GLStats m_last_stats = {}; GLStats m_last_stats = {};
bool m_vram_read_texture_dirty = true;
bool m_drawing_area_changed = true;
bool m_show_renderer_statistics = false; bool m_show_renderer_statistics = false;
}; };