| 163 | } |
| 164 | |
| 165 | RendererShader ShaderManager::LoadOrCompile(const std::string& fileName, const std::string& funcName, ShaderType type, const D3D_SHADER_MACRO* defines, bool forceRecompile) |
| 166 | { |
| 167 | auto rendererShader = RendererShader{}; |
| 168 | |
| 169 | // Define paths for native (uncompiled) shaders and compiled shaders. |
| 170 | auto shaderPath = GetAssetPath(L"Shaders\\"); |
| 171 | auto compiledShaderPath = shaderPath + L"Bin\\" + ToWString(TEN_VERSION_STRING) + L"\\"; |
| 172 | auto wideFileName = ToWString(fileName); |
| 173 | |
| 174 | // Ensure the /Bin subdirectory exists. |
| 175 | std::filesystem::create_directories(compiledShaderPath); |
| 176 | |
| 177 | // Helper function to load or compile a shader. |
| 178 | auto loadOrCompileShader = [this, type, defines, forceRecompile, shaderPath, compiledShaderPath] |
| 179 | (const std::wstring& baseFileName, const std::string& shaderType, const std::string& functionName, const char* model, ComPtr<ID3D10Blob>& bytecode) |
| 180 | { |
| 181 | // Construct full paths using GetAssetPath. |
| 182 | auto prefix = ((_compileCounter < 10) ? L"0" : L"") + std::to_wstring(_compileCounter) + L"_"; |
| 183 | auto csoFileName = compiledShaderPath + prefix + baseFileName + L"." + std::wstring(shaderType.begin(), shaderType.end()) + L".cso"; |
| 184 | auto srcFileName = shaderPath + baseFileName; |
| 185 | |
| 186 | // Try both .hlsl and .fx extensions for source shader. |
| 187 | auto srcFileNameWithExtension = srcFileName + L".hlsl"; |
| 188 | if (!std::filesystem::exists(srcFileNameWithExtension)) |
| 189 | { |
| 190 | srcFileNameWithExtension = srcFileName + L".fx"; |
| 191 | if (!std::filesystem::exists(srcFileNameWithExtension)) |
| 192 | { |
| 193 | TENLog("Shader source file not found: " + ToString(srcFileNameWithExtension), LogLevel::Error); |
| 194 | throw std::runtime_error("Shader source file not found."); |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | // Check modification dates of source and compiled files. |
| 199 | if (!forceRecompile && std::filesystem::exists(csoFileName)) |
| 200 | { |
| 201 | auto csoTime = std::filesystem::last_write_time(csoFileName); |
| 202 | auto srcTime = std::filesystem::last_write_time(srcFileNameWithExtension); |
| 203 | |
| 204 | // Load compiled shader if it exists and is up-to-date. |
| 205 | if (srcTime < csoTime) |
| 206 | { |
| 207 | auto csoFile = std::ifstream(csoFileName, std::ios::binary); |
| 208 | |
| 209 | if (csoFile.is_open()) |
| 210 | { |
| 211 | // Load compiled shader. |
| 212 | csoFile.seekg(0, std::ios::end); |
| 213 | auto fileSize = csoFile.tellg(); |
| 214 | csoFile.seekg(0, std::ios::beg); |
| 215 | |
| 216 | auto buffer = std::vector<char>(fileSize); |
| 217 | csoFile.read(buffer.data(), fileSize); |
| 218 | csoFile.close(); |
| 219 | |
| 220 | D3DCreateBlob(fileSize, &bytecode); |
| 221 | memcpy(bytecode->GetBufferPointer(), buffer.data(), fileSize); |
| 222 |
nothing calls this directly
no test coverage detected