GPU: Implement fill VRAM command

This commit is contained in:
Connor McLaughlin 2019-09-14 16:43:39 +10:00
parent 46870c6a7a
commit 851ef67814
9 changed files with 82 additions and 10 deletions

View File

@ -79,7 +79,7 @@ void Program::BindDefaultAttributes()
BindAttribute(2, "a_color"); BindAttribute(2, "a_color");
} }
void Program::BindFragData(GLuint index /*= 0*/, const char* name /*= "ocol0"*/) void Program::BindFragData(GLuint index /*= 0*/, const char* name /*= "o_col0"*/)
{ {
glBindFragDataLocation(m_program_id, index, name); glBindFragDataLocation(m_program_id, index, name);
} }

View File

@ -19,7 +19,7 @@ public:
void BindAttribute(GLuint index, const char* name); void BindAttribute(GLuint index, const char* name);
void BindDefaultAttributes(); void BindDefaultAttributes();
void BindFragData(GLuint index = 0, const char* name = "ocol0"); void BindFragData(GLuint index = 0, const char* name = "o_col0");
bool Link(); bool Link();

View File

@ -116,18 +116,18 @@ void main()
uniform sampler2D samp0; uniform sampler2D samp0;
in vec2 v_tex0; in vec2 v_tex0;
out vec4 ocol0; out vec4 o_col0;
void main() void main()
{ {
ocol0 = texture(samp0, v_tex0); o_col0 = texture(samp0, v_tex0);
} }
)"; )";
if (!m_display_program.Compile(fullscreen_quad_vertex_shader, display_fragment_shader)) if (!m_display_program.Compile(fullscreen_quad_vertex_shader, display_fragment_shader))
return false; return false;
m_display_program.BindFragData(); m_display_program.BindFragData(0, "o_col0");
if (!m_display_program.Link()) if (!m_display_program.Link())
return false; return false;

View File

@ -157,6 +157,13 @@ void GPU::WriteGP0(u32 value)
case 0x00: // NOP case 0x00: // NOP
break; break;
case 0x02: // Fill Rectnagle
{
if (!HandleFillRectangleCommand())
return;
}
break;
case 0xA0: // Copy Rectangle CPU->VRAM case 0xA0: // Copy Rectangle CPU->VRAM
{ {
if (!HandleCopyRectangleCPUToVRAMCommand()) if (!HandleCopyRectangleCPUToVRAMCommand())
@ -345,6 +352,25 @@ bool GPU::HandleRenderCommand()
ZeroExtend32(words_per_vertex)); ZeroExtend32(words_per_vertex));
DispatchRenderCommand(rc, num_vertices); DispatchRenderCommand(rc, num_vertices);
UpdateDisplay();
return true;
}
bool GPU::HandleFillRectangleCommand()
{
if (m_GP0_command.size() < 3)
return false;
const u32 color = (m_GP0_command[0] & UINT32_C(0x00FFFFFF)) | UINT32_C(0xFF000000);
const u32 dst_x = m_GP0_command[1] & UINT32_C(0xFFFF);
const u32 dst_y = m_GP0_command[1] >> 16;
const u32 width = m_GP0_command[2] & UINT32_C(0xFFFF);
const u32 height = m_GP0_command[2] >> 16;
Log_DebugPrintf("Fill VRAM rectangle offset=(%u,%u), size=(%u,%u)", dst_x, dst_y, width, height);
FillVRAM(dst_x, dst_y, width, height, color);
UpdateDisplay();
return true; return true;
} }
@ -374,6 +400,7 @@ bool GPU::HandleCopyRectangleCPUToVRAMCommand()
FlushRender(); FlushRender();
UpdateVRAM(dst_x, dst_y, copy_width, copy_height, &m_GP0_command[3]); UpdateVRAM(dst_x, dst_y, copy_width, copy_height, &m_GP0_command[3]);
UpdateDisplay();
return true; return true;
} }
@ -411,6 +438,8 @@ void GPU::UpdateDisplay()
m_system->IncrementFrameNumber(); m_system->IncrementFrameNumber();
} }
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) {}
void GPU::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) {} void GPU::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) {}

View File

@ -113,11 +113,13 @@ protected:
// Rendering commands, returns false if not enough data is provided // Rendering commands, returns false if not enough data is provided
bool HandleRenderCommand(); bool HandleRenderCommand();
bool HandleFillRectangleCommand();
bool HandleCopyRectangleCPUToVRAMCommand(); bool HandleCopyRectangleCPUToVRAMCommand();
bool HandleCopyRectangleVRAMToCPUCommand(); bool HandleCopyRectangleVRAMToCPUCommand();
// Rendering in the backend // Rendering in the backend
virtual void UpdateDisplay(); virtual void UpdateDisplay();
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 DispatchRenderCommand(RenderCommand rc, u32 num_vertices); virtual void DispatchRenderCommand(RenderCommand rc, u32 num_vertices);
virtual void FlushRender(); virtual void FlushRender();

View File

