GPU: Implement fill VRAM command
This commit is contained in:
parent
46870c6a7a
commit
851ef67814
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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) {}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 = {};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue