From 5b590d434bbdc54c16ea35a2e7284f0d26baa1d5 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 3 Aug 2024 02:06:20 +1000 Subject: [PATCH] D3D11Device: Fix blend state not applying to MRTs --- src/util/d3d11_device.h | 9 +++++++-- src/util/d3d11_pipeline.cpp | 40 ++++++++++++++++++++++++------------- src/util/gpu_device.cpp | 11 ++++++++++ src/util/gpu_device.h | 1 + 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/util/d3d11_device.h b/src/util/d3d11_device.h index ea556fd36..879ea1e45 100644 --- a/src/util/d3d11_device.h +++ b/src/util/d3d11_device.h @@ -118,9 +118,14 @@ protected: void DestroyDevice() override; private: + using BlendStateMapKey = std::pair; + struct BlendStateMapHash + { + size_t operator()(const BlendStateMapKey& key) const; + }; using RasterizationStateMap = std::unordered_map>; using DepthStateMap = std::unordered_map>; - using BlendStateMap = std::unordered_map>; + using BlendStateMap = std::unordered_map, BlendStateMapHash>; using InputLayoutMap = std::unordered_map, GPUPipeline::InputLayoutHash>; @@ -146,7 +151,7 @@ private: ComPtr GetRasterizationState(const GPUPipeline::RasterizationState& rs, Error* error); ComPtr GetDepthState(const GPUPipeline::DepthState& ds, Error* error); - ComPtr GetBlendState(const GPUPipeline::BlendState& bs, Error* error); + ComPtr GetBlendState(const GPUPipeline::BlendState& bs, u32 num_rts, Error* error); ComPtr GetInputLayout(const GPUPipeline::InputLayout& il, const D3D11Shader* vs, Error* error); bool CreateTimestampQueries(); diff --git a/src/util/d3d11_pipeline.cpp b/src/util/d3d11_pipeline.cpp index 2103189b2..f39d8f927 100644 --- a/src/util/d3d11_pipeline.cpp +++ b/src/util/d3d11_pipeline.cpp @@ -6,6 +6,7 @@ #include "d3d_common.h" #include "common/error.h" +#include "common/hash_combine.h" #include "fmt/format.h" @@ -206,11 +207,19 @@ D3D11Device::ComPtr D3D11Device::GetDepthState(const GP return dds; } -D3D11Device::ComPtr D3D11Device::GetBlendState(const GPUPipeline::BlendState& bs, Error* error) +size_t D3D11Device::BlendStateMapHash::operator()(const BlendStateMapKey& key) const +{ + size_t h = std::hash()(key.first); + hash_combine(h, key.second); + return h; +} + +D3D11Device::ComPtr D3D11Device::GetBlendState(const GPUPipeline::BlendState& bs, u32 num_rts, Error* error) { ComPtr dbs; - const auto it = m_blend_states.find(bs.key); + const std::pair key(bs.key, num_rts); + const auto it = m_blend_states.find(key); if (it != m_blend_states.end()) { dbs = it->second; @@ -243,24 +252,27 @@ D3D11Device::ComPtr D3D11Device::GetBlendState(const GPUPipeli }}; D3D11_BLEND_DESC blend_desc = {}; - D3D11_RENDER_TARGET_BLEND_DESC& tgt_desc = blend_desc.RenderTarget[0]; - tgt_desc.BlendEnable = bs.enable; - tgt_desc.RenderTargetWriteMask = bs.write_mask; - if (bs.enable) + for (u32 i = 0; i < num_rts; i++) { - tgt_desc.SrcBlend = blend_mapping[static_cast(bs.src_blend.GetValue())]; - tgt_desc.DestBlend = blend_mapping[static_cast(bs.dst_blend.GetValue())]; - tgt_desc.BlendOp = op_mapping[static_cast(bs.blend_op.GetValue())]; - tgt_desc.SrcBlendAlpha = blend_mapping[static_cast(bs.src_alpha_blend.GetValue())]; - tgt_desc.DestBlendAlpha = blend_mapping[static_cast(bs.dst_alpha_blend.GetValue())]; - tgt_desc.BlendOpAlpha = op_mapping[static_cast(bs.alpha_blend_op.GetValue())]; + D3D11_RENDER_TARGET_BLEND_DESC& tgt_desc = blend_desc.RenderTarget[i]; + tgt_desc.BlendEnable = bs.enable; + tgt_desc.RenderTargetWriteMask = bs.write_mask; + if (bs.enable) + { + tgt_desc.SrcBlend = blend_mapping[static_cast(bs.src_blend.GetValue())]; + tgt_desc.DestBlend = blend_mapping[static_cast(bs.dst_blend.GetValue())]; + tgt_desc.BlendOp = op_mapping[static_cast(bs.blend_op.GetValue())]; + tgt_desc.SrcBlendAlpha = blend_mapping[static_cast(bs.src_alpha_blend.GetValue())]; + tgt_desc.DestBlendAlpha = blend_mapping[static_cast(bs.dst_alpha_blend.GetValue())]; + tgt_desc.BlendOpAlpha = op_mapping[static_cast(bs.alpha_blend_op.GetValue())]; + } } HRESULT hr = m_device->CreateBlendState(&blend_desc, dbs.GetAddressOf()); if (FAILED(hr)) [[unlikely]] Error::SetHResult(error, "CreateBlendState() failed: ", hr); else - m_blend_states.emplace(bs.key, dbs); + m_blend_states.emplace(key, dbs); return dbs; } @@ -322,7 +334,7 @@ std::unique_ptr D3D11Device::CreatePipeline(const GPUPipeline::Grap { ComPtr rs = GetRasterizationState(config.rasterization, error); ComPtr ds = GetDepthState(config.depth, error); - ComPtr bs = GetBlendState(config.blend, error); + ComPtr bs = GetBlendState(config.blend, config.GetRenderTargetCount(), error); if (!rs || !ds || !bs) return {}; diff --git a/src/util/gpu_device.cpp b/src/util/gpu_device.cpp index 5b6829cac..66b163c69 100644 --- a/src/util/gpu_device.cpp +++ b/src/util/gpu_device.cpp @@ -167,6 +167,17 @@ void GPUPipeline::GraphicsConfig::SetTargetFormats(GPUTexture::Format color_form depth_format = depth_format_; } +u32 GPUPipeline::GraphicsConfig::GetRenderTargetCount() const +{ + u32 num_rts = 0; + for (; num_rts < static_cast(std::size(color_formats)); num_rts++) + { + if (color_formats[num_rts] == GPUTexture::Format::Unknown) + break; + } + return num_rts; +} + GPUTextureBuffer::GPUTextureBuffer(Format format, u32 size) : m_format(format), m_size_in_elements(size) { } diff --git a/src/util/gpu_device.h b/src/util/gpu_device.h index d76d54614..b574b71ea 100644 --- a/src/util/gpu_device.h +++ b/src/util/gpu_device.h @@ -413,6 +413,7 @@ public: void SetTargetFormats(GPUTexture::Format color_format, GPUTexture::Format depth_format_ = GPUTexture::Format::Unknown); + u32 GetRenderTargetCount() const; }; GPUPipeline();