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