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");
}
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);
}

View file

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

View file

@ -116,18 +116,18 @@ void main()
uniform sampler2D samp0;
in vec2 v_tex0;
out vec4 ocol0;
out vec4 o_col0;
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))
return false;
m_display_program.BindFragData();
m_display_program.BindFragData(0, "o_col0");
if (!m_display_program.Link())
return false;

View file

@ -157,6 +157,13 @@ void GPU::WriteGP0(u32 value)
case 0x00: // NOP
break;
case 0x02: // Fill Rectnagle
{
if (!HandleFillRectangleCommand())
return;
}
break;
case 0xA0: // Copy Rectangle CPU->VRAM
{
if (!HandleCopyRectangleCPUToVRAMCommand())
@ -345,6 +352,25 @@ bool GPU::HandleRenderCommand()
ZeroExtend32(words_per_vertex));
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;
}
@ -374,6 +400,7 @@ bool GPU::HandleCopyRectangleCPUToVRAMCommand()
FlushRender();
UpdateVRAM(dst_x, dst_y, copy_width, copy_height, &m_GP0_command[3]);
UpdateDisplay();
return true;
}
@ -411,6 +438,8 @@ void GPU::UpdateDisplay()
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::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) {}

View file

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

View file

@ -245,7 +245,7 @@ void main()
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);
@ -304,6 +304,24 @@ void main()
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::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)

View file

@ -19,13 +19,21 @@ protected:
u16 texcoord;
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));
}
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();
bool IsFlushed() const { return !m_batch_vertices.empty(); }
@ -38,7 +46,8 @@ protected:
std::string GenerateVertexShader(bool textured);
std::string GenerateFragmentShader(bool textured, bool blending);
std::string GenerateScreenQuadVertexShader();
std::string GenerateTexturePageProgram(TextureColorMode mode);
std::string GenerateTexturePageFragmentShader(TextureColorMode mode);
std::string GenerateFillFragmentShader();
std::vector<HWVertex> m_batch_vertices;
RenderCommand m_batch_command = {};

View file

@ -110,7 +110,7 @@ bool GPU_HW_OpenGL::CompilePrograms()
const std::string screen_quad_vs = GenerateScreenQuadVertexShader();
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];
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);
}
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)
{
std::vector<u32> rgba_data;

View file

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