From 391741a075ef206017555b248b8038a41ba9e2a1 Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Fri, 16 Jul 2021 10:28:29 +0200 Subject: [PATCH] Ported vertex shader creation and activation For this, introduced and used CxbxCreateVertexShader, and refactored CxbxUpdateHostVertexShader, to perform local state tracking and switch active host vertex shader only when required Removed ResetD3DDevice method --- src/core/hle/D3D8/Direct3D9/Direct3D9.cpp | 3 - .../hle/D3D8/Direct3D9/VertexShaderCache.cpp | 68 ++++++++++++------- .../hle/D3D8/Direct3D9/VertexShaderCache.h | 3 - src/core/hle/D3D8/XbVertexShader.cpp | 28 ++++++-- 4 files changed, 64 insertions(+), 38 deletions(-) diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index 4099d462f..41d1ecca3 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -2443,9 +2443,6 @@ static void CreateDefaultD3D9Device DrawInitialBlackScreen(); - // Set up cache - g_VertexShaderCache.ResetD3DDevice(g_pD3DDevice); - // Set up ImGui's render backend #ifdef CXBX_USE_D3D11 ImGui_ImplDX11_Init(g_pD3DDevice); diff --git a/src/core/hle/D3D8/Direct3D9/VertexShaderCache.cpp b/src/core/hle/D3D8/Direct3D9/VertexShaderCache.cpp index aed2ffb28..bb0389dd7 100644 --- a/src/core/hle/D3D8/Direct3D9/VertexShaderCache.cpp +++ b/src/core/hle/D3D8/Direct3D9/VertexShaderCache.cpp @@ -5,10 +5,10 @@ #include "core/kernel/init/CxbxKrnl.h" #include "util/hasher.h" #include "core/kernel/support/Emu.h" +#include "core\hle\D3D8\Direct3D9\Direct3D9.h" // For g_pD3DDevice VertexShaderCache g_VertexShaderCache = VertexShaderCache(); // FIXME : This should really be released and created in step with the D3D device lifecycle rather than being a thing on its own -// (And the ResetD3DDevice method should be removed) ID3DBlob* AsyncCreateVertexShader(IntermediateVertexShader intermediateShader, ShaderKey key) { @@ -86,6 +86,45 @@ ShaderKey VertexShaderCache::CreateShader(const xbox::dword_xt* pXboxFunction, D return key; } +IDirect3DVertexShader* CxbxCreateVertexShader(ID3DBlob* pCompiledShader, const char *shader_category) +{ + IDirect3DVertexShader* pHostVertexShader = nullptr; + + // If there's no D3DDevice set, return nullptr + if (g_pD3DDevice == nullptr) { + EmuLog(LOG_LEVEL::WARNING, "Can't create %s vertex shader - no D3D device is set!", shader_category); + } + else { + assert(pCompiledShader); + + HRESULT hRet; +#ifdef CXBX_USE_D3D11 + hRet = g_pD3DDevice->CreateVertexShader( + (const void*)pCompiledShader->GetBufferPointer(), + pCompiledShader->GetBufferSize(), // BytecodeLength + nullptr, // pClassLinkage + &pHostVertexShader + ); +#else + hRet = g_pD3DDevice->CreateVertexShader( + (DWORD *)pCompiledShader->GetBufferPointer(), + &pHostVertexShader + ); +#endif + if (FAILED(hRet)) CxbxrAbort("Failed to create %s vertex shader", shader_category); + + // TODO DEBUG_D3DRESULT(hRet, "g_pD3DDevice->CreateVertexShader"); + if (SUCCEEDED(hRet)) { + EmuLog(LOG_LEVEL::DEBUG, "Created new %s vertex shader instance", shader_category); + } + else { + EmuLog(LOG_LEVEL::ERROR2, "Failed creating new %s vertex shader instance", shader_category); + } + } + + return pHostVertexShader; +} + // Get a shader using the given key IDirect3DVertexShader* VertexShaderCache::GetShader(ShaderKey key) { @@ -101,12 +140,6 @@ IDirect3DVertexShader* VertexShaderCache::GetShader(ShaderKey key) return pLazyShader->pHostVertexShader; } - // If there's no D3DDevice set, return nullptr - if (pD3DDevice == nullptr) { - EmuLog(LOG_LEVEL::WARNING, "Can't create shader - no D3D device is set!"); - return nullptr; - } - // We need to get the compiled HLSL and create a shader from it ID3DBlob* pCompiledShader = nullptr; try { @@ -121,19 +154,9 @@ IDirect3DVertexShader* VertexShaderCache::GetShader(ShaderKey key) } // Create the shader - auto hRet = pD3DDevice->CreateVertexShader - ( - (DWORD*)pCompiledShader->GetBufferPointer(), - &pLazyShader->pHostVertexShader - ); + // TODO : incorporate key into "regular" shader category string + pLazyShader->pHostVertexShader = CxbxCreateVertexShader(pCompiledShader, "regular"); - // TODO DEBUG_D3DRESULT(hRet, "g_pD3DDevice->CreateVertexShader"); - if (SUCCEEDED(hRet)) { - EmuLog(LOG_LEVEL::DEBUG, "Created new vertex shader instance for %llx", key); - } - else { - EmuLog(LOG_LEVEL::ERROR2, "Failed creating new vertex shader instance for %llx", key); - } } catch (const std::exception & e) { EmuLog(LOG_LEVEL::ERROR2, "Failed compiling shader %llx: %s", e.what()); @@ -172,13 +195,6 @@ void VertexShaderCache::ReleaseShader(ShaderKey key) } } -void VertexShaderCache::ResetD3DDevice(IDirect3DDevice* newDevice) -{ - EmuLog(LOG_LEVEL::DEBUG, "Resetting D3D device"); - cache.clear(); - this->pD3DDevice = newDevice; -} - void VertexShaderCache::Clear() { for (auto& x : cache) { diff --git a/src/core/hle/D3D8/Direct3D9/VertexShaderCache.h b/src/core/hle/D3D8/Direct3D9/VertexShaderCache.h index eb08aa963..ad55ad7c8 100644 --- a/src/core/hle/D3D8/Direct3D9/VertexShaderCache.h +++ b/src/core/hle/D3D8/Direct3D9/VertexShaderCache.h @@ -15,9 +15,7 @@ public: IDirect3DVertexShader *GetShader(ShaderKey key); void ReleaseShader(ShaderKey key); - void ResetD3DDevice(IDirect3DDevice* pD3DDevice); void Clear(); - // TODO // WriteCacheToDisk // LoadCacheFromDisk @@ -36,7 +34,6 @@ private: // OptimizationLevel? }; - IDirect3DDevice9* pD3DDevice; std::mutex cacheMutex; std::map cache; diff --git a/src/core/hle/D3D8/XbVertexShader.cpp b/src/core/hle/D3D8/XbVertexShader.cpp index c9a03ded7..3d8ea9089 100644 --- a/src/core/hle/D3D8/XbVertexShader.cpp +++ b/src/core/hle/D3D8/XbVertexShader.cpp @@ -1184,15 +1184,31 @@ IDirect3DVertexDeclaration* CxbxCreateHostVertexDeclaration(D3DVERTEXELEMENT *pD return pHostVertexDeclaration; } +HRESULT CxbxSetVertexShader(IDirect3DVertexShader* pHostVertexShader) +{ + HRESULT hRet; +#ifdef CXBX_USE_D3D11 + hRet = g_pD3DDevice->VSSetShader( + pHostVertexShader, + nullptr, // ppClassInstances + 0 // NumClassInstances + ); +#else + hRet = g_pD3DDevice->SetVertexShader(pHostVertexShader); +#endif + return hRet; +} + +extern IDirect3DVertexShader* CxbxCreateVertexShader(ID3DBlob* pCompiledShader, const char *shader_category); // Implemented in VertexShaderCache.cpp + IDirect3DVertexShader* InitShader(void (*compileFunc)(ID3DBlob**), const char* label) { IDirect3DVertexShader* shader = nullptr; ID3DBlob* pBlob = nullptr; compileFunc(&pBlob); if (pBlob) { - HRESULT hRet = g_pD3DDevice->CreateVertexShader((DWORD*)pBlob->GetBufferPointer(), &shader); + shader = CxbxCreateVertexShader(pBlob, label); pBlob->Release(); - if (FAILED(hRet)) CxbxrAbort("Failed to create shader: %s", label); } return shader; @@ -1209,7 +1225,7 @@ void CxbxUpdateHostVertexShader() int shaderVersion = g_ShaderSources.Update(); if (vertexShaderVersion != shaderVersion) { vertexShaderVersion = shaderVersion; - g_pD3DDevice->SetVertexShader(nullptr); + CxbxSetVertexShader(nullptr); EmuLog(LOG_LEVEL::INFO, "Loading vertex shaders..."); @@ -1234,11 +1250,11 @@ void CxbxUpdateHostVertexShader() LOG_INIT; // Allows use of DEBUG_D3DRESULT if (g_Xbox_VertexShaderMode == VertexShaderMode::FixedFunction) { - HRESULT hRet = g_pD3DDevice->SetVertexShader(fixedFunctionShader); + HRESULT hRet = CxbxSetVertexShader(fixedFunctionShader); if (FAILED(hRet)) CxbxrAbort("Failed to set fixed-function shader"); } else if (g_Xbox_VertexShaderMode == VertexShaderMode::Passthrough && g_bUsePassthroughHLSL) { - HRESULT hRet = g_pD3DDevice->SetVertexShader(passthroughShader); + HRESULT hRet = CxbxSetVertexShader(passthroughShader); if (FAILED(hRet)) CxbxrAbort("Failed to set passthrough shader"); } else { @@ -1248,7 +1264,7 @@ void CxbxUpdateHostVertexShader() DWORD shaderSize; auto VertexShaderKey = g_VertexShaderCache.CreateShader(pTokens, &shaderSize); IDirect3DVertexShader* pHostVertexShader = g_VertexShaderCache.GetShader(VertexShaderKey); - HRESULT hRet = g_pD3DDevice->SetVertexShader(pHostVertexShader); + HRESULT hRet = CxbxSetVertexShader(pHostVertexShader); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShader"); } }