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] 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);