@ -245,7 +245,7 @@ void main()
return ss.str(); return ss.str();
} }
std::string GPU_HW::GenerateTexturePageProgram(TextureColorMode mode) std::string GPU_HW::GenerateTexturePageFragmentShader(TextureColorMode mode)
{ {
const bool is_palette = (mode == GPU::TextureColorMode::Palette4Bit || mode == GPU::TextureColorMode::Palette8Bit); const bool is_palette = (mode == GPU::TextureColorMode::Palette4Bit || mode == GPU::TextureColorMode::Palette8Bit);
@ -304,6 +304,24 @@ void main()
return ss.str(); return ss.str();
} }
std::string GPU_HW::GenerateFillFragmentShader()
{
std::stringstream ss;
GenerateShaderHeader(ss);
ss << R"(
uniform vec4 fill_color;
out vec4 o_col0;
void main()
{
o_col0 = fill_color;
}
)";
return ss.str();
}
void GPU_HW::UpdateTexturePageTexture() {} void GPU_HW::UpdateTexturePageTexture() {}
void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)

View File

@ -19,13 +19,21 @@ protected:
u16 texcoord; u16 texcoord;
u16 padding; u16 padding;
static std::tuple<u8, u8> DecodeTexcoord(u16 texcoord) static constexpr std::tuple<u8, u8> DecodeTexcoord(u16 texcoord)
{ {
return std::make_tuple(static_cast<u8>(texcoord), static_cast<u8>(texcoord >> 8)); return std::make_tuple(static_cast<u8>(texcoord), static_cast<u8>(texcoord >> 8));
} }
static u16 EncodeTexcoord(u8 x, u8 y) { return ZeroExtend16(x) | (ZeroExtend16(y) << 8); } static constexpr u16 EncodeTexcoord(u8 x, u8 y) { return ZeroExtend16(x) | (ZeroExtend16(y) << 8); }
}; };
static constexpr std::tuple<float, float, float, float> RGBA8ToFloat(u32 rgba)
{
return std::make_tuple(static_cast<float>(rgba & UINT32_C(0xFF)) * (1.0f / 255.0f),
static_cast<float>((rgba >> 16) & UINT32_C(0xFF)) * (1.0f / 255.0f),
static_cast<float>((rgba >> 8) & UINT32_C(0xFF)) * (1.0f / 255.0f),
static_cast<float>(rgba >> 24) * (1.0f / 255.0f));
}
virtual void UpdateTexturePageTexture(); virtual void UpdateTexturePageTexture();
bool IsFlushed() const { return !m_batch_vertices.empty(); } bool IsFlushed() const { return !m_batch_vertices.empty(); }
@ -38,7 +46,8 @@ protected:
std::string GenerateVertexShader(bool textured); std::string GenerateVertexShader(bool textured);
std::string GenerateFragmentShader(bool textured, bool blending); std::string GenerateFragmentShader(bool textured, bool blending);
std::string GenerateScreenQuadVertexShader(); std::string GenerateScreenQuadVertexShader();
std::string GenerateTexturePageProgram(TextureColorMode mode); std::string GenerateTexturePageFragmentShader(TextureColorMode mode);
std::string GenerateFillFragmentShader();
std::vector<HWVertex> m_batch_vertices; std::vector<HWVertex> m_batch_vertices;
RenderCommand m_batch_command = {}; RenderCommand m_batch_command = {};

View File

@ -110,7 +110,7 @@ bool GPU_HW_OpenGL::CompilePrograms()
const std::string screen_quad_vs = GenerateScreenQuadVertexShader(); const std::string screen_quad_vs = GenerateScreenQuadVertexShader();
for (u32 palette_size = 0; palette_size < static_cast<u32>(m_texture_page_programs.size()); palette_size++) for (u32 palette_size = 0; palette_size < static_cast<u32>(m_texture_page_programs.size()); palette_size++)
{ {
const std::string fs = GenerateTexturePageProgram(static_cast<TextureColorMode>(palette_size)); const std::string fs = GenerateTexturePageFragmentShader(static_cast<TextureColorMode>(palette_size));
GL::Program& prog = m_texture_page_programs[palette_size]; GL::Program& prog = m_texture_page_programs[palette_size];
if (!prog.Compile(screen_quad_vs.c_str(), fs.c_str())) if (!prog.Compile(screen_quad_vs.c_str(), fs.c_str()))
@ -199,6 +199,19 @@ void GPU_HW_OpenGL::UpdateDisplay()
m_system->GetHostInterface()->SetDisplayTexture(m_framebuffer_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT); m_system->GetHostInterface()->SetDisplayTexture(m_framebuffer_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT);
} }
void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
{
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_fbo_id);
glEnable(GL_SCISSOR_TEST);
glScissor(x, VRAM_HEIGHT - y - height, width, height);
const auto [r, g, b, a] = RGBA8ToFloat(color);
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
}
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)
{ {
std::vector<u32> rgba_data; std::vector<u32> rgba_data;

View File

@ -18,6 +18,7 @@ public:
protected: protected:
void UpdateDisplay() override; void UpdateDisplay() 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 UpdateTexturePageTexture() override; void UpdateTexturePageTexture() override;
void FlushRender() override; void FlushRender() override;