From b445f59e36ef62ea0aa119286a4a9579af4b020b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 1 Aug 2025 16:26:19 +0200 Subject: [PATCH 1/5] D3D11: If debug layer requested but not available, try again without it. --- Windows/GPU/D3D11Context.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Windows/GPU/D3D11Context.cpp b/Windows/GPU/D3D11Context.cpp index f1bd509bd1..4563bb12c2 100644 --- a/Windows/GPU/D3D11Context.cpp +++ b/Windows/GPU/D3D11Context.cpp @@ -63,6 +63,14 @@ HRESULT D3D11Context::CreateTheDevice(IDXGIAdapter *adapter) { // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it hr = ptr_D3D11CreateDevice(adapter, driverType, nullptr, createDeviceFlags, (D3D_FEATURE_LEVEL *)&featureLevels[3], numFeatureLevels - 3, D3D11_SDK_VERSION, &device_, &featureLevel_, &context_); + } else if ((hr == DXGI_ERROR_SDK_COMPONENT_MISSING) && (createDeviceFlags & D3D11_CREATE_DEVICE_DEBUG)) { + // Likely no debug device available. + // This happens in debug builds if you don't install the Graphics Tools optional feature in Windows 10+. + // So, we just retry without the debug flag. + WARN_LOG(Log::G3D, "D3D11CreateDevice failed with DXGI_ERROR_SDK_COMPONENT_MISSING, retrying without debug flag."); + createDeviceFlags &= ~D3D11_CREATE_DEVICE_DEBUG; + hr = ptr_D3D11CreateDevice(adapter, driverType, nullptr, createDeviceFlags, (D3D_FEATURE_LEVEL *)featureLevels, numFeatureLevels, + D3D11_SDK_VERSION, &device_, &featureLevel_, &context_); } return hr; } From e4abbd3cae17392eab0fdf3d8c2e2404a729d1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 1 Aug 2025 17:52:38 +0200 Subject: [PATCH 2/5] DrawEngine: Fix resource lifecycle --- GPU/D3D11/DrawEngineD3D11.cpp | 38 +++++++++++++++++++++++------------ GPU/D3D11/DrawEngineD3D11.h | 4 ++-- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 7f51b78310..9bcb2a651c 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -90,19 +90,6 @@ void DrawEngineD3D11::InitDeviceObjects() { draw_->SetInvalidationCallback(std::bind(&DrawEngineD3D11::Invalidate, this, std::placeholders::_1)); } -void DrawEngineD3D11::ClearInputLayoutMap() { - inputLayoutMap_.Iterate([&](const InputLayoutKey &key, ComPtr il) { - if (il) - il.Reset(); - }); - inputLayoutMap_.Clear(); -} - -void DrawEngineD3D11::NotifyConfigChanged() { - DrawEngineCommon::NotifyConfigChanged(); - ClearInputLayoutMap(); -} - void DrawEngineD3D11::DestroyDeviceObjects() { if (draw_) { draw_->SetInvalidationCallback(InvalidationCallback()); @@ -114,6 +101,31 @@ void DrawEngineD3D11::DestroyDeviceObjects() { tessDataTransfer = nullptr; delete pushVerts_; delete pushInds_; + pushVerts_ = nullptr; + pushInds_ = nullptr; +} + +void DrawEngineD3D11::DeviceLost() { + DestroyDeviceObjects(); + draw_ = nullptr; +} + +void DrawEngineD3D11::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; + InitDeviceObjects(); +} + +void DrawEngineD3D11::ClearInputLayoutMap() { + inputLayoutMap_.Iterate([&](const InputLayoutKey &key, ComPtr il) { + if (il) + il.Reset(); + }); + inputLayoutMap_.Clear(); +} + +void DrawEngineD3D11::NotifyConfigChanged() { + DrawEngineCommon::NotifyConfigChanged(); + ClearInputLayoutMap(); } struct DeclTypeInfo { diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index e9838f0319..10e7380990 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -57,8 +57,8 @@ public: DrawEngineD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context); ~DrawEngineD3D11(); - void DeviceLost() override { draw_ = nullptr; } - void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } + void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; void SetShaderManager(ShaderManagerD3D11 *shaderManager) { shaderManager_ = shaderManager; From e0d9edc077f03155f6cb346107c3d5cc165996b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 1 Aug 2025 17:57:52 +0200 Subject: [PATCH 3/5] TextureCacheD3D11: Fix resource lifecycle --- GPU/D3D11/GPU_D3D11.cpp | 3 --- GPU/D3D11/TextureCacheD3D11.cpp | 16 ++++++++++++++++ GPU/D3D11/TextureCacheD3D11.h | 5 +++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index d59b24850a..4c3fffbeb2 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -76,7 +76,6 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } void GPU_D3D11::FinishInitOnMainThread() { - textureCacheD3D11_->InitDeviceObjects(); stockD3D11.Create(device_); } @@ -111,14 +110,12 @@ void GPU_D3D11::DeviceLost() { // FBOs appear to survive? Or no? shaderManager_->ClearShaders(); drawEngine_.ClearInputLayoutMap(); - textureCache_->Clear(false); GPUCommonHW::DeviceLost(); } void GPU_D3D11::DeviceRestore(Draw::DrawContext *draw) { GPUCommonHW::DeviceRestore(draw); - // Nothing needed. } void GPU_D3D11::BeginHostFrame() { diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index c62ed66a6f..e4d33a8b87 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -140,6 +140,7 @@ TextureCacheD3D11::TextureCacheD3D11(Draw::DrawContext *draw, Draw2D *draw2D) TextureCacheD3D11::~TextureCacheD3D11() { Clear(true); + DestroyDeviceObjects(); } void TextureCacheD3D11::InitDeviceObjects() { @@ -148,6 +149,21 @@ void TextureCacheD3D11::InitDeviceObjects() { _dbg_assert_(SUCCEEDED(hr)); } +void TextureCacheD3D11::DestroyDeviceObjects() { + depalConstants_.Reset(); +} + +void TextureCacheD3D11::DeviceLost() { + Clear(false); + DestroyDeviceObjects(); + draw_ = nullptr; +} + +void TextureCacheD3D11::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; + InitDeviceObjects(); +} + void TextureCacheD3D11::SetFramebufferManager(FramebufferManagerD3D11 *fbManager) { framebufferManager_ = fbManager; } diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 124cdd705c..1e366156a3 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -55,10 +55,11 @@ public: bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; - void DeviceLost() override { draw_ = nullptr; } - void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } + void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; void InitDeviceObjects(); + void DestroyDeviceObjects(); protected: void BindTexture(TexCacheEntry *entry) override; From a5aac9c3868167eff92e101ff0dd338ab551a077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 1 Aug 2025 17:59:33 +0200 Subject: [PATCH 4/5] D3D11 stock objects: Remove unused items --- GPU/D3D11/D3D11Util.cpp | 43 ----------------------------------------- GPU/D3D11/D3D11Util.h | 6 ------ 2 files changed, 49 deletions(-) diff --git a/GPU/D3D11/D3D11Util.cpp b/GPU/D3D11/D3D11Util.cpp index fe63c99653..ce0bbd0b5b 100644 --- a/GPU/D3D11/D3D11Util.cpp +++ b/GPU/D3D11/D3D11Util.cpp @@ -109,38 +109,7 @@ HRESULT CreateGeometryShaderD3D11(ID3D11Device *device, const char *code, size_t } void StockObjectsD3D11::Create(ID3D11Device *device) { - D3D11_BLEND_DESC blend_desc{}; - blend_desc.RenderTarget[0].BlendEnable = false; - blend_desc.IndependentBlendEnable = false; - for (int i = 0; i < 16; i++) { - blend_desc.RenderTarget[0].RenderTargetWriteMask = i; - ASSERT_SUCCESS(device->CreateBlendState(&blend_desc, &blendStateDisabledWithColorMask[i])); - } - - D3D11_DEPTH_STENCIL_DESC depth_desc{}; - depth_desc.DepthEnable = FALSE; - ASSERT_SUCCESS(device->CreateDepthStencilState(&depth_desc, &depthStencilDisabled)); - depth_desc.StencilEnable = TRUE; - depth_desc.StencilReadMask = 0xFF; - depth_desc.StencilWriteMask = 0xFF; - depth_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; - depth_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; - depth_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; - depth_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - depth_desc.BackFace = depth_desc.FrontFace; - ASSERT_SUCCESS(device->CreateDepthStencilState(&depth_desc, &depthDisabledStencilWrite)); - - D3D11_RASTERIZER_DESC raster_desc{}; - raster_desc.FillMode = D3D11_FILL_SOLID; - raster_desc.CullMode = D3D11_CULL_NONE; - raster_desc.ScissorEnable = FALSE; - raster_desc.DepthClipEnable = TRUE; // the default! FALSE is unsupported on D3D11 level 9 - ASSERT_SUCCESS(device->CreateRasterizerState(&raster_desc, &rasterStateNoCull)); - D3D11_SAMPLER_DESC sampler_desc{}; - sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; for (int i = 0; i < 4; i++) @@ -149,27 +118,15 @@ void StockObjectsD3D11::Create(ID3D11Device *device) { sampler_desc.MaxLOD = FLT_MAX; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 1; - ASSERT_SUCCESS(device->CreateSamplerState(&sampler_desc, &samplerPoint2DWrap)); - sampler_desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; - ASSERT_SUCCESS(device->CreateSamplerState(&sampler_desc, &samplerLinear2DWrap)); sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; ASSERT_SUCCESS(device->CreateSamplerState(&sampler_desc, &samplerPoint2DClamp)); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; ASSERT_SUCCESS(device->CreateSamplerState(&sampler_desc, &samplerLinear2DClamp)); } void StockObjectsD3D11::Destroy() { - for (int i = 0; i < 16; i++) { - blendStateDisabledWithColorMask[i].Reset(); - } - depthStencilDisabled.Reset(); - depthDisabledStencilWrite.Reset(); - rasterStateNoCull.Reset(); - samplerPoint2DWrap.Reset(); - samplerLinear2DWrap.Reset(); samplerPoint2DClamp.Reset(); samplerLinear2DClamp.Reset(); } diff --git a/GPU/D3D11/D3D11Util.h b/GPU/D3D11/D3D11Util.h index 99c338f6b1..f38639ff4e 100644 --- a/GPU/D3D11/D3D11Util.h +++ b/GPU/D3D11/D3D11Util.h @@ -85,12 +85,6 @@ public: void Create(ID3D11Device *device); void Destroy(); - Microsoft::WRL::ComPtr depthStencilDisabled; - Microsoft::WRL::ComPtr depthDisabledStencilWrite; - Microsoft::WRL::ComPtr blendStateDisabledWithColorMask[16]; - Microsoft::WRL::ComPtr rasterStateNoCull; - Microsoft::WRL::ComPtr samplerPoint2DWrap; - Microsoft::WRL::ComPtr samplerLinear2DWrap; Microsoft::WRL::ComPtr samplerPoint2DClamp; Microsoft::WRL::ComPtr samplerLinear2DClamp; }; From 77e894c64dae90df79116f3f8293daf44f00f9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 1 Aug 2025 18:20:44 +0200 Subject: [PATCH 5/5] Fix more D3D11 lifecycle problems. Removed some ComPtr that got in the way --- GPU/Common/TextureCacheCommon.cpp | 1 - GPU/D3D11/D3D11Util.cpp | 25 --------------------- GPU/D3D11/D3D11Util.h | 11 --------- GPU/D3D11/DrawEngineD3D11.cpp | 37 ++++++++++++++++++++++++++----- GPU/D3D11/DrawEngineD3D11.h | 27 +++++++++++----------- GPU/D3D11/GPU_D3D11.cpp | 5 ----- GPU/D3D11/GPU_D3D11.h | 4 +--- GPU/D3D11/ShaderManagerD3D11.cpp | 31 ++++++++++++++++++++++---- GPU/D3D11/ShaderManagerD3D11.h | 7 ++++-- GPU/D3D11/StateMappingD3D11.cpp | 16 ++++++------- GPU/D3D11/TextureCacheD3D11.cpp | 25 ++++++++++++++++++--- GPU/D3D11/TextureCacheD3D11.h | 9 ++++++-- 12 files changed, 116 insertions(+), 82 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 259406e7ec..9cb29179e3 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2533,7 +2533,6 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) { void TextureCacheCommon::Clear(bool delete_them) { textureShaderCache_->Clear(); - ForgetLastTexture(); for (TexCache::iterator iter = cache_.begin(); iter != cache_.end(); ++iter) { ReleaseTexture(iter->second.get(), delete_them); } diff --git a/GPU/D3D11/D3D11Util.cpp b/GPU/D3D11/D3D11Util.cpp index ce0bbd0b5b..d2cc4c5556 100644 --- a/GPU/D3D11/D3D11Util.cpp +++ b/GPU/D3D11/D3D11Util.cpp @@ -107,28 +107,3 @@ HRESULT CreateGeometryShaderD3D11(ID3D11Device *device, const char *code, size_t return device->CreateGeometryShader(byteCode.data(), byteCode.size(), nullptr, ppGeometryShader); } - -void StockObjectsD3D11::Create(ID3D11Device *device) { - D3D11_SAMPLER_DESC sampler_desc{}; - sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; - sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; - for (int i = 0; i < 4; i++) - sampler_desc.BorderColor[i] = 1.0f; - sampler_desc.MinLOD = -FLT_MAX; - sampler_desc.MaxLOD = FLT_MAX; - sampler_desc.MipLODBias = 0.0f; - sampler_desc.MaxAnisotropy = 1; - sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - ASSERT_SUCCESS(device->CreateSamplerState(&sampler_desc, &samplerPoint2DClamp)); - sampler_desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; - ASSERT_SUCCESS(device->CreateSamplerState(&sampler_desc, &samplerLinear2DClamp)); -} - -void StockObjectsD3D11::Destroy() { - samplerPoint2DClamp.Reset(); - samplerLinear2DClamp.Reset(); -} - -StockObjectsD3D11 stockD3D11; diff --git a/GPU/D3D11/D3D11Util.h b/GPU/D3D11/D3D11Util.h index f38639ff4e..d5d52b9fef 100644 --- a/GPU/D3D11/D3D11Util.h +++ b/GPU/D3D11/D3D11Util.h @@ -80,17 +80,6 @@ HRESULT CreatePixelShaderD3D11(ID3D11Device *device, const char *code, size_t co HRESULT CreateComputeShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, D3D_FEATURE_LEVEL featureLevel, UINT flags, ID3D11ComputeShader **); HRESULT CreateGeometryShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, D3D_FEATURE_LEVEL featureLevel, UINT flags, ID3D11GeometryShader **); -class StockObjectsD3D11 { -public: - void Create(ID3D11Device *device); - void Destroy(); - - Microsoft::WRL::ComPtr samplerPoint2DClamp; - Microsoft::WRL::ComPtr samplerLinear2DClamp; -}; - #define ASSERT_SUCCESS(x) \ if (!SUCCEEDED((x))) \ Crash(); - -extern StockObjectsD3D11 stockD3D11; diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 9bcb2a651c..6ea1321aba 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -103,6 +103,33 @@ void DrawEngineD3D11::DestroyDeviceObjects() { delete pushInds_; pushVerts_ = nullptr; pushInds_ = nullptr; + + // Clear state caches. + blendCache_.Iterate([&](const uint64_t &key, ID3D11BlendState *state) { + state->Release(); + }); + blendCache_.Clear(); + blendCache1_.Iterate([&](const uint64_t &key, ID3D11BlendState1 *state) { + state->Release(); + }); + blendCache1_.Clear(); + depthStencilCache_.Iterate([&](const uint64_t &key, ID3D11DepthStencilState *state) { + state->Release(); + }); + depthStencilCache_.Clear(); + rasterCache_.Iterate([&](const uint32_t &key, ID3D11RasterizerState *state) { + state->Release(); + }); + rasterCache_.Clear(); + inputLayoutMap_.Iterate([&](const InputLayoutKey &key, ID3D11InputLayout *state) { + state->Release(); + }); + inputLayoutMap_.Clear(); + + blendState_ = nullptr; + blendState1_ = nullptr; + rasterState_ = nullptr; + depthStencilState_ = nullptr; } void DrawEngineD3D11::DeviceLost() { @@ -166,9 +193,9 @@ HRESULT DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshader, const De // TODO: Instead of one for each vshader, we can reduce it to one for each type of shader // that reads TEXCOORD or not, etc. Not sure if worth it. const InputLayoutKey key{ vshader, decFmt.id }; - ComPtr inputLayout; + ID3D11InputLayout *inputLayout; if (inputLayoutMap_.Get(key, &inputLayout)) { - *ppInputLayout = inputLayout.Detach(); + *ppInputLayout = inputLayout; return S_OK; } else { D3D11_INPUT_ELEMENT_DESC VertexElements[8]; @@ -224,7 +251,7 @@ HRESULT DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshader, const De // Add it to map inputLayoutMap_.Insert(key, inputLayout); - *ppInputLayout = inputLayout.Detach(); + *ppInputLayout = inputLayout; return hr; } } @@ -441,12 +468,12 @@ void DrawEngineD3D11::Flush() { // We really do need a vertex layout for each vertex shader (or at least check its ID bits for what inputs it uses)! // Some vertex shaders ignore one of the inputs, and then the layout created from it will lack it, which will be a problem for others. InputLayoutKey key{ vshader, 0xFFFFFFFF }; // Let's use 0xFFFFFFFF to signify TransformedVertex - ComPtr layout; + ID3D11InputLayout *layout; if (!inputLayoutMap_.Get(key, &layout)) { ASSERT_SUCCESS(device_->CreateInputLayout(TransformedVertexElements, ARRAY_SIZE(TransformedVertexElements), vshader->bytecode().data(), vshader->bytecode().size(), &layout)); inputLayoutMap_.Insert(key, layout); } - context_->IASetInputLayout(layout.Get()); + context_->IASetInputLayout(layout); context_->IASetPrimitiveTopology(d3d11prim[prim]); UINT stride = sizeof(TransformedVertex); diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index 10e7380990..fcb00b3a3c 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -110,7 +110,7 @@ private: } }; - DenseHashMap> inputLayoutMap_; + DenseHashMap inputLayoutMap_; // Other ShaderManagerD3D11 *shaderManager_ = nullptr; @@ -118,27 +118,28 @@ private: FramebufferManagerD3D11 *framebufferManager_ = nullptr; // Pushbuffers - PushBufferD3D11 *pushVerts_; - PushBufferD3D11 *pushInds_; + PushBufferD3D11 *pushVerts_ = nullptr; + PushBufferD3D11 *pushInds_ = nullptr; - // D3D11 state object caches. - DenseHashMap> blendCache_; - DenseHashMap> blendCache1_; - DenseHashMap> depthStencilCache_; - DenseHashMap> rasterCache_; + // D3D11 state object caches. Previously had smart pointers but they were harder to deal with. + DenseHashMap blendCache_; + DenseHashMap blendCache1_; + DenseHashMap depthStencilCache_; + DenseHashMap rasterCache_; // Keep the depth state between ApplyDrawState and ApplyDrawStateLate - Microsoft::WRL::ComPtr rasterState_; - Microsoft::WRL::ComPtr blendState_; - Microsoft::WRL::ComPtr blendState1_; - Microsoft::WRL::ComPtr depthStencilState_; + // These do not hold ownership. + ID3D11BlendState *blendState_ = nullptr; + ID3D11BlendState1 *blendState1_ = nullptr; + ID3D11DepthStencilState *depthStencilState_ = nullptr; + ID3D11RasterizerState *rasterState_ = nullptr; // State keys D3D11StateKeys keys_{}; D3D11DynamicState dynState_{}; // Hardware tessellation - TessellationDataTransferD3D11 *tessDataTransferD3D11; + TessellationDataTransferD3D11 *tessDataTransferD3D11 = nullptr; int lastRenderStepId_ = -1; }; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 4c3fffbeb2..606053044c 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -75,12 +75,7 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) textureCache_->NotifyConfigChanged(); } -void GPU_D3D11::FinishInitOnMainThread() { - stockD3D11.Create(device_); -} - GPU_D3D11::~GPU_D3D11() { - stockD3D11.Destroy(); } u32 GPU_D3D11::CheckGPUFeatures() const { diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 007607f883..23aaa9900b 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -34,12 +34,10 @@ public: GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~GPU_D3D11(); - void FinishInitOnMainThread() override; - u32 CheckGPUFeatures() const override; void GetStats(char *buffer, size_t bufsize) override; - void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. + void DeviceLost() override; // Destroy all device objects. void DeviceRestore(Draw::DrawContext *draw) override; protected: diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index 3dfd11ce4b..b79e42d56b 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -88,7 +88,18 @@ ShaderManagerD3D11::ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *de static_assert(sizeof(ub_lights) <= 512, "ub_lights grew too big"); static_assert(sizeof(ub_bones) <= 384, "ub_bones grew too big"); - D3D11_BUFFER_DESC desc{sizeof(ub_base), D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE }; + InitDeviceObjects(); +} + +ShaderManagerD3D11::~ShaderManagerD3D11() { + ClearShaders(); + delete[] codeBuffer_; + DestroyDeviceObjects(); +} + +void ShaderManagerD3D11::InitDeviceObjects() { + + D3D11_BUFFER_DESC desc{sizeof(ub_base), D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE}; ASSERT_SUCCESS(device_->CreateBuffer(&desc, nullptr, &push_base)); desc.ByteWidth = sizeof(ub_lights); ASSERT_SUCCESS(device_->CreateBuffer(&desc, nullptr, &push_lights)); @@ -96,9 +107,21 @@ ShaderManagerD3D11::ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *de ASSERT_SUCCESS(device_->CreateBuffer(&desc, nullptr, &push_bones)); } -ShaderManagerD3D11::~ShaderManagerD3D11() { - ClearShaders(); - delete[] codeBuffer_; +void ShaderManagerD3D11::DestroyDeviceObjects() { + push_base.Reset(); + push_lights.Reset(); + push_bones.Reset(); + Clear(); +} + +void ShaderManagerD3D11::DeviceLost() { + DestroyDeviceObjects(); + draw_ = nullptr; +} + +void ShaderManagerD3D11::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; + InitDeviceObjects(); } void ShaderManagerD3D11::Clear() { diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index f773ee27f1..35ee3c927d 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -90,8 +90,11 @@ public: void ClearShaders() override; void DirtyLastShader() override; - void DeviceLost() override { draw_ = nullptr; } - void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } + void InitDeviceObjects(); + void DestroyDeviceObjects(); + + void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; int GetNumVertexShaders() const { return (int)vsCache_.size(); } int GetNumFragmentShaders() const { return (int)fsCache_.size(); } diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index bf2ffa9b47..4f5c9be683 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -356,7 +356,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { // There might have been interactions between depth and blend above. if (gstate_c.IsDirty(DIRTY_BLEND_STATE)) { if (!device1_) { - ComPtr bs; + ID3D11BlendState *bs; if (!blendCache_.Get(keys_.blend.value, &bs) || !bs) { D3D11_BLEND_DESC desc{}; D3D11_RENDER_TARGET_BLEND_DESC &rt = desc.RenderTarget[0]; @@ -373,7 +373,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { } blendState_ = bs; } else { - ComPtr bs1; + ID3D11BlendState1 *bs1; if (!blendCache1_.Get(keys_.blend.value, &bs1) || !bs1) { D3D11_BLEND_DESC1 desc1{}; D3D11_RENDER_TARGET_BLEND_DESC1 &rt = desc1.RenderTarget[0]; @@ -395,7 +395,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { } if (gstate_c.IsDirty(DIRTY_RASTER_STATE)) { - ComPtr rs; + ID3D11RasterizerState *rs; if (!rasterCache_.Get(keys_.raster.value, &rs) || !rs) { D3D11_RASTERIZER_DESC desc{}; desc.CullMode = (D3D11_CULL_MODE)(keys_.raster.cullMode); @@ -410,7 +410,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { } if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) { - ComPtr ds; + ID3D11DepthStencilState *ds; if (!depthStencilCache_.Get(keys_.depthStencil.value, &ds) || !ds) { D3D11_DEPTH_STENCIL_DESC desc{}; desc.DepthEnable = keys_.depthStencil.depthTestEnable; @@ -446,20 +446,20 @@ void DrawEngineD3D11::ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRe draw_->SetScissorRect(dynState_.scissor.left, dynState_.scissor.top, dynState_.scissor.right - dynState_.scissor.left, dynState_.scissor.bottom - dynState_.scissor.top); } if (gstate_c.IsDirty(DIRTY_RASTER_STATE)) { - context_->RSSetState(rasterState_.Get()); + context_->RSSetState(rasterState_); } if (gstate_c.IsDirty(DIRTY_BLEND_STATE)) { // Need to do this AFTER ApplyTexture because the process of depalettization can ruin the blend state. float blendColor[4]; Uint8x4ToFloat4(blendColor, dynState_.blendColor); if (device1_) { - context1_->OMSetBlendState(blendState1_.Get(), blendColor, 0xFFFFFFFF); + context1_->OMSetBlendState(blendState1_, blendColor, 0xFFFFFFFF); } else { - context_->OMSetBlendState(blendState_.Get(), blendColor, 0xFFFFFFFF); + context_->OMSetBlendState(blendState_, blendColor, 0xFFFFFFFF); } } if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE) || applyStencilRef) { - context_->OMSetDepthStencilState(depthStencilState_.Get(), applyStencilRef ? stencilRef : dynState_.stencilRef); + context_->OMSetDepthStencilState(depthStencilState_, applyStencilRef ? stencilRef : dynState_.stencilRef); } gstate_c.Clean(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_BLEND_STATE); gstate_c.Dirty(dirtyRequiresRecheck_); diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index e4d33a8b87..a78d2255f8 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -147,10 +147,29 @@ void TextureCacheD3D11::InitDeviceObjects() { D3D11_BUFFER_DESC desc{ sizeof(DepthPushConstants), D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE }; HRESULT hr = device_->CreateBuffer(&desc, nullptr, &depalConstants_); _dbg_assert_(SUCCEEDED(hr)); + D3D11_SAMPLER_DESC sampler_desc{}; + sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; + for (int i = 0; i < 4; i++) + sampler_desc.BorderColor[i] = 1.0f; + sampler_desc.MinLOD = -FLT_MAX; + sampler_desc.MaxLOD = FLT_MAX; + sampler_desc.MipLODBias = 0.0f; + sampler_desc.MaxAnisotropy = 1; + sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + ASSERT_SUCCESS(device_->CreateSamplerState(&sampler_desc, &samplerPoint2DClamp_)); + sampler_desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + ASSERT_SUCCESS(device_->CreateSamplerState(&sampler_desc, &samplerLinear2DClamp_)); } void TextureCacheD3D11::DestroyDeviceObjects() { depalConstants_.Reset(); + samplerPoint2DClamp_.Reset(); + samplerLinear2DClamp_.Reset(); + lastBoundTexture_ = D3D11_INVALID_TEX; + samplerCache_.Destroy(); } void TextureCacheD3D11::DeviceLost() { @@ -238,14 +257,14 @@ void TextureCacheD3D11::BindTexture(TexCacheEntry *entry) { int maxLevel = (entry->status & TexCacheEntry::STATUS_NO_MIPS) ? 0 : entry->maxLevel; SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry); ComPtr state; - samplerCache_.GetOrCreateSampler(device_.Get(), samplerKey, &state); + samplerCache_.GetOrCreateSampler(device_, samplerKey, &state); context_->PSSetSamplers(0, 1, state.GetAddressOf()); gstate_c.SetUseShaderDepal(ShaderDepalMode::OFF); } void TextureCacheD3D11::ApplySamplingParams(const SamplerCacheKey &key) { ComPtr state; - samplerCache_.GetOrCreateSampler(device_.Get(), key, &state); + samplerCache_.GetOrCreateSampler(device_, key, &state); context_->PSSetSamplers(0, 1, state.GetAddressOf()); } @@ -256,7 +275,7 @@ void TextureCacheD3D11::Unbind() { void TextureCacheD3D11::BindAsClutTexture(Draw::Texture *tex, bool smooth) { ID3D11ShaderResourceView *clutTexture = (ID3D11ShaderResourceView *)draw_->GetNativeObject(Draw::NativeObject::TEXTURE_VIEW, tex); context_->PSSetShaderResources(TEX_SLOT_CLUT, 1, &clutTexture); - context_->PSSetSamplers(3, 1, smooth ? stockD3D11.samplerLinear2DClamp.GetAddressOf() : stockD3D11.samplerPoint2DClamp.GetAddressOf()); + context_->PSSetSamplers(3, 1, smooth ? samplerLinear2DClamp_.GetAddressOf() : samplerPoint2DClamp_.GetAddressOf()); } void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 1e366156a3..791da3ccf0 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -37,6 +37,9 @@ public: SamplerCacheD3D11() {} ~SamplerCacheD3D11(); HRESULT GetOrCreateSampler(ID3D11Device *device, const SamplerCacheKey &key, ID3D11SamplerState **); + void Destroy() { + cache_.clear(); + } private: std::map> cache_; @@ -75,8 +78,8 @@ private: void BuildTexture(TexCacheEntry *const entry) override; - Microsoft::WRL::ComPtr device_; - Microsoft::WRL::ComPtr context_; + ID3D11Device *device_; + ID3D11DeviceContext *context_; ID3D11Resource *&DxTex(const TexCacheEntry *entry) const { return (ID3D11Resource *&)entry->texturePtr; @@ -89,6 +92,8 @@ private: ID3D11ShaderResourceView *lastBoundTexture_ = D3D11_INVALID_TEX; Microsoft::WRL::ComPtr depalConstants_; + Microsoft::WRL::ComPtr samplerPoint2DClamp_; + Microsoft::WRL::ComPtr samplerLinear2DClamp_; }; DXGI_FORMAT GetClutDestFormatD3D11(GEPaletteFormat format);