Move shader hlsl management into Shader.cpp
- g_ShaderHlsl keeps track of hlsl - VS and PS source their hlsl from g_ShaderHlsl
This commit is contained in:
parent
260e2fb7c8
commit
79884bdf3d
|
@ -1,6 +1,3 @@
|
|||
// This starts the raw string (comment to get syntax highlighting, UNCOMMENT to compile) :
|
||||
R"DELIMITER(
|
||||
|
||||
struct PS_INPUT // Declared identical to vertex shader output (see VS_OUTPUT)
|
||||
{
|
||||
float2 iPos : VPOS; // Screen space x,y pixel location
|
||||
|
@ -92,10 +89,9 @@ uniform const float FRONTFACE_FACTOR : register(c27); // Note : PSH_XBOX_CONSTA
|
|||
#define PS_FINALCOMBINERSETTING_CLAMP_SUM
|
||||
#endif
|
||||
|
||||
)DELIMITER", /* This terminates the 1st raw string within the 16380 single-byte characters limit. // */
|
||||
// See https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2026?f1url=%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(C2026)%26rd%3Dtrue&view=vs-2019
|
||||
// Second raw string :
|
||||
R"DELIMITER(
|
||||
// Hardcoded state will be inserted here
|
||||
// <HARDCODED STATE GOES HERE>
|
||||
// End hardcoded state
|
||||
|
||||
// PS_COMBINERCOUNT_UNIQUE_C0 steers whether for C0 to use combiner stage-specific constants c0_0 .. c0_7, or c0_0 for all stages
|
||||
#ifdef PS_COMBINERCOUNT_UNIQUE_C0
|
||||
|
@ -173,10 +169,6 @@ R"DELIMITER(
|
|||
// HLSL : https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-lerp
|
||||
// lerp(x, y, s ) x*(1-s ) + y*s == x + s(y-x)
|
||||
// lerp(s2, s1, s0) s2*(1-s0) + s1*s0
|
||||
)DELIMITER", /* This terminates the 1st raw string within the 16380 single-byte characters limit. // */
|
||||
// See https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2026?f1url=%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(C2026)%26rd%3Dtrue&view=vs-2019
|
||||
// Second raw string :
|
||||
R"DELIMITER(
|
||||
|
||||
float m21d(const float input)
|
||||
{
|
||||
|
@ -379,10 +371,9 @@ PS_OUTPUT main(const PS_INPUT xIn)
|
|||
v1 = isFrontFace ? xIn.iD1 : xIn.iB1; // Specular front/back
|
||||
fog = float4(c_fog.rgb, xIn.iFog); // color from PSH_XBOX_CONSTANT_FOG, alpha from vertex shader output / pixel shader input
|
||||
|
||||
// Xbox shader program
|
||||
)DELIMITER", /* This terminates the 2nd raw string within the 16380 single-byte characters limit. // */
|
||||
// Third and last raw string, the footer :
|
||||
R"DELIMITER(
|
||||
// Xbox shader program will be inserted here
|
||||
// <XBOX SHADER PROGRAM GOES HERE>
|
||||
// End Xbox shader program
|
||||
|
||||
// Copy r0.rgba to output
|
||||
PS_OUTPUT xOut;
|
||||
|
@ -391,5 +382,3 @@ R"DELIMITER(
|
|||
|
||||
return xOut;
|
||||
}
|
||||
|
||||
// End of pixel shader footer)DELIMITER" /* This terminates the footer raw string" // */
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "..\FixedFunctionState.h"
|
||||
#include "core\hle\D3D8\ResourceTracker.h"
|
||||
#include "core\hle\D3D8\Direct3D9\Direct3D9.h" // For LPDIRECTDRAWSURFACE7
|
||||
#include "core\hle\D3D8\Direct3D9\Shader.h" // For InitShaderHotloading
|
||||
#include "core\hle\D3D8\XbVertexBuffer.h"
|
||||
#include "core\hle\D3D8\XbVertexShader.h"
|
||||
#include "core\hle\D3D8\XbPixelShader.h" // For DxbxUpdateActivePixelShader
|
||||
|
@ -683,8 +684,8 @@ void CxbxInitWindow(bool bFullInit)
|
|||
ImGui_ImplWin32_Shutdown();
|
||||
});
|
||||
|
||||
extern void InitShaderHotloading();
|
||||
InitShaderHotloading();
|
||||
g_ShaderHlsl.UpdateShaders();
|
||||
g_ShaderHlsl.InitShaderHotloading();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -289,12 +289,7 @@ bool IsTextureSampled(DecodedRegisterCombiner* pShader, int reg)
|
|||
|
||||
void BuildShader(DecodedRegisterCombiner* pShader, std::stringstream& hlsl)
|
||||
{
|
||||
// Include HLSL header and footer as raw strings :
|
||||
static const std::string hlsl_template[4] = {
|
||||
#include "core\hle\D3D8\Direct3D9\CxbxPixelShaderTemplate.hlsl"
|
||||
};
|
||||
|
||||
hlsl << hlsl_template[0]; // Start with the HLSL template header
|
||||
hlsl << g_ShaderHlsl.pixelShaderTemplateHlsl[0]; // Start with the HLSL template header
|
||||
|
||||
hlsl << "\n#define ALPHAKILL {"
|
||||
<< (pShader->AlphaKill[0] ? "true, " : "false, ")
|
||||
|
@ -341,9 +336,9 @@ void BuildShader(DecodedRegisterCombiner* pShader, std::stringstream& hlsl)
|
|||
OutputDefineFlag(hlsl, pShader->FinalCombiner.ComplementV1, "PS_FINALCOMBINERSETTING_COMPLEMENT_V1");
|
||||
OutputDefineFlag(hlsl, pShader->FinalCombiner.ComplementR0, "PS_FINALCOMBINERSETTING_COMPLEMENT_R0");
|
||||
OutputDefineFlag(hlsl, pShader->FinalCombiner.ClampSum, "PS_FINALCOMBINERSETTING_CLAMP_SUM");
|
||||
hlsl << '\n';
|
||||
|
||||
hlsl << hlsl_template[1];
|
||||
hlsl << hlsl_template[2];
|
||||
hlsl << g_ShaderHlsl.pixelShaderTemplateHlsl[1];
|
||||
|
||||
// Generate all four texture stages
|
||||
for (unsigned i = 0; i < PSH_XBOX_MAX_T_REGISTER_COUNT; i++) {
|
||||
|
@ -390,7 +385,7 @@ void BuildShader(DecodedRegisterCombiner* pShader, std::stringstream& hlsl)
|
|||
|
||||
FinalCombinerStageHlsl(hlsl, pShader->FinalCombiner, pShader->hasFinalCombiner);
|
||||
|
||||
hlsl << hlsl_template[3]; // Finish with the HLSL template footer
|
||||
hlsl << g_ShaderHlsl.pixelShaderTemplateHlsl[2]; // Finish with the HLSL template footer
|
||||
}
|
||||
|
||||
// recompile xbox pixel shader function
|
||||
|
|
|
@ -29,10 +29,18 @@
|
|||
|
||||
#include <d3dcompiler.h>
|
||||
#include "Shader.h"
|
||||
#include "common/FilePaths.hpp" // For szFilePath_CxbxReloaded_Exe
|
||||
#include "core\kernel\init\CxbxKrnl.h" // LOG_TEST_CASE
|
||||
#include "core\kernel\support\Emu.h" // EmuLog
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <array>
|
||||
#include <thread>
|
||||
//#include <sstream>
|
||||
|
||||
ShaderHlsl g_ShaderHlsl;
|
||||
|
||||
std::string DebugPrependLineNumbers(std::string shaderString) {
|
||||
std::stringstream shader(shaderString);
|
||||
auto debugShader = std::stringstream();
|
||||
|
@ -140,3 +148,159 @@ extern HRESULT EmuCompileShader
|
|||
|
||||
return hRet;
|
||||
}
|
||||
|
||||
std::ifstream OpenWithRetry(const std::string& path) {
|
||||
auto fstream = std::ifstream(path);
|
||||
int failures = 0;
|
||||
while (fstream.fail()) {
|
||||
Sleep(50);
|
||||
fstream = std::ifstream(path);
|
||||
|
||||
if (failures++ > 10) {
|
||||
// crash?
|
||||
CxbxrAbort("Error opening shader file: %s", path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fstream;
|
||||
}
|
||||
|
||||
int ShaderHlsl::UpdateShaders() {
|
||||
int versionOnDisk = shaderVersionOnDisk;
|
||||
if (shaderVersionLoadedFromDisk != versionOnDisk) {
|
||||
LoadShadersFromDisk();
|
||||
shaderVersionLoadedFromDisk = versionOnDisk;
|
||||
}
|
||||
|
||||
return shaderVersionLoadedFromDisk;
|
||||
}
|
||||
|
||||
void ShaderHlsl::LoadShadersFromDisk() {
|
||||
const auto hlslDir = std::filesystem::path(szFilePath_CxbxReloaded_Exe)
|
||||
.parent_path()
|
||||
.append("hlsl");
|
||||
|
||||
// Pixel Shader Template
|
||||
{
|
||||
std::stringstream tmp;
|
||||
auto dir = hlslDir;
|
||||
dir.append("CxbxPixelShaderTemplate.hlsl");
|
||||
tmp << OpenWithRetry(dir.string()).rdbuf();
|
||||
std::string hlsl = tmp.str();
|
||||
|
||||
// Split the HLSL file on insertion points
|
||||
std::array<std::string, 2> insertionPoints = {
|
||||
"// <HARDCODED STATE GOES HERE>\n",
|
||||
"// <XBOX SHADER PROGRAM GOES HERE>\n",
|
||||
};
|
||||
int pos = 0;
|
||||
for (int i = 0; i < insertionPoints.size(); i++) {
|
||||
auto insertionPoint = insertionPoints[i];
|
||||
auto index = hlsl.find(insertionPoint, pos);
|
||||
|
||||
this->pixelShaderTemplateHlsl[i] = hlsl.substr(pos, index - pos);
|
||||
pos = index + insertionPoint.length();
|
||||
}
|
||||
this->pixelShaderTemplateHlsl[insertionPoints.size()] = hlsl.substr(pos);
|
||||
}
|
||||
|
||||
// Fixed Function Pixel Shader
|
||||
{
|
||||
auto dir = hlslDir;
|
||||
this->fixedFunctionPixelShaderPath = dir.append("FixedFunctionPixelShader.hlsl").string();
|
||||
std::stringstream tmp;
|
||||
tmp << OpenWithRetry(this->fixedFunctionPixelShaderPath).rdbuf();
|
||||
this->fixedFunctionPixelShaderHlsl = tmp.str();
|
||||
}
|
||||
|
||||
// Vertex Shader Template
|
||||
{
|
||||
std::stringstream tmp;
|
||||
auto dir = hlslDir;
|
||||
dir.append("CxbxVertexShaderTemplate.hlsl");
|
||||
tmp << OpenWithRetry(dir.string()).rdbuf();
|
||||
std::string hlsl = tmp.str();
|
||||
|
||||
const std::string insertionPoint = "// <XBOX SHADER PROGRAM GOES HERE>\n";
|
||||
auto index = hlsl.find(insertionPoint);
|
||||
this->vertexShaderTemplateHlsl[0] = hlsl.substr(0, index);
|
||||
this->vertexShaderTemplateHlsl[1] = hlsl.substr(index + insertionPoint.length());
|
||||
}
|
||||
|
||||
// Fixed Function Vertex Shader
|
||||
{
|
||||
auto dir = hlslDir;
|
||||
this->fixedFunctionVertexShaderPath = dir.append("FixedFunctionVertexShader.hlsl").string();
|
||||
std::stringstream tmp;
|
||||
tmp << OpenWithRetry(this->fixedFunctionVertexShaderPath).rdbuf();
|
||||
this->fixedFunctionVertexShaderHlsl = tmp.str();
|
||||
}
|
||||
|
||||
// Passthrough Vertex Shader
|
||||
{
|
||||
auto dir = hlslDir;
|
||||
this->vertexShaderPassthroughPath = dir.append("CxbxVertexShaderPassthrough.hlsl").string();
|
||||
std::stringstream tmp;
|
||||
tmp << OpenWithRetry(this->vertexShaderPassthroughPath).rdbuf();
|
||||
this->vertexShaderPassthroughHlsl = tmp.str();
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderHlsl::InitShaderHotloading() {
|
||||
static std::thread fsWatcherThread;
|
||||
|
||||
if (fsWatcherThread.joinable()) {
|
||||
EmuLog(LOG_LEVEL::ERROR2, "Ignoring request to start shader file watcher - it has already been started.");
|
||||
return;
|
||||
}
|
||||
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Starting shader file watcher...");
|
||||
|
||||
fsWatcherThread = std::thread([]{
|
||||
// Determine the filename and directory for the fixed function shader
|
||||
char cxbxExePath[MAX_PATH];
|
||||
GetModuleFileName(GetModuleHandle(nullptr), cxbxExePath, MAX_PATH);
|
||||
auto hlslDir = std::filesystem::path(cxbxExePath)
|
||||
.parent_path()
|
||||
.append("hlsl/");
|
||||
|
||||
HANDLE changeHandle = FindFirstChangeNotification(hlslDir.string().c_str(), false, FILE_NOTIFY_CHANGE_LAST_WRITE);
|
||||
|
||||
if (changeHandle == INVALID_HANDLE_VALUE) {
|
||||
DWORD errorCode = GetLastError();
|
||||
EmuLog(LOG_LEVEL::ERROR2, "Error initializing shader file watcher: %d", errorCode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (FindNextChangeNotification(changeHandle)) {
|
||||
WaitForSingleObject(changeHandle, INFINITE);
|
||||
|
||||
// Wait for changes to stop..
|
||||
// Will usually be at least two - one for the file and one for the directory
|
||||
while (true) {
|
||||
FindNextChangeNotification(changeHandle);
|
||||
if (WaitForSingleObject(changeHandle, 100) == WAIT_TIMEOUT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Change detected in shader folder");
|
||||
g_ShaderHlsl.shaderVersionOnDisk += 1;
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::ERROR2, "Shader filewatcher failed to get the next notification");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Shader file watcher exiting...");
|
||||
|
||||
// until there is a way to disable hotloading
|
||||
// this is always an error
|
||||
FindCloseChangeNotification(changeHandle);
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,3 +10,38 @@ extern HRESULT EmuCompileShader
|
|||
ID3DBlob** ppHostShader,
|
||||
const char* pSourceName = nullptr
|
||||
);
|
||||
|
||||
struct ShaderHlsl {
|
||||
// Pixel Shader
|
||||
std::string pixelShaderTemplateHlsl[3];
|
||||
|
||||
std::string fixedFunctionPixelShaderHlsl;
|
||||
std::string fixedFunctionPixelShaderPath;
|
||||
|
||||
// Vertex Shader
|
||||
std::string vertexShaderTemplateHlsl[2];
|
||||
|
||||
std::string fixedFunctionVertexShaderHlsl;
|
||||
std::string fixedFunctionVertexShaderPath;
|
||||
|
||||
std::string vertexShaderPassthroughHlsl;
|
||||
std::string vertexShaderPassthroughPath;
|
||||
|
||||
// Load shaders from disk (if out-of-date)
|
||||
// and return the current loaded shader version
|
||||
int UpdateShaders();
|
||||
|
||||
// Start a thread to watch for changes in the shader folder
|
||||
void InitShaderHotloading();
|
||||
|
||||
private:
|
||||
void LoadShadersFromDisk();
|
||||
|
||||
// counts upwards on every change detected to the shader source files at runtime
|
||||
volatile int shaderVersionOnDisk = 0;
|
||||
// current loaded shader version
|
||||
// Initialized to < shaderVersionOnDisk
|
||||
int shaderVersionLoadedFromDisk = -1;
|
||||
};
|
||||
|
||||
extern ShaderHlsl g_ShaderHlsl;
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
#include "VertexShader.h" // EmuCompileVertexShader
|
||||
#include "core\kernel\init\CxbxKrnl.h" // implicit CxbxKrnl_Xbe used in LOG_TEST_CASE
|
||||
#include "core\kernel\support\Emu.h" // LOG_TEST_CASE (via Logging.h)
|
||||
#include "common/FilePaths.hpp" // For szFilePath_CxbxReloaded_Exe
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream> // std::stringstream
|
||||
|
||||
extern const char* g_vs_model = vs_model_3_0;
|
||||
|
@ -283,67 +281,6 @@ void BuildShader(IntermediateVertexShader* pShader, std::stringstream& hlsl)
|
|||
}
|
||||
}
|
||||
|
||||
std::string vertexShaderTemplateHlsl[2];
|
||||
std::string fixedFunctionVertexShaderHlsl;
|
||||
std::string fixedFunctionVertexShaderPath;
|
||||
std::string vertexShaderPassthroughHlsl;
|
||||
std::string vertexShaderPassthroughPath;
|
||||
|
||||
std::ifstream OpenWithRetry(const std::string& path) {
|
||||
auto fstream = std::ifstream(path);
|
||||
int failures = 0;
|
||||
while (fstream.fail()) {
|
||||
Sleep(50);
|
||||
fstream = std::ifstream(path);
|
||||
|
||||
if (failures++ > 10) {
|
||||
// crash?
|
||||
CxbxrAbort("Error opening shader file: %s", path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fstream;
|
||||
}
|
||||
|
||||
void LoadShadersFromDisk() {
|
||||
const auto hlslDir = std::filesystem::path(szFilePath_CxbxReloaded_Exe)
|
||||
.parent_path()
|
||||
.append("hlsl");
|
||||
|
||||
// Vertex Shader Template
|
||||
{
|
||||
std::stringstream tmp;
|
||||
auto dir = hlslDir;
|
||||
dir.append("CxbxVertexShaderTemplate.hlsl");
|
||||
tmp << OpenWithRetry(dir.string()).rdbuf();
|
||||
std::string hlsl = tmp.str();
|
||||
|
||||
const std::string insertionPoint = "// <XBOX SHADER PROGRAM GOES HERE>\n";
|
||||
auto index = hlsl.find(insertionPoint);
|
||||
vertexShaderTemplateHlsl[0] = hlsl.substr(0, index);
|
||||
vertexShaderTemplateHlsl[1] = hlsl.substr(index + insertionPoint.length());
|
||||
}
|
||||
|
||||
// Fixed Function Vertex Shader
|
||||
{
|
||||
auto dir = hlslDir;
|
||||
fixedFunctionVertexShaderPath = dir.append("FixedFunctionVertexShader.hlsl").string();
|
||||
std::stringstream tmp;
|
||||
tmp << OpenWithRetry(fixedFunctionVertexShaderPath).rdbuf();
|
||||
fixedFunctionVertexShaderHlsl = tmp.str();
|
||||
}
|
||||
|
||||
// Passthrough Vertex Shader
|
||||
{
|
||||
auto dir = hlslDir;
|
||||
vertexShaderPassthroughPath = dir.append("CxbxVertexShaderPassthrough.hlsl").string();
|
||||
std::stringstream tmp;
|
||||
tmp << OpenWithRetry(vertexShaderPassthroughPath).rdbuf();
|
||||
vertexShaderPassthroughHlsl = tmp.str();
|
||||
}
|
||||
}
|
||||
|
||||
// recompile xbox vertex shader function
|
||||
extern HRESULT EmuCompileVertexShader
|
||||
(
|
||||
|
@ -355,9 +292,9 @@ extern HRESULT EmuCompileVertexShader
|
|||
|
||||
// Combine the shader template with the shader program
|
||||
auto hlsl_stream = std::stringstream();
|
||||
hlsl_stream << vertexShaderTemplateHlsl[0]; // Start with the HLSL template header
|
||||
hlsl_stream << g_ShaderHlsl.vertexShaderTemplateHlsl[0]; // Start with the HLSL template header
|
||||
BuildShader(pIntermediateShader, hlsl_stream);
|
||||
hlsl_stream << vertexShaderTemplateHlsl[1]; // Finish with the HLSL template footer
|
||||
hlsl_stream << g_ShaderHlsl.vertexShaderTemplateHlsl[1]; // Finish with the HLSL template footer
|
||||
std::string hlsl_str = hlsl_stream.str();
|
||||
|
||||
auto notionalSourceName = "CxbxVertexShaderTemplate.hlsl";
|
||||
|
@ -375,10 +312,10 @@ extern HRESULT EmuCompileVertexShader
|
|||
|
||||
extern void EmuCompileFixedFunction(ID3DBlob** ppHostShader)
|
||||
{
|
||||
EmuCompileShader(fixedFunctionVertexShaderHlsl, g_vs_model, ppHostShader, fixedFunctionVertexShaderPath.c_str());
|
||||
EmuCompileShader(g_ShaderHlsl.fixedFunctionVertexShaderHlsl, g_vs_model, ppHostShader, g_ShaderHlsl.fixedFunctionVertexShaderPath.c_str());
|
||||
};
|
||||
|
||||
extern void EmuCompileXboxPassthrough(ID3DBlob** ppHostShader)
|
||||
{
|
||||
EmuCompileShader(vertexShaderPassthroughHlsl, g_vs_model, ppHostShader, vertexShaderPassthroughPath.c_str());
|
||||
EmuCompileShader(g_ShaderHlsl.vertexShaderPassthroughHlsl, g_vs_model, ppHostShader, g_ShaderHlsl.vertexShaderPassthroughPath.c_str());
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@ extern HRESULT EmuCompileVertexShader
|
|||
ID3DBlob** ppHostShader
|
||||
);
|
||||
|
||||
void LoadShadersFromDisk();
|
||||
|
||||
extern void EmuCompileFixedFunction(ID3DBlob** ppHostShader);
|
||||
|
||||
extern void EmuCompileXboxPassthrough(ID3DBlob** ppHostShader);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "core\kernel\support\Emu.h"
|
||||
#include "core\hle\D3D8\Direct3D9\Direct3D9.h" // For g_pD3DDevice, g_pXbox_PixelShader
|
||||
#include "core\hle\D3D8\Direct3D9\Shader.h" // For g_ShaderHlsl
|
||||
#include "core\hle\D3D8\XbPixelShader.h"
|
||||
#include "core\hle\D3D8\Direct3D9\PixelShader.h" // EmuCompilePixelShader
|
||||
#include "core\hle\D3D8\XbD3D8Logging.h" // For D3DErrorString()
|
||||
|
@ -664,30 +665,8 @@ constexpr int PSH_XBOX_CONSTANT_FRONTFACE_FACTOR = PSH_XBOX_CONSTANT_LUM + 4; //
|
|||
constexpr int PSH_XBOX_CONSTANT_MAX = PSH_XBOX_CONSTANT_FRONTFACE_FACTOR + 1; // = 28
|
||||
|
||||
std::string GetFixedFunctionShaderTemplate() {
|
||||
static bool loaded = false;
|
||||
static std::string hlslString;
|
||||
|
||||
// TODO does this need to be thread safe?
|
||||
if (!loaded) {
|
||||
loaded = true;
|
||||
|
||||
// Determine the filename and directory for the fixed function shader
|
||||
// TODO make this a relative path so we guarantee an LPCSTR for D3DCompile
|
||||
auto hlslDir = std::filesystem::path(szFilePath_CxbxReloaded_Exe)
|
||||
.parent_path()
|
||||
.append("hlsl");
|
||||
|
||||
auto sourceFile = hlslDir.append("FixedFunctionPixelShader.hlsl").string();
|
||||
|
||||
// Load the shader into a string
|
||||
std::ifstream hlslStream(sourceFile);
|
||||
std::stringstream hlsl;
|
||||
hlsl << hlslStream.rdbuf();
|
||||
|
||||
hlslString = hlsl.str();
|
||||
}
|
||||
|
||||
return hlslString;
|
||||
// TODO hlsl hotloading support
|
||||
return g_ShaderHlsl.fixedFunctionPixelShaderHlsl;
|
||||
}
|
||||
|
||||
std::string_view GetD3DTOPString(int d3dtop) {
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "core\hle\D3D8\Direct3D9\Direct3D9.h" // For g_Xbox_VertexShader_Handle
|
||||
#include "core\hle\D3D8\Direct3D9\RenderStates.h" // For XboxRenderStateConverter
|
||||
#include "core\hle\D3D8\Direct3D9\VertexShaderCache.h" // For g_VertexShaderCache
|
||||
#include "core\hle\D3D8\Direct3D9\Shader.h" // For g_ShaderHlsl
|
||||
#include "core\hle\D3D8\XbVertexBuffer.h" // For CxbxImpl_SetVertexData4f
|
||||
#include "core\hle\D3D8\XbVertexShader.h"
|
||||
#include "core\hle\D3D8\XbD3D8Logging.h" // For DEBUG_D3DRESULT
|
||||
|
@ -1144,12 +1145,16 @@ IDirect3DVertexShader* InitShader(void (*compileFunc)(ID3DBlob**), const char* l
|
|||
void CxbxUpdateHostVertexShader()
|
||||
{
|
||||
extern bool g_bUsePassthroughHLSL; // TMP glue
|
||||
// TODO move d3d9 state to VertexShader.cpp
|
||||
static IDirect3DVertexShader* fixedFunctionShader = nullptr; // TODO move to shader cache
|
||||
static IDirect3DVertexShader* passthroughShader = nullptr;
|
||||
static int vertexShaderVersion = -1;
|
||||
|
||||
int shaderVersion = g_ShaderHlsl.UpdateShaders();
|
||||
if (vertexShaderVersion != shaderVersion) {
|
||||
vertexShaderVersion = shaderVersion;
|
||||
|
||||
if (isShaderFolderDirty) {
|
||||
EmuLog(LOG_LEVEL::INFO, "Loading vertex shaders...");
|
||||
LoadShadersFromDisk();
|
||||
|
||||
g_VertexShaderCache.Clear();
|
||||
|
||||
|
@ -1164,8 +1169,6 @@ void CxbxUpdateHostVertexShader()
|
|||
passthroughShader = nullptr;
|
||||
}
|
||||
passthroughShader = InitShader(EmuCompileXboxPassthrough, "Passthrough Vertex Shader");
|
||||
|
||||
isShaderFolderDirty = false;
|
||||
}
|
||||
|
||||
// TODO Call this when state is dirty
|
||||
|
@ -1623,64 +1626,3 @@ extern void EmuParseVshFunction
|
|||
pCurToken += X_VSH_INSTRUCTION_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InitShaderHotloading() {
|
||||
static HANDLE fsWatcherThread = 0;
|
||||
|
||||
if (fsWatcherThread) {
|
||||
EmuLog(LOG_LEVEL::ERROR2, "Ignoring request to start shader file watcher - it has already been started.");
|
||||
return;
|
||||
}
|
||||
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Starting shader file watcher...");
|
||||
|
||||
auto fsWatcher = [](void* param) -> DWORD {
|
||||
// Determine the filename and directory for the fixed function shader
|
||||
char cxbxExePath[MAX_PATH];
|
||||
GetModuleFileName(GetModuleHandle(nullptr), cxbxExePath, MAX_PATH);
|
||||
auto hlslDir = std::filesystem::path(cxbxExePath)
|
||||
.parent_path()
|
||||
.append("hlsl/");
|
||||
|
||||
HANDLE changeHandle = FindFirstChangeNotification(hlslDir.string().c_str(), false, FILE_NOTIFY_CHANGE_LAST_WRITE);
|
||||
|
||||
if (changeHandle == INVALID_HANDLE_VALUE) {
|
||||
DWORD errorCode = GetLastError();
|
||||
EmuLog(LOG_LEVEL::ERROR2, "Error initializing shader file watcher: %d", errorCode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (FindNextChangeNotification(changeHandle)) {
|
||||
WaitForSingleObject(changeHandle, INFINITE);
|
||||
|
||||
// Wait for changes to stop..
|
||||
// Will usually be at least two - one for the file and one for the directory
|
||||
while (true) {
|
||||
FindNextChangeNotification(changeHandle);
|
||||
if (WaitForSingleObject(changeHandle, 100) == WAIT_TIMEOUT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Change detected in shader folder");
|
||||
isShaderFolderDirty = true;
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::ERROR2, "Shader filewatcher failed to get the next notification");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Shader file watcher exiting...");
|
||||
|
||||
// until there is a way to disable hotloading
|
||||
// this is always an error
|
||||
FindCloseChangeNotification(changeHandle);
|
||||
return 1;
|
||||
};
|
||||
|
||||
fsWatcherThread = CreateThread(nullptr, 0, fsWatcher, nullptr, 0, nullptr);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue