mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-21 21:35:38 +00:00
OpenGLDevice: Cache intermediate state
This commit is contained in:
parent
eb080834ad
commit
ce7f6128e9
|
@ -861,12 +861,20 @@ bool GPU_HW::CompilePipelines()
|
|||
}
|
||||
else
|
||||
{
|
||||
const u32 factor = (static_cast<GPUTransparencyMode>(transparency_mode) ==
|
||||
GPUTransparencyMode::HalfBackgroundPlusHalfForeground) ?
|
||||
0xFF808080u :
|
||||
0xFFFFFFFFu;
|
||||
// TODO: This isn't entirely accurate, 127.5 versus 128.
|
||||
// But if we use fbfetch on Mali, it doesn't matter.
|
||||
plconfig.blend.src_blend = GPUPipeline::BlendFunc::One;
|
||||
plconfig.blend.dst_blend = GPUPipeline::BlendFunc::ConstantColor;
|
||||
plconfig.blend.dst_blend = GPUPipeline::BlendFunc::One;
|
||||
if (static_cast<GPUTransparencyMode>(transparency_mode) ==
|
||||
GPUTransparencyMode::HalfBackgroundPlusHalfForeground ||
|
||||
static_cast<GPUTransparencyMode>(transparency_mode) ==
|
||||
GPUTransparencyMode::BackgroundPlusQuarterForeground)
|
||||
{
|
||||
plconfig.blend.dst_blend = GPUPipeline::BlendFunc::ConstantColor;
|
||||
plconfig.blend.dst_alpha_blend = GPUPipeline::BlendFunc::ConstantColor;
|
||||
plconfig.blend.constant = 0x00808080u;
|
||||
}
|
||||
|
||||
plconfig.blend.blend_op =
|
||||
(static_cast<GPUTransparencyMode>(transparency_mode) ==
|
||||
GPUTransparencyMode::BackgroundMinusForeground &&
|
||||
|
@ -874,7 +882,6 @@ bool GPU_HW::CompilePipelines()
|
|||
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque) ?
|
||||
GPUPipeline::BlendOp::ReverseSubtract :
|
||||
GPUPipeline::BlendOp::Add;
|
||||
plconfig.blend.constant = factor;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -348,6 +348,10 @@ public:
|
|||
BitField<u64, bool, 27, 1> write_a;
|
||||
BitField<u64, u8, 24, 4> write_mask;
|
||||
BitField<u64, u32, 32, 32> constant;
|
||||
|
||||
BitField<u64, u16, 1, 16> blend_factors;
|
||||
BitField<u64, u8, 17, 6> blend_ops;
|
||||
|
||||
u64 key;
|
||||
|
||||
// clang-format off
|
||||
|
|
|
@ -26,6 +26,8 @@ OpenGLDevice::OpenGLDevice()
|
|||
std::memset(&m_last_rasterization_state, 0xFF, sizeof(m_last_rasterization_state));
|
||||
std::memset(&m_last_depth_state, 0xFF, sizeof(m_last_depth_state));
|
||||
std::memset(&m_last_blend_state, 0xFF, sizeof(m_last_blend_state));
|
||||
m_last_blend_state.enable = false;
|
||||
m_last_blend_state.constant = 0;
|
||||
}
|
||||
|
||||
OpenGLDevice::~OpenGLDevice()
|
||||
|
@ -425,6 +427,7 @@ bool OpenGLDevice::CheckFeatures(bool* buggy_pbo)
|
|||
m_features.dual_source_blend =
|
||||
(max_dual_source_draw_buffers > 0) &&
|
||||
(GLAD_GL_VERSION_3_3 || GLAD_GL_ARB_blend_func_extended || GLAD_GL_EXT_blend_func_extended);
|
||||
m_features.dual_source_blend = false;
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Partial texture buffer uploads appear to be broken in macOS's OpenGL driver.
|
||||
|
|
|
@ -160,6 +160,10 @@ private:
|
|||
bool DiscardPipelineCache();
|
||||
void ClosePipelineCache();
|
||||
|
||||
void ApplyRasterizationState(GPUPipeline::RasterizationState rs);
|
||||
void ApplyDepthState(GPUPipeline::DepthState ds);
|
||||
void ApplyBlendState(GPUPipeline::BlendState bs);
|
||||
|
||||
std::unique_ptr<GL::Context> m_gl_context;
|
||||
std::unique_ptr<OpenGLFramebuffer> m_window_framebuffer;
|
||||
|
||||
|
|
|
@ -590,8 +590,12 @@ std::unique_ptr<GPUPipeline> OpenGLDevice::CreatePipeline(const GPUPipeline::Gra
|
|||
config.blend, primitives[static_cast<u8>(config.primitive)]));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE static void ApplyRasterizationState(const GPUPipeline::RasterizationState& rs)
|
||||
ALWAYS_INLINE_RELEASE void OpenGLDevice::ApplyRasterizationState(GPUPipeline::RasterizationState rs)
|
||||
{
|
||||
if (m_last_rasterization_state == rs)
|
||||
return;
|
||||
|
||||
// Only one thing, no need to check.
|
||||
if (rs.cull_mode == GPUPipeline::CullMode::None)
|
||||
{
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
@ -601,9 +605,11 @@ ALWAYS_INLINE static void ApplyRasterizationState(const GPUPipeline::Rasterizati
|
|||
glEnable(GL_CULL_FACE);
|
||||
glCullFace((rs.cull_mode == GPUPipeline::CullMode::Front) ? GL_FRONT : GL_BACK);
|
||||
}
|
||||
|
||||
m_last_rasterization_state = rs;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE static void ApplyDepthState(const GPUPipeline::DepthState& ds)
|
||||
ALWAYS_INLINE_RELEASE void OpenGLDevice::ApplyDepthState(GPUPipeline::DepthState ds)
|
||||
{
|
||||
static constexpr std::array<GLenum, static_cast<u32>(GPUPipeline::DepthFunc::MaxCount)> func_mapping = {{
|
||||
GL_NEVER, // Never
|
||||
|
@ -615,13 +621,19 @@ ALWAYS_INLINE static void ApplyDepthState(const GPUPipeline::DepthState& ds)
|
|||
GL_EQUAL, // Equal
|
||||
}};
|
||||
|
||||
if (m_last_depth_state == ds)
|
||||
return;
|
||||
|
||||
(ds.depth_test != GPUPipeline::DepthFunc::Always || ds.depth_write) ? glEnable(GL_DEPTH_TEST) :
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthFunc(func_mapping[static_cast<u8>(ds.depth_test.GetValue())]);
|
||||
glDepthMask(ds.depth_write);
|
||||
if (m_last_depth_state.depth_write != ds.depth_write)
|
||||
glDepthMask(ds.depth_write);
|
||||
|
||||
m_last_depth_state = ds;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE static void ApplyBlendState(const GPUPipeline::BlendState& bs)
|
||||
ALWAYS_INLINE_RELEASE void OpenGLDevice::ApplyBlendState(GPUPipeline::BlendState bs)
|
||||
{
|
||||
static constexpr std::array<GLenum, static_cast<u32>(GPUPipeline::BlendFunc::MaxCount)> blend_mapping = {{
|
||||
GL_ZERO, // Zero
|
||||
|
@ -649,24 +661,44 @@ ALWAYS_INLINE static void ApplyBlendState(const GPUPipeline::BlendState& bs)
|
|||
}};
|
||||
|
||||
// TODO: driver bugs
|
||||
// TODO: rdoc and look for redundant calls
|
||||
|
||||
bs.enable ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
if (bs == m_last_blend_state)
|
||||
return;
|
||||
|
||||
if (bs.enable != m_last_blend_state.enable)
|
||||
bs.enable ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
|
||||
if (bs.enable)
|
||||
{
|
||||
glBlendFuncSeparate(blend_mapping[static_cast<u8>(bs.src_blend.GetValue())],
|
||||
blend_mapping[static_cast<u8>(bs.dst_blend.GetValue())],
|
||||
blend_mapping[static_cast<u8>(bs.src_alpha_blend.GetValue())],
|
||||
blend_mapping[static_cast<u8>(bs.dst_alpha_blend.GetValue())]);
|
||||
glBlendEquationSeparate(op_mapping[static_cast<u8>(bs.blend_op.GetValue())],
|
||||
op_mapping[static_cast<u8>(bs.alpha_blend_op.GetValue())]);
|
||||
if (bs.blend_factors != m_last_blend_state.blend_factors)
|
||||
{
|
||||
glBlendFuncSeparate(blend_mapping[static_cast<u8>(bs.src_blend.GetValue())],
|
||||
blend_mapping[static_cast<u8>(bs.dst_blend.GetValue())],
|
||||
blend_mapping[static_cast<u8>(bs.src_alpha_blend.GetValue())],
|
||||
blend_mapping[static_cast<u8>(bs.dst_alpha_blend.GetValue())]);
|
||||
}
|
||||
|
||||
// TODO: cache this to avoid calls?
|
||||
glBlendColor(bs.GetConstantRed(), bs.GetConstantGreen(), bs.GetConstantBlue(), bs.GetConstantAlpha());
|
||||
if (bs.blend_ops != m_last_blend_state.blend_ops)
|
||||
{
|
||||
glBlendEquationSeparate(op_mapping[static_cast<u8>(bs.blend_op.GetValue())],
|
||||
op_mapping[static_cast<u8>(bs.alpha_blend_op.GetValue())]);
|
||||
}
|
||||
|
||||
if (bs.constant != m_last_blend_state.constant)
|
||||
glBlendColor(bs.GetConstantRed(), bs.GetConstantGreen(), bs.GetConstantBlue(), bs.GetConstantAlpha());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep old values for blend options to potentially avoid calls when re-enabling.
|
||||
bs.blend_factors.SetValue(m_last_blend_state.blend_factors);
|
||||
bs.blend_ops.SetValue(m_last_blend_state.blend_ops);
|
||||
bs.constant.SetValue(m_last_blend_state.constant);
|
||||
}
|
||||
|
||||
glColorMask(bs.write_r, bs.write_g, bs.write_b, bs.write_a);
|
||||
if (bs.write_mask != m_last_blend_state.write_mask)
|
||||
glColorMask(bs.write_r, bs.write_g, bs.write_b, bs.write_a);
|
||||
|
||||
m_last_blend_state = bs;
|
||||
}
|
||||
|
||||
void OpenGLDevice::SetPipeline(GPUPipeline* pipeline)
|
||||
|
@ -677,21 +709,10 @@ void OpenGLDevice::SetPipeline(GPUPipeline* pipeline)
|
|||
OpenGLPipeline* const P = static_cast<OpenGLPipeline*>(pipeline);
|
||||
m_current_pipeline = P;
|
||||
|
||||
if (m_last_rasterization_state != P->GetRasterizationState())
|
||||
{
|
||||
m_last_rasterization_state = P->GetRasterizationState();
|
||||
ApplyRasterizationState(m_last_rasterization_state);
|
||||
}
|
||||
if (m_last_depth_state != P->GetDepthState())
|
||||
{
|
||||
m_last_depth_state = P->GetDepthState();
|
||||
ApplyDepthState(m_last_depth_state);
|
||||
}
|
||||
if (m_last_blend_state != P->GetBlendState())
|
||||
{
|
||||
m_last_blend_state = P->GetBlendState();
|
||||
ApplyBlendState(m_last_blend_state);
|
||||
}
|
||||
ApplyRasterizationState(P->GetRasterizationState());
|
||||
ApplyDepthState(P->GetDepthState());
|
||||
ApplyBlendState(P->GetBlendState());
|
||||
|
||||
if (m_last_vao != P->GetVAO())
|
||||
{
|
||||
m_last_vao = P->GetVAO();
|
||||
|
|
Loading…
Reference in a new issue