GPU: Two-pass rendering for B-F transparency
This commit is contained in:
parent
7254d48835
commit
5627955900
|
@ -245,12 +245,14 @@ void main()
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GPU_HW::GenerateFragmentShader(bool transparent, bool textured, TextureColorMode texture_color_mode,
|
std::string GPU_HW::GenerateFragmentShader(TransparencyRenderMode transparency, bool textured,
|
||||||
bool blending)
|
TextureColorMode texture_color_mode, bool blending)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
GenerateShaderHeader(ss);
|
GenerateShaderHeader(ss);
|
||||||
DefineMacro(ss, "TRANSPARENT", transparent);
|
DefineMacro(ss, "TRANSPARENT", transparency != TransparencyRenderMode::Off);
|
||||||
|
DefineMacro(ss, "TRANSPARENT_ONLY_OPAQUE", transparency == TransparencyRenderMode::OnlyOpaque);
|
||||||
|
DefineMacro(ss, "TRANSPARENT_ONLY_TRANSPARENT", transparency == TransparencyRenderMode::OnlyTransparent);
|
||||||
DefineMacro(ss, "TEXTURED", textured);
|
DefineMacro(ss, "TEXTURED", textured);
|
||||||
DefineMacro(ss, "PALETTE",
|
DefineMacro(ss, "PALETTE",
|
||||||
textured && (texture_color_mode == GPU::TextureColorMode::Palette4Bit ||
|
textured && (texture_color_mode == GPU::TextureColorMode::Palette4Bit ||
|
||||||
|
@ -337,9 +339,19 @@ void main()
|
||||||
#if TRANSPARENT
|
#if TRANSPARENT
|
||||||
// Apply semitransparency. If not a semitransparent texel, destination alpha is ignored.
|
// Apply semitransparency. If not a semitransparent texel, destination alpha is ignored.
|
||||||
if (texcol.a != 0)
|
if (texcol.a != 0)
|
||||||
|
{
|
||||||
|
#if TRANSPARENT_ONLY_OPAQUE
|
||||||
|
discard;
|
||||||
|
#endif
|
||||||
o_col0 = vec4(color * u_transparent_alpha.x, u_transparent_alpha.y);
|
o_col0 = vec4(color * u_transparent_alpha.x, u_transparent_alpha.y);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
#if TRANSPARENT_ONLY_TRANSPARENT
|
||||||
|
discard;
|
||||||
|
#endif
|
||||||
o_col0 = vec4(color, 0.0);
|
o_col0 = vec4(color, 0.0);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
// Mask bit from texture.
|
// Mask bit from texture.
|
||||||
o_col0 = vec4(color, texcol.a);
|
o_col0 = vec4(color, texcol.a);
|
||||||
|
@ -575,4 +587,5 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadVertices(rc, num_vertices);
|
LoadVertices(rc, num_vertices);
|
||||||
|
FlushRender();
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,14 @@ protected:
|
||||||
std::vector<HWVertex> vertices;
|
std::vector<HWVertex> vertices;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class TransparencyRenderMode
|
||||||
|
{
|
||||||
|
Off,
|
||||||
|
TransparentAndOpaque,
|
||||||
|
OnlyOpaque,
|
||||||
|
OnlyTransparent
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr u32 VERTEX_BUFFER_SIZE = 1 * 1024 * 1024;
|
static constexpr u32 VERTEX_BUFFER_SIZE = 1 * 1024 * 1024;
|
||||||
static constexpr u32 MAX_BATCH_VERTEX_COUNT = VERTEX_BUFFER_SIZE / sizeof(HWVertex);
|
static constexpr u32 MAX_BATCH_VERTEX_COUNT = VERTEX_BUFFER_SIZE / sizeof(HWVertex);
|
||||||
static constexpr u32 TEXTURE_TILE_SIZE = 256;
|
static constexpr u32 TEXTURE_TILE_SIZE = 256;
|
||||||
|
@ -85,8 +93,8 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GenerateVertexShader(bool textured);
|
std::string GenerateVertexShader(bool textured);
|
||||||
std::string GenerateFragmentShader(bool transparent, bool textured, TextureColorMode texture_color_mode,
|
std::string GenerateFragmentShader(TransparencyRenderMode transparency, bool textured,
|
||||||
bool blending);
|
TextureColorMode texture_color_mode, bool blending);
|
||||||
std::string GenerateScreenQuadVertexShader();
|
std::string GenerateScreenQuadVertexShader();
|
||||||
std::string GenerateFillFragmentShader();
|
std::string GenerateFillFragmentShader();
|
||||||
std::string GenerateRGB24DecodeFragmentShader();
|
std::string GenerateRGB24DecodeFragmentShader();
|
||||||
|
|
|
@ -61,9 +61,6 @@ void GPU_HW_OpenGL::RestoreGraphicsAPIState()
|
||||||
glLineWidth(static_cast<float>(m_resolution_scale));
|
glLineWidth(static_cast<float>(m_resolution_scale));
|
||||||
UpdateDrawingArea();
|
UpdateDrawingArea();
|
||||||
|
|
||||||
m_last_transparency_enable = false;
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
|
||||||
glBindVertexArray(m_vao_id);
|
glBindVertexArray(m_vao_id);
|
||||||
}
|
}
|
||||||
|
@ -291,17 +288,17 @@ void GPU_HW_OpenGL::CreateVertexBuffer()
|
||||||
|
|
||||||
bool GPU_HW_OpenGL::CompilePrograms()
|
bool GPU_HW_OpenGL::CompilePrograms()
|
||||||
{
|
{
|
||||||
for (u32 textured = 0; textured < 2; textured++)
|
for (u32 transparent = 0; transparent < 4; transparent++)
|
||||||
{
|
{
|
||||||
for (u32 blending = 0; blending < 2; blending++)
|
for (u32 textured = 0; textured < 2; textured++)
|
||||||
{
|
{
|
||||||
for (u32 transparent = 0; transparent < 2; transparent++)
|
for (u32 format = 0; format < 3; format++)
|
||||||
{
|
{
|
||||||
for (u32 format = 0; format < 3; format++)
|
for (u32 blending = 0; blending < 2; blending++)
|
||||||
{
|
{
|
||||||
// TODO: eliminate duplicate shaders here
|
// TODO: eliminate duplicate shaders here
|
||||||
if (!CompileProgram(m_render_programs[transparent][textured][format][blending],
|
if (!CompileProgram(m_render_programs[transparent][textured][format][blending],
|
||||||
ConvertToBoolUnchecked(transparent), ConvertToBoolUnchecked(textured),
|
static_cast<TransparencyRenderMode>(transparent), ConvertToBoolUnchecked(textured),
|
||||||
static_cast<TextureColorMode>(format), ConvertToBoolUnchecked(blending)))
|
static_cast<TextureColorMode>(format), ConvertToBoolUnchecked(blending)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -329,7 +326,7 @@ bool GPU_HW_OpenGL::CompilePrograms()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_HW_OpenGL::CompileProgram(GL::Program& prog, bool transparent, bool textured,
|
bool GPU_HW_OpenGL::CompileProgram(GL::Program& prog, TransparencyRenderMode transparent, bool textured,
|
||||||
TextureColorMode texture_color_mode, bool blending)
|
TextureColorMode texture_color_mode, bool blending)
|
||||||
{
|
{
|
||||||
const std::string vs = GenerateVertexShader(textured);
|
const std::string vs = GenerateVertexShader(textured);
|
||||||
|
@ -366,10 +363,10 @@ bool GPU_HW_OpenGL::CompileProgram(GL::Program& prog, bool transparent, bool tex
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW_OpenGL::SetDrawState()
|
void GPU_HW_OpenGL::SetDrawState(TransparencyRenderMode render_mode)
|
||||||
{
|
{
|
||||||
const GL::Program& prog =
|
const GL::Program& prog =
|
||||||
m_render_programs[BoolToUInt32(m_batch.transparency_enable)][BoolToUInt32(m_batch.texture_enable)]
|
m_render_programs[static_cast<u32>(render_mode)][BoolToUInt32(m_batch.texture_enable)]
|
||||||
[static_cast<u32>(m_batch.texture_color_mode)][BoolToUInt32(m_batch.texture_blending_enable)];
|
[static_cast<u32>(m_batch.texture_color_mode)][BoolToUInt32(m_batch.texture_blending_enable)];
|
||||||
prog.Bind();
|
prog.Bind();
|
||||||
|
|
||||||
|
@ -392,25 +389,17 @@ void GPU_HW_OpenGL::SetDrawState()
|
||||||
m_vram_read_texture->Bind();
|
m_vram_read_texture->Bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_last_transparency_enable != m_batch.transparency_enable ||
|
if (render_mode == TransparencyRenderMode::Off || render_mode == TransparencyRenderMode::OnlyOpaque)
|
||||||
(m_last_transparency_enable && m_last_transparency_mode != m_batch.transparency_mode))
|
|
||||||
{
|
{
|
||||||
m_last_transparency_enable = m_batch.texture_enable;
|
glDisable(GL_BLEND);
|
||||||
m_last_transparency_mode = m_batch.transparency_mode;
|
}
|
||||||
|
else
|
||||||
if (!m_batch.transparency_enable)
|
{
|
||||||
{
|
glEnable(GL_BLEND);
|
||||||
glDisable(GL_BLEND);
|
glBlendEquationSeparate(
|
||||||
}
|
m_batch.transparency_mode == TransparencyMode::BackgroundMinusForeground ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD,
|
||||||
else
|
GL_FUNC_ADD);
|
||||||
{
|
glBlendFuncSeparate(GL_ONE, GL_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendEquationSeparate(m_batch.transparency_mode == GPU::TransparencyMode::BackgroundMinusForeground ?
|
|
||||||
GL_FUNC_REVERSE_SUBTRACT :
|
|
||||||
GL_FUNC_ADD,
|
|
||||||
GL_FUNC_ADD);
|
|
||||||
glBlendFuncSeparate(GL_ONE, GL_SRC_ALPHA, GL_ONE, GL_ZERO);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_drawing_area_changed)
|
if (m_drawing_area_changed)
|
||||||
|
@ -472,8 +461,6 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_vram_fbo);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_vram_fbo);
|
||||||
glViewport(0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight());
|
glViewport(0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight());
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
if (m_last_transparency_enable)
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -662,14 +649,26 @@ void GPU_HW_OpenGL::FlushRender()
|
||||||
m_stats.num_batches++;
|
m_stats.num_batches++;
|
||||||
m_stats.num_vertices += static_cast<u32>(m_batch.vertices.size());
|
m_stats.num_vertices += static_cast<u32>(m_batch.vertices.size());
|
||||||
|
|
||||||
SetDrawState();
|
|
||||||
|
|
||||||
Assert((m_batch.vertices.size() * sizeof(HWVertex)) <= VERTEX_BUFFER_SIZE);
|
Assert((m_batch.vertices.size() * sizeof(HWVertex)) <= VERTEX_BUFFER_SIZE);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, static_cast<GLsizei>(sizeof(HWVertex) * m_batch.vertices.size()),
|
glBufferSubData(GL_ARRAY_BUFFER, 0, static_cast<GLsizei>(sizeof(HWVertex) * m_batch.vertices.size()),
|
||||||
m_batch.vertices.data());
|
m_batch.vertices.data());
|
||||||
|
|
||||||
static constexpr std::array<GLenum, 4> gl_primitives = {{GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP}};
|
static constexpr std::array<GLenum, 4> gl_primitives = {{GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP}};
|
||||||
glDrawArrays(gl_primitives[static_cast<u8>(m_batch.primitive)], 0, static_cast<GLsizei>(m_batch.vertices.size()));
|
|
||||||
|
if (m_batch.transparency_enable && m_batch.texture_enable &&
|
||||||
|
m_batch.transparency_mode == GPU::TransparencyMode::BackgroundMinusForeground)
|
||||||
|
{
|
||||||
|
SetDrawState(TransparencyRenderMode::OnlyTransparent);
|
||||||
|
glDrawArrays(gl_primitives[static_cast<u8>(m_batch.primitive)], 0, static_cast<GLsizei>(m_batch.vertices.size()));
|
||||||
|
SetDrawState(TransparencyRenderMode::OnlyOpaque);
|
||||||
|
glDrawArrays(gl_primitives[static_cast<u8>(m_batch.primitive)], 0, static_cast<GLsizei>(m_batch.vertices.size()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetDrawState(m_batch.transparency_enable ? TransparencyRenderMode::TransparentAndOpaque :
|
||||||
|
TransparencyRenderMode::Off);
|
||||||
|
glDrawArrays(gl_primitives[static_cast<u8>(m_batch.primitive)], 0, static_cast<GLsizei>(m_batch.vertices.size()));
|
||||||
|
}
|
||||||
|
|
||||||
m_batch.vertices.clear();
|
m_batch.vertices.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,9 @@ private:
|
||||||
void CreateVertexBuffer();
|
void CreateVertexBuffer();
|
||||||
|
|
||||||
bool CompilePrograms();
|
bool CompilePrograms();
|
||||||
bool CompileProgram(GL::Program& prog, bool transparent, bool textured, TextureColorMode texture_color_mode,
|
bool CompileProgram(GL::Program& prog, TransparencyRenderMode transparent, bool textured,
|
||||||
bool blending);
|
TextureColorMode texture_color_mode, bool blending);
|
||||||
void SetDrawState();
|
void SetDrawState(TransparencyRenderMode render_mode);
|
||||||
|
|
||||||
// downsample texture - used for readbacks at >1xIR.
|
// downsample texture - used for readbacks at >1xIR.
|
||||||
std::unique_ptr<GL::Texture> m_vram_texture;
|
std::unique_ptr<GL::Texture> m_vram_texture;
|
||||||
|
@ -71,11 +71,9 @@ private:
|
||||||
GLuint m_attributeless_vao_id = 0;
|
GLuint m_attributeless_vao_id = 0;
|
||||||
|
|
||||||
bool m_vram_read_texture_dirty = true;
|
bool m_vram_read_texture_dirty = true;
|
||||||
bool m_last_transparency_enable = false;
|
|
||||||
TransparencyMode m_last_transparency_mode = TransparencyMode::BackgroundMinusForeground;
|
|
||||||
bool m_drawing_area_changed = true;
|
bool m_drawing_area_changed = true;
|
||||||
|
|
||||||
std::array<std::array<std::array<std::array<GL::Program, 2>, 3>, 2>, 2> m_render_programs;
|
std::array<std::array<std::array<std::array<GL::Program, 2>, 3>, 2>, 4> m_render_programs;
|
||||||
GL::Program m_reinterpret_rgb8_program;
|
GL::Program m_reinterpret_rgb8_program;
|
||||||
|
|
||||||
GLStats m_stats = {};
|
GLStats m_stats = {};
|
||||||
|
|
|
@ -94,9 +94,9 @@ int main(int argc, char* argv[])
|
||||||
g_pLog->SetConsoleOutputParams(true, "Pad SPU", level);
|
g_pLog->SetConsoleOutputParams(true, "Pad SPU", level);
|
||||||
g_pLog->SetFilterLevel(level);
|
g_pLog->SetFilterLevel(level);
|
||||||
#else
|
#else
|
||||||
// g_pLog->SetConsoleOutputParams(true, nullptr, LOGLEVEL_DEBUG);
|
g_pLog->SetConsoleOutputParams(true, nullptr, LOGLEVEL_DEBUG);
|
||||||
// g_pLog->SetConsoleOutputParams(true, "GPU GPU_HW_OpenGL SPU Pad DigitalController", LOGLEVEL_DEBUG);
|
// g_pLog->SetConsoleOutputParams(true, "GPU GPU_HW_OpenGL SPU Pad DigitalController", LOGLEVEL_DEBUG);
|
||||||
g_pLog->SetConsoleOutputParams(true, "GPU GPU_HW_OpenGL SPU Pad DigitalController InterruptController", LOGLEVEL_DEBUG);
|
// g_pLog->SetConsoleOutputParams(true, "GPU GPU_HW_OpenGL SPU Pad DigitalController InterruptController", LOGLEVEL_DEBUG);
|
||||||
// g_pLog->SetFilterLevel(LOGLEVEL_TRACE);
|
// g_pLog->SetFilterLevel(LOGLEVEL_TRACE);
|
||||||
g_pLog->SetFilterLevel(LOGLEVEL_DEBUG);
|
g_pLog->SetFilterLevel(LOGLEVEL_DEBUG);
|
||||||
// g_pLog->SetFilterLevel(LOGLEVEL_DEV);
|
// g_pLog->SetFilterLevel(LOGLEVEL_DEV);
|
||||||
|
|
Loading…
Reference in New Issue