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
This commit is contained in:
PatrickvL 2021-07-16 10:28:29 +02:00
parent aa98efbc1a
commit 391741a075
4 changed files with 64 additions and 38 deletions

View File

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

View File

@ -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) {

View File

@ -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<ShaderKey, LazyVertexShader> cache;

View File

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