diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 2f81ef45da..a290292e8e 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -511,6 +511,16 @@ const char* PixelShaderVersionString() return "ps_4_0"; } +const char* ComputeShaderVersionString() +{ + if (s_featlevel == D3D_FEATURE_LEVEL_11_0) + return "cs_5_0"; + else if (s_featlevel == D3D_FEATURE_LEVEL_10_1) + return "cs_4_1"; + else /*if(featlevel == D3D_FEATURE_LEVEL_10_0)*/ + return "cs_4_0"; +} + D3DTexture2D* GetBackBuffer() { return s_backbuf; diff --git a/Source/Core/VideoBackends/D3D/D3DBase.h b/Source/Core/VideoBackends/D3D/D3DBase.h index 64c19fb5ed..c4ef6de5f5 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.h +++ b/Source/Core/VideoBackends/D3D/D3DBase.h @@ -69,6 +69,7 @@ D3DTexture2D* GetBackBuffer(); const char* PixelShaderVersionString(); const char* GeometryShaderVersionString(); const char* VertexShaderVersionString(); +const char* ComputeShaderVersionString(); bool BGRATexturesSupported(); bool AllowTearingSupported(); diff --git a/Source/Core/VideoBackends/D3D/D3DShader.cpp b/Source/Core/VideoBackends/D3D/D3DShader.cpp index 6afb1eb1cc..f47b428904 100644 --- a/Source/Core/VideoBackends/D3D/D3DShader.cpp +++ b/Source/Core/VideoBackends/D3D/D3DShader.cpp @@ -188,6 +188,66 @@ bool CompilePixelShader(const std::string& code, D3DBlob** blob, const D3D_SHADE return SUCCEEDED(hr); } +// bytecode->shader +ID3D11ComputeShader* CreateComputeShaderFromByteCode(const void* bytecode, size_t len) +{ + ID3D11ComputeShader* shader; + HRESULT hr = D3D::device->CreateComputeShader(bytecode, len, nullptr, &shader); + if (FAILED(hr)) + { + PanicAlert("CreateComputeShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__); + return nullptr; + } + return shader; +} + +// code->bytecode +bool CompileComputeShader(const std::string& code, D3DBlob** blob, const D3D_SHADER_MACRO* pDefines) +{ + ID3D10Blob* shaderBuffer = nullptr; + ID3D10Blob* errorBuffer = nullptr; + +#if defined(_DEBUG) || defined(DEBUGFAST) + UINT flags = D3D10_SHADER_DEBUG; +#else + UINT flags = D3D10_SHADER_OPTIMIZATION_LEVEL3; +#endif + HRESULT hr = + PD3DCompile(code.c_str(), code.length(), nullptr, pDefines, nullptr, "main", + D3D::ComputeShaderVersionString(), flags, 0, &shaderBuffer, &errorBuffer); + + if (errorBuffer) + { + INFO_LOG(VIDEO, "Compute shader compiler messages:\n%s", + (const char*)errorBuffer->GetBufferPointer()); + } + + if (FAILED(hr)) + { + static int num_failures = 0; + std::string filename = StringFromFormat("%sbad_cs_%04i.txt", + File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); + std::ofstream file; + File::OpenFStream(file, filename, std::ios_base::out); + file << code; + file.close(); + + PanicAlert("Failed to compile compute shader: %s\nDebug info (%s):\n%s", filename.c_str(), + D3D::ComputeShaderVersionString(), + reinterpret_cast(errorBuffer->GetBufferPointer())); + + *blob = nullptr; + errorBuffer->Release(); + } + else + { + *blob = new D3DBlob(shaderBuffer); + shaderBuffer->Release(); + } + + return SUCCEEDED(hr); +} + ID3D11VertexShader* CompileAndCreateVertexShader(const std::string& code) { D3DBlob* blob = nullptr; @@ -226,6 +286,19 @@ ID3D11PixelShader* CompileAndCreatePixelShader(const std::string& code) return nullptr; } +ID3D11ComputeShader* CompileAndCreateComputeShader(const std::string& code) +{ + D3DBlob* blob = nullptr; + CompileComputeShader(code, &blob); + if (blob) + { + ID3D11ComputeShader* shader = CreateComputeShaderFromByteCode(blob); + blob->Release(); + return shader; + } + return nullptr; +} + } // namespace } // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/D3DShader.h b/Source/Core/VideoBackends/D3D/D3DShader.h index 751c854015..4212847e63 100644 --- a/Source/Core/VideoBackends/D3D/D3DShader.h +++ b/Source/Core/VideoBackends/D3D/D3DShader.h @@ -19,6 +19,7 @@ namespace D3D ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, size_t len); ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, size_t len); ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, size_t len); +ID3D11ComputeShader* CreateComputeShaderFromByteCode(const void* bytecode, size_t len); // The returned bytecode buffers should be Release()d. bool CompileVertexShader(const std::string& code, D3DBlob** blob); @@ -26,12 +27,15 @@ bool CompileGeometryShader(const std::string& code, D3DBlob** blob, const D3D_SHADER_MACRO* pDefines = nullptr); bool CompilePixelShader(const std::string& code, D3DBlob** blob, const D3D_SHADER_MACRO* pDefines = nullptr); +bool CompileComputeShader(const std::string& code, D3DBlob** blob, + const D3D_SHADER_MACRO* pDefines = nullptr); // Utility functions ID3D11VertexShader* CompileAndCreateVertexShader(const std::string& code); ID3D11GeometryShader* CompileAndCreateGeometryShader(const std::string& code, const D3D_SHADER_MACRO* pDefines = nullptr); ID3D11PixelShader* CompileAndCreatePixelShader(const std::string& code); +ID3D11ComputeShader* CompileAndCreateComputeShader(const std::string& code); inline ID3D11VertexShader* CreateVertexShaderFromByteCode(D3DBlob* bytecode) { @@ -45,21 +49,29 @@ inline ID3D11PixelShader* CreatePixelShaderFromByteCode(D3DBlob* bytecode) { return CreatePixelShaderFromByteCode(bytecode->Data(), bytecode->Size()); } +inline ID3D11ComputeShader* CreateComputeShaderFromByteCode(D3DBlob* bytecode) +{ + return CreateComputeShaderFromByteCode(bytecode->Data(), bytecode->Size()); +} inline ID3D11VertexShader* CompileAndCreateVertexShader(D3DBlob* code) { - return CompileAndCreateVertexShader((const char*)code->Data()); + return CompileAndCreateVertexShader(reinterpret_cast(code->Data())); } inline ID3D11GeometryShader* CompileAndCreateGeometryShader(D3DBlob* code, const D3D_SHADER_MACRO* pDefines = nullptr) { - return CompileAndCreateGeometryShader((const char*)code->Data(), pDefines); + return CompileAndCreateGeometryShader(reinterpret_cast(code->Data()), pDefines); } inline ID3D11PixelShader* CompileAndCreatePixelShader(D3DBlob* code) { - return CompileAndCreatePixelShader((const char*)code->Data()); + return CompileAndCreatePixelShader(reinterpret_cast(code->Data())); +} +inline ID3D11ComputeShader* CompileAndCreateComputeShader(D3DBlob* code) +{ + return CompileAndCreateComputeShader(reinterpret_cast(code->Data())); } }