GPU: Eliminate temporary buffer when reading back
This commit is contained in:
parent
3998b9684e
commit
9ea7a8418c
|
@ -1,5 +1,6 @@
|
||||||
#include "gpu.h"
|
#include "gpu.h"
|
||||||
#include "YBaseLib/Log.h"
|
#include "YBaseLib/Log.h"
|
||||||
|
#include "common/heap_array.h"
|
||||||
#include "common/state_wrapper.h"
|
#include "common/state_wrapper.h"
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
#include "host_interface.h"
|
#include "host_interface.h"
|
||||||
|
@ -127,16 +128,16 @@ bool GPU::DoState(StateWrapper& sw)
|
||||||
|
|
||||||
if (sw.IsReading())
|
if (sw.IsReading())
|
||||||
{
|
{
|
||||||
std::vector<u16> vram;
|
// Still need a temporary here.
|
||||||
sw.Do(&vram);
|
HeapArray<u16, VRAM_WIDTH * VRAM_HEIGHT> temp;
|
||||||
UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, vram.data());
|
sw.DoBytes(temp.data(), VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16));
|
||||||
|
UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, temp.data());
|
||||||
UpdateDisplay();
|
UpdateDisplay();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<u16> vram(VRAM_WIDTH * VRAM_HEIGHT);
|
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
|
||||||
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, vram.data());
|
sw.DoBytes(m_vram_ptr, VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16));
|
||||||
sw.Do(&vram);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !sw.HasError();
|
return !sw.HasError();
|
||||||
|
@ -693,7 +694,7 @@ void GPU::HandleGetGPUInfoCommand(u32 value)
|
||||||
|
|
||||||
void GPU::UpdateDisplay() {}
|
void GPU::UpdateDisplay() {}
|
||||||
|
|
||||||
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 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) {}
|
||||||
|
|
||||||
|
|
|
@ -288,7 +288,7 @@ protected:
|
||||||
void HandleGetGPUInfoCommand(u32 value);
|
void HandleGetGPUInfoCommand(u32 value);
|
||||||
|
|
||||||
// Rendering in the backend
|
// Rendering in the backend
|
||||||
virtual void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer);
|
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 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);
|
||||||
virtual void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height);
|
virtual void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height);
|
||||||
|
@ -303,6 +303,9 @@ protected:
|
||||||
InterruptController* m_interrupt_controller = nullptr;
|
InterruptController* m_interrupt_controller = nullptr;
|
||||||
Timers* m_timers = nullptr;
|
Timers* m_timers = nullptr;
|
||||||
|
|
||||||
|
// Pointer to VRAM, used for reads/writes. In the hardware backends, this is the shadow buffer.
|
||||||
|
u16* m_vram_ptr = nullptr;
|
||||||
|
|
||||||
union GPUSTAT
|
union GPUSTAT
|
||||||
{
|
{
|
||||||
u32 bits;
|
u32 bits;
|
||||||
|
|
|
@ -330,14 +330,24 @@ bool GPU::HandleCopyRectangleVRAMToCPUCommand(const u32*& command_ptr, u32 comma
|
||||||
// all rendering should be done first...
|
// all rendering should be done first...
|
||||||
FlushRender();
|
FlushRender();
|
||||||
|
|
||||||
// TODO: A better way of doing this..
|
// TODO: A better way of doing this.. get rid of the m_GPUREAD_buffer.
|
||||||
std::vector<u32> temp(num_words);
|
ReadVRAM(src_x, src_y, width, height);
|
||||||
ReadVRAM(src_x, src_y, width, height, temp.data());
|
for (u32 row = 0; row < height;)
|
||||||
for (const u32 bits : temp)
|
{
|
||||||
m_GPUREAD_buffer.push_back(bits);
|
const u32 row_offset = ((src_y + row++) % VRAM_HEIGHT) * VRAM_WIDTH;
|
||||||
|
for (u32 col = 0; col < width;)
|
||||||
|
{
|
||||||
|
// TODO: Handle unaligned reads...
|
||||||
|
const u32 col_offset1 = row_offset + ((src_x + col++) % VRAM_WIDTH);
|
||||||
|
const u32 col_offset2 = row_offset + ((src_x + col++) % VRAM_WIDTH);
|
||||||
|
m_GPUREAD_buffer.push_back(ZeroExtend32(m_vram_ptr[col_offset1]) | (ZeroExtend32(m_vram_ptr[col_offset2]) << 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_system->GetSettings().debugging.dump_vram_to_cpu_copies)
|
if (m_system->GetSettings().debugging.dump_vram_to_cpu_copies)
|
||||||
{
|
{
|
||||||
|
std::vector<u32> temp;
|
||||||
|
std::copy(m_GPUREAD_buffer.begin(), m_GPUREAD_buffer.end(), std::back_inserter(temp));
|
||||||
DumpVRAMToFile(SmallString::FromFormat("vram_to_cpu_copy_%u.png", s_vram_to_cpu_dump_id++), width, height,
|
DumpVRAMToFile(SmallString::FromFormat("vram_to_cpu_copy_%u.png", s_vram_to_cpu_dump_id++), width, height,
|
||||||
sizeof(u16) * width, temp.data(), true);
|
sizeof(u16) * width, temp.data(), true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,10 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
Log_SetChannel(GPU_HW);
|
Log_SetChannel(GPU_HW);
|
||||||
|
|
||||||
GPU_HW::GPU_HW() = default;
|
GPU_HW::GPU_HW() : GPU()
|
||||||
|
{
|
||||||
|
m_vram_ptr = m_vram_shadow.data();
|
||||||
|
}
|
||||||
|
|
||||||
GPU_HW::~GPU_HW() = default;
|
GPU_HW::~GPU_HW() = default;
|
||||||
|
|
||||||
|
@ -209,22 +212,6 @@ GPU_HW::BatchPrimitive GPU_HW::GetPrimitiveForCommand(RenderCommand rc)
|
||||||
return BatchPrimitive::Triangles;
|
return BatchPrimitive::Triangles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer)
|
|
||||||
{
|
|
||||||
u8* out_ptr = static_cast<u8*>(buffer);
|
|
||||||
|
|
||||||
for (u32 row = 0; row < height; row++)
|
|
||||||
{
|
|
||||||
const u32 row_offset = ((y + row) % VRAM_HEIGHT) * VRAM_WIDTH;
|
|
||||||
for (u32 col = 0; col < width; col++)
|
|
||||||
{
|
|
||||||
const u32 col_offset = row_offset + ((x + col) % VRAM_WIDTH);
|
|
||||||
std::memcpy(out_ptr, &m_vram_shadow[col_offset], sizeof(u16));
|
|
||||||
out_ptr += sizeof(u16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPU_HW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
void GPU_HW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
||||||
{
|
{
|
||||||
m_vram_dirty_rect.Include(Common::Rectangle<u32>::FromExtents(x, y, width, height));
|
m_vram_dirty_rect.Include(Common::Rectangle<u32>::FromExtents(x, y, width, height));
|
||||||
|
|
|
@ -127,7 +127,6 @@ protected:
|
||||||
|
|
||||||
bool IsFlushed() const { return m_batch_current_vertex_ptr == m_batch_start_vertex_ptr; }
|
bool IsFlushed() const { return m_batch_current_vertex_ptr == m_batch_start_vertex_ptr; }
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -584,7 +584,7 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW_D3D11::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer)
|
void GPU_HW_D3D11::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
|
||||||
{
|
{
|
||||||
// Get bounds with wrap-around handled.
|
// Get bounds with wrap-around handled.
|
||||||
const Common::Rectangle<u32> copy_rect = GetVRAMTransferBounds(x, y, width, height);
|
const Common::Rectangle<u32> copy_rect = GetVRAMTransferBounds(x, y, width, height);
|
||||||
|
@ -614,9 +614,6 @@ void GPU_HW_D3D11::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
|
|
||||||
// Feed the shadow buffer back to the output.
|
|
||||||
GPU_HW::ReadVRAM(x, y, width, height, buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW_D3D11::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
void GPU_HW_D3D11::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdateDisplay() override;
|
void UpdateDisplay() override;
|
||||||
void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) 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 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;
|
||||||
|
|
|
@ -526,7 +526,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW_OpenGL::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer)
|
void GPU_HW_OpenGL::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
|
||||||
{
|
{
|
||||||
// Get bounds with wrap-around handled.
|
// Get bounds with wrap-around handled.
|
||||||
const Common::Rectangle<u32> copy_rect = GetVRAMTransferBounds(x, y, width, height);
|
const Common::Rectangle<u32> copy_rect = GetVRAMTransferBounds(x, y, width, height);
|
||||||
|
@ -554,9 +554,6 @@ void GPU_HW_OpenGL::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer)
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
|
|
||||||
// Feed the shadow buffer back to the output.
|
|
||||||
GPU_HW::ReadVRAM(x, y, width, height, buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdateDisplay() override;
|
void UpdateDisplay() override;
|
||||||
void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) 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 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;
|
||||||
|
|
|
@ -10,6 +10,7 @@ Log_SetChannel(GPU_SW);
|
||||||
GPU_SW::GPU_SW()
|
GPU_SW::GPU_SW()
|
||||||
{
|
{
|
||||||
m_vram.fill(0);
|
m_vram.fill(0);
|
||||||
|
m_vram_ptr = m_vram.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
GPU_SW::~GPU_SW()
|
GPU_SW::~GPU_SW()
|
||||||
|
@ -37,15 +38,9 @@ void GPU_SW::Reset()
|
||||||
m_vram.fill(0);
|
m_vram.fill(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_SW::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer)
|
void GPU_SW::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
|
||||||
{
|
{
|
||||||
u16* buffer_ptr = static_cast<u16*>(buffer);
|
// No need to do anything - pointer is already up to date.
|
||||||
for (u32 yoffs = 0; yoffs < height; yoffs++)
|
|
||||||
{
|
|
||||||
u16* src_ptr = GetPixelPtr(x, y + yoffs);
|
|
||||||
std::copy_n(src_ptr, width, buffer_ptr);
|
|
||||||
buffer_ptr += width;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_SW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
void GPU_SW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
||||||
|
|
|
@ -34,7 +34,7 @@ protected:
|
||||||
u8 texcoord_x, texcoord_y;
|
u8 texcoord_x, texcoord_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) 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 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;
|
||||||
|
|
Loading…
Reference in New Issue