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"); } }