From b798fbb482adcf57ff814af7aa301e7460015211 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Tue, 24 Mar 2026 20:38:23 +0100 Subject: [PATCH 01/10] chore: remove old iw4 techset compiler --- .../Game/IW4/Techset/CompilerTechsetIW4.cpp | 1382 ----------------- .../Game/IW4/Techset/CompilerTechsetIW4.h | 26 - 2 files changed, 1408 deletions(-) delete mode 100644 src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.cpp delete mode 100644 src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.h diff --git a/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.cpp b/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.cpp deleted file mode 100644 index aa3a270ce..000000000 --- a/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.cpp +++ /dev/null @@ -1,1382 +0,0 @@ -#include "CompilerTechsetIW4.h" - -#include "Game/IW4/IW4.h" -#include "Game/IW4/Techset/TechsetConstantsIW4.h" -#include "Shader/D3D9ShaderAnalyser.h" -#include "Shader/ShaderCommon.h" -#include "Techset/CommonTechsetLoader.h" -#include "Techset/StateMap/StateMapReader.h" -#include "Techset/StateMap/TechniqueStateMapCache.h" -#include "Techset/TechsetCommon.h" -#include "Utils/Alignment.h" -#include "Utils/Logging/Log.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace IW4; -using namespace ::techset; -using namespace std::string_literals; - -namespace -{ - /* - class LoadedTechnique - { - public: - LoadedTechnique(MaterialTechnique* technique, std::vector dependencies) - : m_technique(technique), - m_dependencies(std::move(dependencies)) - { - } - - MaterialTechnique* m_technique; - std::vector m_dependencies; - }; - - class TechniqueZoneLoadingState final : public IZoneAssetCreationState - { - public: - typedef const float (*literal_t)[4]; - - [[nodiscard]] const LoadedTechnique* FindLoadedTechnique(const std::string& techniqueName) const - { - const auto loadedTechnique = m_loaded_techniques.find(techniqueName); - if (loadedTechnique != m_loaded_techniques.end()) - return loadedTechnique->second.get(); - - return nullptr; - } - - const LoadedTechnique* AddLoadedTechnique(std::string techniqueName, MaterialTechnique* technique, std::vector dependencies) - { - return m_loaded_techniques.emplace(std::make_pair(std::move(techniqueName), std::make_unique(technique, std::move(dependencies)))) - .first->second.get(); - } - - literal_t GetAllocatedLiteral(MemoryManager& memory, ShaderArgumentLiteralSource source) - { - const auto& existingEntry = m_allocated_literals.find(source); - - if (existingEntry != m_allocated_literals.end()) - return existingEntry->second; - - auto* newLiteral = memory.Alloc(); - (*newLiteral)[0] = source.m_value[0]; - (*newLiteral)[1] = source.m_value[1]; - (*newLiteral)[2] = source.m_value[2]; - (*newLiteral)[3] = source.m_value[3]; - m_allocated_literals.emplace(std::make_pair(source, newLiteral)); - - return newLiteral; - } - - private: - std::unordered_map> m_loaded_techniques; - std::map m_allocated_literals; - }; - - class ShaderInfoFromFileSystemCacheState final : public IZoneAssetCreationState - { - public: - [[nodiscard]] const d3d9::ShaderInfo* LoadShaderInfoFromDisk(ISearchPath& searchPath, const std::string& fileName) - { - const auto cachedShaderInfo = m_cached_shader_info.find(fileName); - if (cachedShaderInfo != m_cached_shader_info.end()) - return cachedShaderInfo->second.get(); - - const auto file = searchPath.Open(fileName); - if (!file.IsOpen()) - return nullptr; - - const auto shaderSize = static_cast(file.m_length); - - if (shaderSize % sizeof(uint32_t) != 0) - { - con::error("Invalid shader \"{}\": Size must be dividable by {}", fileName, sizeof(uint32_t)); - return nullptr; - } - - const auto shaderData = std::make_unique(shaderSize); - file.m_stream->read(shaderData.get(), static_cast(shaderSize)); - - auto shaderInfo = d3d9::ShaderAnalyser::GetShaderInfo(shaderData.get(), shaderSize); - if (!shaderInfo) - return nullptr; - - const auto* result = shaderInfo.get(); - m_cached_shader_info.emplace(std::make_pair(fileName, std::move(shaderInfo))); - return result; - } - - private: - std::unordered_map> m_cached_shader_info; - }; - - class TechniqueCreator final : public ITechniqueDefinitionAcceptor - { - public: - class PassShaderArgument - { - public: - explicit PassShaderArgument(const MaterialShaderArgument arg) - : m_arg(arg), - m_update_frequency(GetUpdateFrequencyForArg(arg)) - { - } - - static MaterialUpdateFrequency GetUpdateFrequencyForArg(const MaterialShaderArgument arg) - { - switch (arg.type) - { - case MTL_ARG_CODE_VERTEX_CONST: - case MTL_ARG_CODE_PIXEL_CONST: - if (arg.u.codeConst.index >= std::extent_v) - { - assert(false); - return MTL_UPDATE_RARELY; - } - return s_codeConstUpdateFreq[arg.u.codeConst.index]; - - case MTL_ARG_CODE_PIXEL_SAMPLER: - if (arg.u.codeSampler >= std::extent_v) - { - assert(false); - return MTL_UPDATE_RARELY; - } - return s_codeSamplerUpdateFreq[arg.u.codeSampler]; - - case MTL_ARG_MATERIAL_VERTEX_CONST: - case MTL_ARG_MATERIAL_PIXEL_SAMPLER: - case MTL_ARG_MATERIAL_PIXEL_CONST: - case MTL_ARG_LITERAL_VERTEX_CONST: - case MTL_ARG_LITERAL_PIXEL_CONST: - default: - return MTL_UPDATE_RARELY; - } - } - - MaterialShaderArgument m_arg; - MaterialUpdateFrequency m_update_frequency; - }; - - struct Pass - { - Pass() - : m_vertex_shader(nullptr), - m_vertex_shader_info(nullptr), - m_pixel_shader(nullptr), - m_pixel_shader_info(nullptr), - m_vertex_decl{}, - m_vertex_decl_asset(nullptr) - { - } - - XAssetInfo* m_vertex_shader; - const d3d9::ShaderInfo* m_vertex_shader_info; - std::unique_ptr m_vertex_shader_info_unq; - std::vector m_vertex_shader_argument_handled_offset; - std::vector m_handled_vertex_shader_arguments; - - XAssetInfo* m_pixel_shader; - const d3d9::ShaderInfo* m_pixel_shader_info; - std::unique_ptr m_pixel_shader_info_unq; - std::vector m_pixel_shader_argument_handled_offset; - std::vector m_handled_pixel_shader_arguments; - - MaterialVertexDeclaration m_vertex_decl; - XAssetInfo* m_vertex_decl_asset; - std::vector m_arguments; - }; - - TechniqueCreator(const std::string& techniqueName, - ISearchPath& searchPath, - MemoryManager& memory, - AssetCreationContext& context, - techset::ICreatorIW4* techsetCreator) - : m_technique_name(techniqueName), - m_search_path(searchPath), - m_memory(memory), - m_context(context), - m_zone_state(context.GetZoneAssetCreationState()), - m_state_map_cache(context.GetZoneAssetCreationState()), - m_shader_info_cache(context.GetZoneAssetCreationState()), - m_techset_creator(techsetCreator) - { - } - - void AcceptNextPass() override - { - m_passes.emplace_back(); - } - - static unsigned RegisterCountPerElement(const d3d9::ShaderConstant& constant) - { - const auto valuesPerRegister = - constant.m_register_set == d3d9::RegisterSet::BOOL || constant.m_register_set == d3d9::RegisterSet::SAMPLER ? 1u : 4u; - - return utils::Align(constant.m_type_columns * constant.m_type_rows, valuesPerRegister) / valuesPerRegister; - } - - static bool IsSamplerArgument(const d3d9::ShaderConstant& constant) - { - return constant.m_type == d3d9::ParameterType::SAMPLER || constant.m_type == d3d9::ParameterType::SAMPLER_1D - || constant.m_type == d3d9::ParameterType::SAMPLER_2D || constant.m_type == d3d9::ParameterType::SAMPLER_3D - || constant.m_type == d3d9::ParameterType::SAMPLER_CUBE; - } - - bool AutoCreateShaderArgument(const ShaderSelector shaderType, - const d3d9::ShaderConstant& shaderArgument, - const size_t elementOffset, - const size_t registerOffset) - { - assert(!m_passes.empty()); - auto& pass = m_passes.at(m_passes.size() - 1); - - const auto isSamplerArgument = IsSamplerArgument(shaderArgument); - if (shaderType == ShaderSelector::VERTEX_SHADER && isSamplerArgument) - return false; - - MaterialShaderArgument argument; - argument.dest = static_cast(shaderArgument.m_register_index + registerOffset); - - unsigned arrayCount; - const std::vector accessors({shaderArgument.m_name}); - if (isSamplerArgument) - { - const CodeSamplerSource* samplerSource = FindCodeSamplerSource(accessors, s_codeSamplers); - if (!samplerSource) - samplerSource = FindCodeSamplerSource(accessors, s_defaultCodeSamplers); - - if (!samplerSource) - return false; - - argument.type = MTL_ARG_CODE_PIXEL_SAMPLER; - argument.u.codeSampler = samplerSource->source + static_cast(elementOffset); - - arrayCount = static_cast(samplerSource->arrayCount); - } - else - { - const CodeConstantSource* constantSource = FindCodeConstantSource(accessors, s_codeConsts); - if (!constantSource) - constantSource = FindCodeConstantSource(accessors, s_defaultCodeConsts); - - if (!constantSource) - return false; - - argument.type = shaderType == ShaderSelector::VERTEX_SHADER ? MTL_ARG_CODE_VERTEX_CONST : MTL_ARG_CODE_PIXEL_CONST; - argument.u.codeConst.index = static_cast(constantSource->source + elementOffset); - argument.u.codeConst.firstRow = 0u; - argument.u.codeConst.rowCount = static_cast(shaderArgument.m_type_rows); - - arrayCount = static_cast(constantSource->arrayCount); - } - - if (elementOffset >= std::max(arrayCount, 1u)) - return false; - - pass.m_arguments.emplace_back(argument); - return true; - } - - bool AutoCreateVertexShaderArguments(std::string& errorMessage) - { - assert(!m_passes.empty()); - const auto& pass = m_passes.at(m_passes.size() - 1); - - for (auto i = 0u; i < pass.m_vertex_shader_argument_handled_offset.size(); i++) - { - const auto& argument = pass.m_vertex_shader_info->m_constants[i]; - const auto argumentHandledIndex = pass.m_vertex_shader_argument_handled_offset[i]; - const auto argumentRegistersPerElement = argument.m_type_elements > 1u ? RegisterCountPerElement(argument) : argument.m_register_count; - - auto elementIndex = 0u; - for (auto registerIndex = 0u; registerIndex < argument.m_register_count; registerIndex += argumentRegistersPerElement) - { - if (!pass.m_handled_vertex_shader_arguments[argumentHandledIndex + elementIndex]) - { - if (!AutoCreateShaderArgument(ShaderSelector::VERTEX_SHADER, argument, elementIndex, registerIndex)) - { - std::string elementIndexStr; - if (argument.m_type_elements > 1) - elementIndexStr = std::format("[{}]", elementIndex); - - errorMessage = - std::format("Unassigned vertex shader \"{}\" arg: {}{}", pass.m_vertex_shader->m_name, argument.m_name, elementIndexStr); - return false; - } - } - - elementIndex++; - } - } - - return true; - } - - bool AutoCreatePixelShaderArguments(std::string& errorMessage) - { - assert(!m_passes.empty()); - const auto& pass = m_passes.at(m_passes.size() - 1); - - for (auto i = 0u; i < pass.m_pixel_shader_argument_handled_offset.size(); i++) - { - const auto& argument = pass.m_pixel_shader_info->m_constants[i]; - const auto argumentHandledIndex = pass.m_pixel_shader_argument_handled_offset[i]; - const auto argumentRegistersPerElement = argument.m_type_elements > 1u ? RegisterCountPerElement(argument) : argument.m_register_count; - - auto elementIndex = 0u; - for (auto registerIndex = 0u; registerIndex < argument.m_register_count; registerIndex += argumentRegistersPerElement) - { - if (!pass.m_handled_pixel_shader_arguments[argumentHandledIndex + elementIndex]) - { - if (!AutoCreateShaderArgument(ShaderSelector::PIXEL_SHADER, argument, elementIndex, registerIndex)) - { - std::ostringstream ss; - ss << "Unassigned pixel shader \"" << pass.m_pixel_shader->m_name << "\" arg: " << argument.m_name; - - if (argument.m_type_elements > 1) - ss << '[' << elementIndex << ']'; - - errorMessage = ss.str(); - return false; - } - } - - elementIndex++; - } - } - - return true; - } - - void AllocateVertexDecl() - { - assert(!m_passes.empty()); - auto& pass = m_passes.at(m_passes.size() - 1); - - std::sort(std::begin(pass.m_vertex_decl.routing.data), - std::begin(pass.m_vertex_decl.routing.data) + pass.m_vertex_decl.streamCount, - [](const MaterialStreamRouting& r1, const MaterialStreamRouting& r2) - { - return r1.source < r2.source; - }); - - std::ostringstream ss; - for (auto i = 0u; i < pass.m_vertex_decl.streamCount; i++) - { - const auto& stream = pass.m_vertex_decl.routing.data[i]; - assert(stream.source < std::extent_v); - assert(stream.dest < std::extent_v); - - ss << materialStreamSourceAbbreviation[stream.source] << materialStreamDestinationAbbreviation[stream.dest]; - } - - pass.m_vertex_decl_asset = m_context.LoadDependency(ss.str()); - } - - bool AcceptEndPass(std::string& errorMessage) override - { - assert(!m_passes.empty()); - auto& pass = m_passes.at(m_passes.size() - 1); - - if (!AutoCreateVertexShaderArguments(errorMessage) || !AutoCreatePixelShaderArguments(errorMessage)) - return false; - - // Sort args by their update frequency - std::ranges::sort(pass.m_arguments, - [](const PassShaderArgument& arg1, const PassShaderArgument& arg2) - { - if (arg1.m_update_frequency != arg2.m_update_frequency) - return arg1.m_update_frequency < arg2.m_update_frequency; - - if (arg1.m_arg.type != arg2.m_arg.type) - return arg1.m_arg.type < arg2.m_arg.type; - - if (arg1.m_arg.type == MTL_ARG_MATERIAL_VERTEX_CONST || arg1.m_arg.type == MTL_ARG_MATERIAL_PIXEL_CONST - || arg1.m_arg.type == MTL_ARG_MATERIAL_PIXEL_SAMPLER) - return arg1.m_arg.u.nameHash < arg2.m_arg.u.nameHash; - - return arg1.m_arg.dest < arg2.m_arg.dest; - }); - - AllocateVertexDecl(); - - return true; - } - - bool AcceptStateMap(const std::string& stateMapName, std::string& errorMessage) override - { - const auto* stateMap = m_techset_creator->LoadStateMapDefinition(stateMapName, m_context); - - if (!stateMap) - { - std::ostringstream ss; - ss << std::format("Failed to load specified state map \"{}\"", stateMapName); - errorMessage = ss.str(); - return false; - } - - m_state_map_cache.SetTechniqueUsesStateMap(m_technique_name, stateMap); - return true; - } - - static void InitializeArgumentState(const d3d9::ShaderInfo& shaderInfo, - std::vector& argumentHandledOffsetVector, - std::vector& argumentHandledVector) - { - auto vertexShaderArgumentSlotCount = 0u; - auto argIndex = 0u; - argumentHandledOffsetVector.resize(shaderInfo.m_constants.size()); - for (const auto& arg : shaderInfo.m_constants) - { - argumentHandledOffsetVector[argIndex++] = vertexShaderArgumentSlotCount; - - if (arg.m_type_elements > 1) - vertexShaderArgumentSlotCount += arg.m_register_count / RegisterCountPerElement(arg); - else - vertexShaderArgumentSlotCount++; - } - argumentHandledVector.resize(vertexShaderArgumentSlotCount); - } - - bool AcceptVertexShader(const std::string& vertexShaderName, std::string& errorMessage) override - { - auto* vertexShaderDependency = m_context.LoadDependency(vertexShaderName); - if (vertexShaderDependency == nullptr) - { - errorMessage = std::format("Failed to load specified shader \"{}\"", vertexShaderName); - return false; - } - - assert(!m_passes.empty()); - auto& pass = m_passes.at(m_passes.size() - 1); - pass.m_vertex_shader = vertexShaderDependency; - - if (pass.m_vertex_shader->Asset()->name && pass.m_vertex_shader->Asset()->name[0] == ',') - { - pass.m_vertex_shader_info = - m_shader_info_cache.LoadShaderInfoFromDisk(m_search_path, ::shader::GetFileNameForVertexShaderAssetName(vertexShaderName)); - } - else - { - const auto& shaderLoadDef = pass.m_vertex_shader->Asset()->prog.loadDef; - pass.m_vertex_shader_info_unq = d3d9::ShaderAnalyser::GetShaderInfo(shaderLoadDef.program, shaderLoadDef.programSize * sizeof(uint32_t)); - pass.m_vertex_shader_info = pass.m_vertex_shader_info_unq.get(); - } - - if (!pass.m_vertex_shader_info) - { - errorMessage = std::format("No shader info for shader \"{}\"", vertexShaderName); - return false; - } - - InitializeArgumentState(*pass.m_vertex_shader_info, pass.m_vertex_shader_argument_handled_offset, pass.m_handled_vertex_shader_arguments); - - return true; - } - - bool AcceptPixelShader(const std::string& pixelShaderName, std::string& errorMessage) override - { - auto* pixelShaderDependency = m_context.LoadDependency(pixelShaderName); - if (pixelShaderDependency == nullptr) - { - errorMessage = std::format("Failed to load specified shader \"{}\"", pixelShaderName); - return false; - } - - assert(!m_passes.empty()); - auto& pass = m_passes.at(m_passes.size() - 1); - pass.m_pixel_shader = pixelShaderDependency; - - if (pass.m_pixel_shader->Asset()->name && pass.m_pixel_shader->Asset()->name[0] == ',') - { - pass.m_pixel_shader_info = - m_shader_info_cache.LoadShaderInfoFromDisk(m_search_path, ::shader::GetFileNameForPixelShaderAssetName(pixelShaderName)); - } - else - { - const auto& shaderLoadDef = pass.m_pixel_shader->Asset()->prog.loadDef; - pass.m_pixel_shader_info_unq = d3d9::ShaderAnalyser::GetShaderInfo(shaderLoadDef.program, shaderLoadDef.programSize * sizeof(uint32_t)); - pass.m_pixel_shader_info = pass.m_pixel_shader_info_unq.get(); - } - - if (!pass.m_pixel_shader_info) - { - errorMessage = std::format("No shader info for shader \"{}\"", pixelShaderName); - return false; - } - - InitializeArgumentState(*pass.m_pixel_shader_info, pass.m_pixel_shader_argument_handled_offset, pass.m_handled_pixel_shader_arguments); - - return true; - } - - static const CodeConstantSource* FindCodeConstantSource(const std::vector& accessors, const CodeConstantSource* sourceTable) - { - const CodeConstantSource* foundSource = nullptr; - const CodeConstantSource* currentTable = sourceTable; - for (const auto& accessor : accessors) - { - if (currentTable == nullptr) - return nullptr; - - while (true) - { - if (currentTable->name == nullptr) - return nullptr; - - if (accessor == currentTable->name) - break; - - currentTable++; - } - - foundSource = currentTable; - currentTable = currentTable->subtable; - } - - return foundSource; - } - - static const CodeSamplerSource* FindCodeSamplerSource(const std::vector& accessors, const CodeSamplerSource* sourceTable) - { - const CodeSamplerSource* foundSource = nullptr; - const CodeSamplerSource* currentTable = sourceTable; - for (const auto& accessor : accessors) - { - if (currentTable == nullptr) - return nullptr; - - while (true) - { - if (currentTable->name == nullptr) - return nullptr; - - if (accessor == currentTable->name) - break; - - currentTable++; - } - - foundSource = currentTable; - currentTable = currentTable->subtable; - } - - return foundSource; - } - - static bool FindShaderArgument( - const d3d9::ShaderInfo& shaderInfo, const ShaderArgument& argument, size_t& constantIndex, size_t& registerOffset, std::string& errorMessage) - { - const auto matchingShaderConstant = std::ranges::find_if(shaderInfo.m_constants, - [argument](const d3d9::ShaderConstant& constant) - { - return constant.m_name == argument.m_argument_name; - }); - - if (matchingShaderConstant == shaderInfo.m_constants.end()) - { - errorMessage = "Could not find argument in shader"; - return false; - } - - if (argument.m_argument_index_specified) - { - if (matchingShaderConstant->m_type_elements <= 1) - { - errorMessage = "Argument does not have more than one element"; - return false; - } - - const auto registersPerElement = RegisterCountPerElement(*matchingShaderConstant); - if (argument.m_argument_index >= matchingShaderConstant->m_register_count / registersPerElement) - { - errorMessage = "Argument index out of bounds"; - return false; - } - - registerOffset = argument.m_argument_index * registersPerElement; - } - else if (matchingShaderConstant->m_type_elements > 1) - { - errorMessage = "Argument has more than one element and needs to be accessed with an index"; - return false; - } - else - { - registerOffset = 0u; - } - - constantIndex = static_cast(matchingShaderConstant - shaderInfo.m_constants.begin()); - return true; - } - - static bool SetArgumentCodeConst(MaterialShaderArgument& argument, - const ShaderArgumentCodeSource& source, - const d3d9::ShaderConstant& shaderConstant, - const unsigned sourceIndex, - const unsigned arrayCount, - std::string& errorMessage) - { - if (arrayCount > 0u) - { - if (!source.m_index_accessor_specified) - { - errorMessage = "Code constant must have array index specified"; - return false; - } - - if (source.m_index_accessor >= arrayCount) - { - errorMessage = "Code constant array index out of bounds"; - return false; - } - - argument.u.codeConst.index = static_cast(sourceIndex + source.m_index_accessor); - } - else if (source.m_index_accessor_specified) - { - errorMessage = "Code constant cannot have array index specified"; - return false; - } - else - { - argument.u.codeConst.index = static_cast(sourceIndex); - } - argument.u.codeConst.firstRow = 0u; - argument.u.codeConst.rowCount = static_cast(shaderConstant.m_type_rows); - - return true; - } - - static bool SetArgumentCodeSampler(MaterialShaderArgument& argument, - const ShaderArgumentCodeSource& source, - const d3d9::ShaderConstant& shaderConstant, - const unsigned sourceIndex, - const unsigned arrayCount, - std::string& errorMessage) - { - if (arrayCount > 0u) - { - if (!source.m_index_accessor_specified) - { - errorMessage = "Code constant must have array index specified"; - return false; - } - - if (source.m_index_accessor >= arrayCount) - { - errorMessage = "Code constant array index out of bounds"; - return false; - } - - argument.u.codeSampler = sourceIndex + source.m_index_accessor; - } - else if (source.m_index_accessor_specified) - { - errorMessage = "Code constant cannot have array index specified"; - return false; - } - else - { - argument.u.codeSampler = sourceIndex; - } - - return true; - } - - bool AcceptVertexShaderConstantArgument(const ShaderArgument& shaderArgument, const ShaderArgumentCodeSource& source, std::string& errorMessage) - { - assert(!m_passes.empty()); - auto& pass = m_passes.at(m_passes.size() - 1); - - if (!pass.m_vertex_shader_info) - { - errorMessage = "Shader not specified"; - return false; - } - - size_t shaderConstantIndex = 0u; - size_t registerOffset = 0u; - if (!FindShaderArgument(*pass.m_vertex_shader_info, shaderArgument, shaderConstantIndex, registerOffset, errorMessage)) - return false; - - const auto elementOffset = shaderArgument.m_argument_index_specified ? shaderArgument.m_argument_index : 0u; - const auto& shaderConstant = pass.m_vertex_shader_info->m_constants[shaderConstantIndex]; - const auto argumentIsSampler = IsSamplerArgument(shaderConstant); - if (argumentIsSampler) - { - errorMessage = "Vertex shader argument expected sampler but got constant"; - return false; - } - - MaterialShaderArgument argument{}; - argument.type = MTL_ARG_CODE_VERTEX_CONST; - argument.dest = static_cast(shaderConstant.m_register_index + registerOffset); - - const CodeConstantSource* constantSource = FindCodeConstantSource(source.m_accessors, s_codeConsts); - if (!constantSource) - constantSource = FindCodeConstantSource(source.m_accessors, s_defaultCodeConsts); - - if (!constantSource) - { - errorMessage = "Unknown code constant"; - return false; - } - - if (!SetArgumentCodeConst(argument, source, shaderConstant, constantSource->source, constantSource->arrayCount, errorMessage)) - return false; - - pass.m_arguments.emplace_back(argument); - pass.m_handled_vertex_shader_arguments[pass.m_vertex_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; - - return true; - } - - bool AcceptPixelShaderCodeArgument(const ShaderArgument& shaderArgument, - const ShaderArgumentCodeSource& source, - std::string& errorMessage, - const bool isSampler) - { - assert(!m_passes.empty()); - auto& pass = m_passes.at(m_passes.size() - 1); - - if (!pass.m_pixel_shader_info) - { - errorMessage = "Shader not specified"; - return false; - } - - size_t shaderConstantIndex = 0u; - size_t registerOffset = 0u; - if (!FindShaderArgument(*pass.m_pixel_shader_info, shaderArgument, shaderConstantIndex, registerOffset, errorMessage)) - return false; - - const auto elementOffset = shaderArgument.m_argument_index_specified ? shaderArgument.m_argument_index : 0u; - const auto& shaderConstant = pass.m_pixel_shader_info->m_constants[shaderConstantIndex]; - const auto argumentIsSampler = IsSamplerArgument(shaderConstant); - if (argumentIsSampler && !isSampler) - { - errorMessage = "Pixel shader argument expects sampler but got constant"; - return false; - } - else if (!argumentIsSampler && isSampler) - { - errorMessage = "Pixel shader argument expects constant but got sampler"; - return false; - } - - MaterialShaderArgument argument{}; - argument.type = isSampler ? MTL_ARG_CODE_PIXEL_SAMPLER : MTL_ARG_CODE_PIXEL_CONST; - argument.dest = static_cast(shaderConstant.m_register_index + registerOffset); - - unsigned sourceIndex, arrayCount; - if (isSampler) - { - const CodeSamplerSource* samplerSource = FindCodeSamplerSource(source.m_accessors, s_codeSamplers); - if (!samplerSource) - samplerSource = FindCodeSamplerSource(source.m_accessors, s_defaultCodeSamplers); - - if (!samplerSource) - { - errorMessage = "Unknown code sampler"; - return false; - } - - sourceIndex = static_cast(samplerSource->source); - arrayCount = static_cast(samplerSource->arrayCount); - - if (!SetArgumentCodeSampler(argument, source, shaderConstant, sourceIndex, arrayCount, errorMessage)) - return false; - } - else - { - const CodeConstantSource* constantSource = FindCodeConstantSource(source.m_accessors, s_codeConsts); - if (!constantSource) - constantSource = FindCodeConstantSource(source.m_accessors, s_defaultCodeConsts); - - if (!constantSource) - { - errorMessage = "Unknown code constant"; - return false; - } - - sourceIndex = static_cast(constantSource->source); - arrayCount = static_cast(constantSource->arrayCount); - - if (!SetArgumentCodeConst(argument, source, shaderConstant, sourceIndex, arrayCount, errorMessage)) - return false; - } - - pass.m_arguments.emplace_back(argument); - pass.m_handled_pixel_shader_arguments[pass.m_pixel_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; - - return true; - } - - bool AcceptShaderConstantArgument(const ShaderSelector shader, - const ShaderArgument shaderArgument, - const ShaderArgumentCodeSource source, - std::string& errorMessage) override - { - if (shader == ShaderSelector::VERTEX_SHADER) - return AcceptVertexShaderConstantArgument(shaderArgument, source, errorMessage); - - assert(shader == ShaderSelector::PIXEL_SHADER); - return AcceptPixelShaderCodeArgument(shaderArgument, source, errorMessage, false); - } - - bool AcceptShaderSamplerArgument(const ShaderSelector shader, - const ShaderArgument shaderArgument, - const ShaderArgumentCodeSource source, - std::string& errorMessage) override - { - if (shader == ShaderSelector::VERTEX_SHADER) - { - errorMessage = "Vertex sampler are unsupported"; - return false; - } - - assert(shader == ShaderSelector::PIXEL_SHADER); - return AcceptPixelShaderCodeArgument(shaderArgument, source, errorMessage, true); - } - - bool AcceptShaderLiteralArgument(const ShaderSelector shader, - const ShaderArgument shaderArgument, - const ShaderArgumentLiteralSource source, - std::string& errorMessage) override - { - assert(!m_passes.empty()); - auto& pass = m_passes.at(m_passes.size() - 1); - - MaterialShaderArgument argument; - const d3d9::ShaderInfo* shaderInfo; - - if (shader == ShaderSelector::VERTEX_SHADER) - { - argument.type = MTL_ARG_LITERAL_VERTEX_CONST; - shaderInfo = pass.m_vertex_shader_info; - } - else - { - assert(shader == ShaderSelector::PIXEL_SHADER); - argument.type = MTL_ARG_LITERAL_PIXEL_CONST; - shaderInfo = pass.m_pixel_shader_info; - } - - if (!shaderInfo) - { - errorMessage = "Shader not specified"; - return false; - } - - size_t shaderConstantIndex = 0u; - size_t registerOffset = 0u; - if (!FindShaderArgument(*shaderInfo, shaderArgument, shaderConstantIndex, registerOffset, errorMessage)) - return false; - - const auto elementOffset = shaderArgument.m_argument_index_specified ? shaderArgument.m_argument_index : 0u; - const auto& shaderConstant = shaderInfo->m_constants[shaderConstantIndex]; - const auto argumentIsSampler = IsSamplerArgument(shaderConstant); - if (argumentIsSampler) - { - if (shader == ShaderSelector::VERTEX_SHADER) - errorMessage = "Vertex shader argument expects sampler but got constant"; - else - errorMessage = "Pixel shader argument expects sampler but got constant"; - - return false; - } - - argument.dest = static_cast(shaderConstant.m_register_index + registerOffset); - argument.u.literalConst = m_zone_state.GetAllocatedLiteral(m_memory, source); - pass.m_arguments.emplace_back(argument); - - if (shader == ShaderSelector::VERTEX_SHADER) - pass.m_handled_vertex_shader_arguments[pass.m_vertex_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; - else - pass.m_handled_pixel_shader_arguments[pass.m_pixel_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; - - return true; - } - - bool AcceptShaderMaterialArgument(const ShaderSelector shader, - const ShaderArgument shaderArgument, - const ShaderArgumentMaterialSource source, - std::string& errorMessage) override - { - assert(!m_passes.empty()); - auto& pass = m_passes.at(m_passes.size() - 1); - - MaterialShaderArgument argument; - const d3d9::ShaderInfo* shaderInfo; - - if (shader == ShaderSelector::VERTEX_SHADER) - { - shaderInfo = pass.m_vertex_shader_info; - } - else - { - assert(shader == ShaderSelector::PIXEL_SHADER); - shaderInfo = pass.m_pixel_shader_info; - } - - if (!shaderInfo) - { - errorMessage = "Shader not specified"; - return false; - } - - size_t shaderConstantIndex = 0u; - size_t registerOffset = 0u; - if (!FindShaderArgument(*shaderInfo, shaderArgument, shaderConstantIndex, registerOffset, errorMessage)) - return false; - - const auto elementOffset = shaderArgument.m_argument_index_specified ? shaderArgument.m_argument_index : 0u; - const auto& shaderConstant = shaderInfo->m_constants[shaderConstantIndex]; - const auto argumentIsSampler = IsSamplerArgument(shaderConstant); - if (shader == ShaderSelector::VERTEX_SHADER) - { - if (argumentIsSampler) - { - errorMessage = "Vertex sampler are unsupported"; - return false; - } - argument.type = MTL_ARG_MATERIAL_VERTEX_CONST; - } - else - { - assert(shader == ShaderSelector::PIXEL_SHADER); - argument.type = !argumentIsSampler ? MTL_ARG_MATERIAL_PIXEL_CONST : MTL_ARG_MATERIAL_PIXEL_SAMPLER; - } - - if (source.m_is_hash) - argument.u.nameHash = static_cast(source.m_hash); - else - argument.u.nameHash = Common::R_HashString(source.m_name.c_str(), 0u); - - argument.dest = static_cast(shaderConstant.m_register_index + registerOffset); - pass.m_arguments.emplace_back(argument); - - if (shader == ShaderSelector::VERTEX_SHADER) - pass.m_handled_vertex_shader_arguments[pass.m_vertex_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; - else - pass.m_handled_pixel_shader_arguments[pass.m_pixel_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; - - return true; - } - - bool AcceptVertexStreamRouting(const std::string& destination, const std::string& source, std::string& errorMessage) override - { - assert(!m_passes.empty()); - auto& pass = m_passes.at(m_passes.size() - 1); - - const auto streamIndex = static_cast(pass.m_vertex_decl.streamCount); - if (pass.m_vertex_decl.streamCount >= std::extent_v) - { - errorMessage = "Too many stream routings"; - return false; - } - - const auto foundDestination = std::ranges::find(materialStreamDestinationNames, destination); - if (foundDestination == std::end(materialStreamDestinationNames)) - { - errorMessage = "Unknown stream destination"; - return false; - } - - const auto foundSource = std::ranges::find(materialStreamSourceNames, source); - if (foundSource == std::end(materialStreamSourceNames)) - { - errorMessage = "Unknown stream source"; - return false; - } - - const auto destinationIndex = static_cast(foundDestination - std::begin(materialStreamDestinationNames)); - const auto sourceIndex = static_cast(foundSource - std::begin(materialStreamSourceNames)); - - pass.m_vertex_decl.routing.data[streamIndex].dest = destinationIndex; - pass.m_vertex_decl.routing.data[streamIndex].source = sourceIndex; - - pass.m_vertex_decl.hasOptionalSource = pass.m_vertex_decl.hasOptionalSource || sourceIndex >= STREAM_SRC_OPTIONAL_BEGIN; - - pass.m_vertex_decl.streamCount++; - return true; - } - - std::vector m_passes; - - private: - const std::string& m_technique_name; - ISearchPath& m_search_path; - MemoryManager& m_memory; - AssetCreationContext& m_context; - TechniqueZoneLoadingState& m_zone_state; - TechniqueStateMapCache& m_state_map_cache; - ShaderInfoFromFileSystemCacheState& m_shader_info_cache; - techset::ICreatorIW4* m_techset_creator; - }; - - class TechniqueLoader - { - public: - TechniqueLoader(ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context, techset::ICreatorIW4* techsetCreator) - : m_search_path(searchPath), - m_memory(memory), - m_context(context), - m_zone_state(context.GetZoneAssetCreationState()), - m_techset_creator(techsetCreator) - { - } - - [[nodiscard]] const LoadedTechnique* LoadMaterialTechnique(const std::string& techniqueName) const - { - auto* technique = m_zone_state.FindLoadedTechnique(techniqueName); - if (technique) - return technique; - - std::vector dependencies; - auto* techniqueFromRaw = LoadTechniqueFromRaw(techniqueName, dependencies); - if (techniqueFromRaw == nullptr) - return nullptr; - - return m_zone_state.AddLoadedTechnique(techniqueName, techniqueFromRaw, dependencies); - } - - private: - static void UpdateTechniqueFlags(MaterialTechnique& technique) - { - // This is stupid but that's what the game does for zprepass for sure - // The other ones might be handled by the game in the same fashion because there is not recognizable pattern that connects the shaders with the same - // flags - static std::unordered_map flagsByTechniqueName({ - {"zprepass", MTL_TECHFLAG_ZPREPASS | TECHNIQUE_FLAG_200 }, - {"build_floatz", MTL_TECHFLAG_BUILD_FLOATZ }, - {"build_shadowmap_depth", MTL_TECHFLAG_BUILD_SHADOW_MAP_DEPTH_OR_MODEL | TECHNIQUE_FLAG_200}, - {"build_shadowmap_model", MTL_TECHFLAG_BUILD_SHADOW_MAP_DEPTH_OR_MODEL | TECHNIQUE_FLAG_200}, - {"distortion_scale_ua_zfeather", MTL_TECHFLAG_USES_DISTORTION_FLOATZ }, - {"distortion_scale_zfeather", MTL_TECHFLAG_USES_DISTORTION_FLOATZ }, - {"distortion_scale_zfeather_dtex", MTL_TECHFLAG_USES_DISTORTION_FLOATZ }, - {"alternate_scene_overlay", TECHNIQUE_FLAG_200 }, - {"blur_apply", TECHNIQUE_FLAG_200 }, - {"build_floatz", TECHNIQUE_FLAG_200 }, - {"build_floatz_clear", TECHNIQUE_FLAG_200 }, - {"build_floatz_dtex", TECHNIQUE_FLAG_200 }, - {"build_floatz_ua", TECHNIQUE_FLAG_200 }, - {"build_floatz_ua_dtex", TECHNIQUE_FLAG_200 }, - {"build_shadowmap_depth_nc", TECHNIQUE_FLAG_200 }, - {"build_shadowmap_depth_ua", TECHNIQUE_FLAG_200 }, - {"build_shadowmap_model_dtex", TECHNIQUE_FLAG_200 }, - {"build_shadowmap_model_nc_dtex", TECHNIQUE_FLAG_200 }, - {"build_shadowmap_model_ua", TECHNIQUE_FLAG_200 }, - {"cinematic", TECHNIQUE_FLAG_200 }, - {"cinematic_3d", TECHNIQUE_FLAG_200 }, - {"cinematic_dtex_3d", TECHNIQUE_FLAG_200 }, - {"dof_near_coc", TECHNIQUE_FLAG_200 }, - {"floatz", TECHNIQUE_FLAG_200 }, - {"floatzdisplay", TECHNIQUE_FLAG_200 }, - {"particle_blend", TECHNIQUE_FLAG_200 }, - {"particle_zdownsample", TECHNIQUE_FLAG_200 }, - {"passthru_alpha", TECHNIQUE_FLAG_200 }, - {"postfx", TECHNIQUE_FLAG_200 }, - {"postfx_mblur", TECHNIQUE_FLAG_200 }, - {"processed_floatz", TECHNIQUE_FLAG_200 }, - {"ps3_aadownsample", TECHNIQUE_FLAG_200 }, - {"shell_shock", TECHNIQUE_FLAG_200 }, - {"shell_shock_flashed", TECHNIQUE_FLAG_200 }, - {"small_blur", TECHNIQUE_FLAG_200 }, - {"stencildisplay", TECHNIQUE_FLAG_200 }, - {"stencilshadow", TECHNIQUE_FLAG_200 }, - {"wireframe_solid", TECHNIQUE_FLAG_200 }, - {"wireframe_solid_atest_dtex", TECHNIQUE_FLAG_200 }, - {"wireframe_solid_dtex", TECHNIQUE_FLAG_200 }, - {"wireframe_solid_nc", TECHNIQUE_FLAG_200 }, - {"wireframe_solid_nc_dtex", TECHNIQUE_FLAG_200 }, - {"wireframe_solid_ua", TECHNIQUE_FLAG_200 }, - {"wireframe_solid_ua_dtex", TECHNIQUE_FLAG_200 }, - }); - - const auto flagsForName = flagsByTechniqueName.find(technique.name); - if (flagsForName != flagsByTechniqueName.end()) - { - technique.flags |= flagsForName->second; - } - - for (auto i = 0u; i < technique.passCount; i++) - { - const auto& pass = technique.passArray[i]; - if (pass.vertexDecl && pass.vertexDecl->hasOptionalSource) - { - technique.flags |= MTL_TECHFLAG_DECL_HAS_OPTIONAL_SOURCE; - break; - } - } - } - - static void UpdateTechniqueFlagsForArgument(uint16_t& techniqueFlags, const TechniqueCreator::PassShaderArgument& arg) - { - if (arg.m_arg.type == MTL_ARG_CODE_PIXEL_SAMPLER) - { - switch (arg.m_arg.u.codeSampler) - { - case TEXTURE_SRC_CODE_RESOLVED_POST_SUN: - techniqueFlags |= MTL_TECHFLAG_NEEDS_RESOLVED_POST_SUN; - break; - case TEXTURE_SRC_CODE_RESOLVED_SCENE: - techniqueFlags |= MTL_TECHFLAG_NEEDS_RESOLVED_SCENE; - break; - case TEXTURE_SRC_CODE_FLOATZ: - case TEXTURE_SRC_CODE_PROCESSED_FLOATZ: - case TEXTURE_SRC_CODE_RAW_FLOATZ: - if ((techniqueFlags & MTL_TECHFLAG_USES_DISTORTION_FLOATZ) == 0) - techniqueFlags |= MTL_TECHFLAG_USES_FLOATZ; - break; - default: - break; - } - } - else if (arg.m_arg.type == MTL_ARG_CODE_VERTEX_CONST || arg.m_arg.type == MTL_ARG_CODE_PIXEL_CONST) - { - switch (arg.m_arg.u.codeConst.index) - { - case CONST_SRC_CODE_LIGHT_SPOTDIR: - case CONST_SRC_CODE_LIGHT_SPOTFACTORS: - techniqueFlags |= MTL_TECHFLAG_USES_LIGHT_SPOT_FACTORS; - break; - default: - break; - } - } - } - - void ConvertPass(MaterialTechnique& technique, MaterialPass& out, const TechniqueCreator::Pass& in, std::vector& dependencies) const - { - out.customSamplerFlags = 0u; - out.vertexShader = in.m_vertex_shader->Asset(); - out.pixelShader = in.m_pixel_shader->Asset(); - out.vertexDecl = in.m_vertex_decl_asset->Asset(); - - out.args = m_memory.Alloc(in.m_arguments.size()); - - size_t perObjArgCount = 0u; - size_t perPrimArgCount = 0u; - size_t stableArgCount = 0u; - size_t argIndex = 0u; - for (const auto& arg : in.m_arguments) - { - UpdateTechniqueFlagsForArgument(technique.flags, arg); - switch (arg.m_update_frequency) - { - case MTL_UPDATE_PER_PRIM: - perPrimArgCount++; - break; - case MTL_UPDATE_PER_OBJECT: - perObjArgCount++; - break; - case MTL_UPDATE_RARELY: - stableArgCount++; - break; - case MTL_UPDATE_CUSTOM: - { - assert(arg.m_arg.type == MTL_ARG_CODE_PIXEL_SAMPLER); - if (arg.m_arg.type == MTL_ARG_CODE_PIXEL_SAMPLER) - { - const auto customSampler = std::ranges::find(g_customSamplerSrc, arg.m_arg.u.codeSampler); - assert(customSampler != std::end(g_customSamplerSrc)); - if (customSampler != std::end(g_customSamplerSrc)) - { - const auto customSamplerIndex = customSampler - std::begin(g_customSamplerSrc); - out.customSamplerFlags |= 1 << customSamplerIndex; - } - } - } - continue; - default: - assert(false); - continue; - } - - out.args[argIndex++] = arg.m_arg; - } - - out.perObjArgCount = static_cast(perObjArgCount); - out.perPrimArgCount = static_cast(perPrimArgCount); - out.stableArgCount = static_cast(stableArgCount); - - if (in.m_vertex_shader) - dependencies.push_back(in.m_vertex_shader); - if (in.m_pixel_shader) - dependencies.push_back(in.m_pixel_shader); - if (in.m_vertex_decl_asset) - dependencies.push_back(in.m_vertex_decl_asset); - } - - MaterialTechnique* ConvertTechnique(const std::string& techniqueName, - const std::vector& passes, - std::vector& dependencies) const - { - assert(!passes.empty()); - const auto techniqueSize = sizeof(MaterialTechnique) + (passes.size() - 1u) * sizeof(MaterialPass); - auto* technique = static_cast(m_memory.AllocRaw(techniqueSize)); - technique->name = m_memory.Dup(techniqueName.c_str()); - technique->passCount = static_cast(passes.size()); - - UpdateTechniqueFlags(*technique); - - for (auto i = 0u; i < passes.size(); i++) - ConvertPass(*technique, technique->passArray[i], passes.at(i), dependencies); - - return technique; - } - - MaterialTechnique* LoadTechniqueFromRaw(const std::string& techniqueName, std::vector& dependencies) const - { - const auto techniqueFileName = GetFileNameForTechniqueName(techniqueName); - const auto file = m_search_path.Open(techniqueFileName); - if (!file.IsOpen()) - return nullptr; - - TechniqueCreator creator(techniqueName, m_search_path, m_memory, m_context, m_techset_creator); - const TechniqueFileReader reader(*file.m_stream, techniqueFileName, &creator); - if (!reader.ReadTechniqueDefinition()) - return nullptr; - - return ConvertTechnique(techniqueName, creator.m_passes, dependencies); - } - - ISearchPath& m_search_path; - MemoryManager& m_memory; - AssetCreationContext& m_context; - TechniqueZoneLoadingState& m_zone_state; - techset::ICreatorIW4* m_techset_creator; - }; - */ - class TechsetLoader final : public techset::ICreatorIW4 - { - public: - TechsetLoader(MemoryManager& memory, ISearchPath& searchPath) - : m_memory(memory), - m_search_path(searchPath) - { - } - - AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override - { - return AssetCreationResult::NoAction(); - /* - bool failure = false; - const auto* techsetDefinition = LoadTechsetDefinition(assetName, context, failure); - if (!techsetDefinition) - return failure ? AssetCreationResult::Failure() : AssetCreationResult::NoAction(); - - return CreateTechsetFromDefinition(assetName, *techsetDefinition, context); - */ - } - - /* - AssetCreationResult CreateTechsetFromDefinition(const std::string& assetName, const CommonTechset& definition, AssetCreationContext& context) - { - auto* techset = m_memory.Alloc(); - techset->name = m_memory.Dup(assetName.c_str()); - - AssetRegistration registration(assetName, techset); - - const TechniqueLoader techniqueLoader(m_search_path, m_memory, context, this); - for (auto i = 0u; i < std::extent_v; i++) - { - const auto& techniqueName = definition.m_technique_names[i]; - if (!techniqueName.empty()) - { - auto* technique = techniqueLoader.LoadMaterialTechnique(techniqueName); - - if (!technique) - return AssetCreationResult::Failure(); - - for (auto* techniqueDependency : technique->m_dependencies) - registration.AddDependency(techniqueDependency); - - techset->techniques[i] = technique->m_technique; - } - } - - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); - } - */ - - CommonTechset* LoadTechsetDefinition(const std::string& assetName, AssetCreationContext& context, bool& failure) override - { - /* - failure = false; - auto& definitionCache = context.GetZoneAssetCreationState(); - auto* cachedTechsetDefinition = definitionCache.GetCachedTechsetDefinition(assetName); - if (cachedTechsetDefinition) - return cachedTechsetDefinition; - - const auto techsetFileName = GetFileNameForTechsetName(assetName); - const auto file = m_search_path.Open(techsetFileName); - if (!file.IsOpen()) - return nullptr; - - auto techsetDefinition = LoadCommonTechset(assetName, commonTechniqueTypeNames, m_search_path, failure); - if (!techsetDefinition) - return nullptr; - - auto* techsetDefinitionPtr = techsetDefinition.get(); - - definitionCache.AddCommonTechsetToCache(assetName, std::move(techsetDefinition)); - - return techsetDefinitionPtr; - */ - return nullptr; - } - - const state_map::StateMapDefinition* LoadStateMapDefinition(const std::string& stateMapName, AssetCreationContext& context) override - { - /* - auto& stateMapCache = context.GetZoneAssetCreationState(); - auto* cachedStateMap = stateMapCache.GetCachedStateMap(stateMapName); - if (cachedStateMap) - return cachedStateMap; - - const auto stateMapFileName = GetFileNameForStateMapName(stateMapName); - const auto file = m_search_path.Open(stateMapFileName); - if (!file.IsOpen()) - return nullptr; - - const state_map::StateMapReader reader(*file.m_stream, stateMapFileName, stateMapName, stateMapLayout); - auto stateMapDefinition = reader.ReadStateMapDefinition(); - if (!stateMapDefinition) - return nullptr; - - const auto* stateMapDefinitionPtr = stateMapDefinition.get(); - - stateMapCache.AddStateMapToCache(std::move(stateMapDefinition)); - - return stateMapDefinitionPtr; - */ - return nullptr; - } - - private: - MemoryManager& m_memory; - ISearchPath& m_search_path; - }; -} // namespace - -namespace techset -{ - std::unique_ptr CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) - { - return std::make_unique(memory, searchPath); - } -} // namespace techset diff --git a/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.h b/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.h deleted file mode 100644 index c0e54d879..000000000 --- a/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "Asset/IAssetCreator.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" -#include "Techset/CommonTechset.h" -#include "Techset/StateMap/StateMapDefinition.h" -#include "Utils/MemoryManager.h" - -#include -#include - -namespace techset -{ - class ICreatorIW4 : public AssetCreator - { - public: - ICreatorIW4() = default; - virtual ~ICreatorIW4() = default; - - virtual CommonTechset* LoadTechsetDefinition(const std::string& assetName, AssetCreationContext& context, bool& failure) = 0; - virtual const state_map::StateMapDefinition* LoadStateMapDefinition(const std::string& stateMapName, AssetCreationContext& context) = 0; - }; - - std::unique_ptr CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); -} // namespace techset From 0fc6dc73dd20e22e7c37e3fc0e105ba9c0322b8d Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Tue, 24 Mar 2026 21:22:33 +0100 Subject: [PATCH 02/10] feat: add shader compiler for IW4 --- src/ObjCommon/Shader/ShaderCommon.cpp | 5 + src/ObjCommon/Shader/ShaderCommon.h | 2 + .../Game/IW4/Material/CompilerMaterialIW4.cpp | 1 - src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp | 4 + .../IW4/Techset/PixelShaderCompilerIW4.cpp | 117 ++++++++++++++++++ .../Game/IW4/Techset/PixelShaderCompilerIW4.h | 11 ++ .../IW4/Techset/VertexShaderCompilerIW4.cpp | 117 ++++++++++++++++++ .../IW4/Techset/VertexShaderCompilerIW4.h | 11 ++ .../Techset/ShaderIncludeHandler.cpp | 59 +++++++++ .../Techset/ShaderIncludeHandler.h | 27 ++++ src/Utils/Utils/Logging/Log.h | 5 + 11 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp create mode 100644 src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.h create mode 100644 src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp create mode 100644 src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.h create mode 100644 src/ObjCompiling/Techset/ShaderIncludeHandler.cpp create mode 100644 src/ObjCompiling/Techset/ShaderIncludeHandler.h diff --git a/src/ObjCommon/Shader/ShaderCommon.cpp b/src/ObjCommon/Shader/ShaderCommon.cpp index 7dc6c7bbd..b92d74736 100644 --- a/src/ObjCommon/Shader/ShaderCommon.cpp +++ b/src/ObjCommon/Shader/ShaderCommon.cpp @@ -4,6 +4,11 @@ namespace shader { + std::string GetSourceFileNameForShaderAssetName(const std::string& assetName) + { + return std::format("shader/{}", assetName); + } + std::string GetFileNameForPixelShaderAssetName(const std::string& assetName) { return std::format("shader_bin/ps_{}.cso", assetName); diff --git a/src/ObjCommon/Shader/ShaderCommon.h b/src/ObjCommon/Shader/ShaderCommon.h index 0e3ef8786..521fbc88d 100644 --- a/src/ObjCommon/Shader/ShaderCommon.h +++ b/src/ObjCommon/Shader/ShaderCommon.h @@ -4,6 +4,8 @@ namespace shader { + std::string GetSourceFileNameForShaderAssetName(const std::string& assetName); + std::string GetFileNameForPixelShaderAssetName(const std::string& assetName); std::string GetFileNameForVertexShaderAssetName(const std::string& assetName); } // namespace shader diff --git a/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.cpp b/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.cpp index d2e20bc0f..79b53d03c 100644 --- a/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.cpp +++ b/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.cpp @@ -4,7 +4,6 @@ #include "Game/IW4/IW4.h" #include "Game/IW4/MaterialConstantsIW4.h" #include "Game/IW4/ObjConstantsIW4.h" -#include "Game/IW4/Techset/CompilerTechsetIW4.h" #include "Game/IW4/Techset/TechsetConstantsIW4.h" #include "Gdt/AbstractGdtEntryReader.h" #include "Gdt/IGdtQueryable.h" diff --git a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp index 884577441..95a24fe0b 100644 --- a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp +++ b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp @@ -6,6 +6,8 @@ #include "Game/IW4/Techset/VertexDeclCompilerIW4.h" #include "Image/ImageIwdPostProcessor.h" #include "Material/CompilerMaterialIW4.h" +#include "Techset/PixelShaderCompilerIW4.h" +#include "Techset/VertexShaderCompilerIW4.h" #include @@ -21,6 +23,8 @@ namespace collection.AddAssetCreator(material::CreateCompilerIW4(memory, searchPath, gdt)); #endif collection.AddAssetCreator(techset::CreateVertexDeclCompilerIW4(memory)); + collection.AddAssetCreator(techset::CreateVertexShaderCompilerIW4(memory, searchPath)); + collection.AddAssetCreator(techset::CreatePixelShaderCompilerIW4(memory, searchPath)); collection.AddAssetCreator(techset::CreateTechsetCompilerIW4(memory, searchPath)); collection.AddSubAssetCreator(techset::CreateTechniqueCompilerIW4(memory, zone, searchPath)); diff --git a/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp new file mode 100644 index 000000000..e59ade53d --- /dev/null +++ b/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp @@ -0,0 +1,117 @@ +#include "PixelShaderCompilerIW4.h" + +#include "Game/IW4/IW4.h" +#include "Shader/ShaderCommon.h" +#include "Techset/ShaderIncludeHandler.h" +#include "Utils/Logging/Log.h" + +#include +#include +#include + +#ifdef _WIN32 +#include + +#pragma comment(lib, "d3dcompiler.lib") +#endif + +using namespace IW4; + +namespace +{ + class PixelShaderCompilerIW4 final : public AssetCreator + { + public: + PixelShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { +#ifdef _WIN32 + const auto fileName = shader::GetSourceFileNameForShaderAssetName(assetName); + auto file = m_search_path.Open(fileName); + if (!file.IsOpen() || file.m_length <= 0) + return AssetCreationResult::NoAction(); + + if (std::cmp_greater(file.m_length, techset::ShaderIncludeHandler::MAX_SHADER_SIZE)) + { + con::error("Invalid shader source \"{}\": File too big: {}", assetName, file.m_length); + return AssetCreationResult::Failure(); + } + + const auto shaderSize = static_cast(file.m_length); + const auto shaderData = std::make_unique(shaderSize); + file.m_stream->read(shaderData.get(), shaderSize); + file.m_stream.reset(); + + constexpr unsigned shaderFlags = D3DCOMPILE_OPTIMIZATION_LEVEL1 +#ifdef _DEBUG + | D3DCOMPILE_DEBUG +#endif + ; + + techset::ShaderIncludeHandler shaderIncluder(m_search_path); + + ID3DBlob* shaderBlob = nullptr; + ID3DBlob* errorBlob = nullptr; + const auto errorCode = D3DCompile( + shaderData.get(), shaderSize, assetName.c_str(), nullptr, &shaderIncluder, "PSMain", "ps_3_0", shaderFlags, 0u, &shaderBlob, &errorBlob); + + if (FAILED(errorCode)) + { + con::error("Invalid pixel shader \"{}\": Compilation error", assetName); + + if (errorBlob) + { + std::cerr << " " << static_cast(errorBlob->GetBufferPointer()) << "\n"; + errorBlob->Release(); + } + + if (shaderBlob) + shaderBlob->Release(); + + return AssetCreationResult::Failure(); + } + + con::info("Compiled pixel shader \"{}\"", assetName); + + const auto shaderBlobSize = static_cast(shaderBlob->GetBufferSize()); + assert(shaderBlobSize % sizeof(uint32_t) == 0); + + auto* pixelShader = m_memory.Alloc(); + pixelShader->name = m_memory.Dup(assetName.c_str()); + pixelShader->prog.loadDef.programSize = static_cast(shaderBlobSize / sizeof(uint32_t)); + pixelShader->prog.loadDef.loadForRenderer = 0; + pixelShader->prog.ps = nullptr; + + auto* assetShaderBuffer = m_memory.Alloc(shaderBlobSize); + memcpy(assetShaderBuffer, shaderBlob->GetBufferPointer(), shaderBlobSize); + pixelShader->prog.loadDef.program = reinterpret_cast(assetShaderBuffer); + + shaderBlob->Release(); + + return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, pixelShader))); +#else + // Shader compilation is only support with Windows + return AssetCreationResult::NoAction(); +#endif + } + + void FinalizeZone(AssetCreationContext& context) override {} + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace techset +{ + std::unique_ptr CreatePixelShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace techset diff --git a/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.h b/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.h new file mode 100644 index 000000000..0486277b1 --- /dev/null +++ b/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Utils/MemoryManager.h" + +#include + +namespace techset +{ + std::unique_ptr CreatePixelShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath); +} diff --git a/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp new file mode 100644 index 000000000..be8181aa3 --- /dev/null +++ b/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp @@ -0,0 +1,117 @@ +#include "VertexShaderCompilerIW4.h" + +#include "Game/IW4/IW4.h" +#include "Shader/ShaderCommon.h" +#include "Techset/ShaderIncludeHandler.h" +#include "Utils/Logging/Log.h" + +#include +#include +#include + +#ifdef _WIN32 +#include + +#pragma comment(lib, "d3dcompiler.lib") +#endif + +using namespace IW4; + +namespace +{ + class VertexShaderCompilerIW4 final : public AssetCreator + { + public: + VertexShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { +#ifdef _WIN32 + const auto fileName = shader::GetSourceFileNameForShaderAssetName(assetName); + auto file = m_search_path.Open(fileName); + if (!file.IsOpen() || file.m_length <= 0) + return AssetCreationResult::NoAction(); + + if (std::cmp_greater(file.m_length, techset::ShaderIncludeHandler::MAX_SHADER_SIZE)) + { + con::error("Invalid shader source \"{}\": File too big: {}", assetName, file.m_length); + return AssetCreationResult::Failure(); + } + + const auto shaderSize = static_cast(file.m_length); + const auto shaderData = std::make_unique(shaderSize); + file.m_stream->read(shaderData.get(), shaderSize); + file.m_stream.reset(); + + constexpr unsigned shaderFlags = D3DCOMPILE_OPTIMIZATION_LEVEL1 +#ifdef _DEBUG + | D3DCOMPILE_DEBUG +#endif + ; + + techset::ShaderIncludeHandler shaderIncluder(m_search_path); + + ID3DBlob* shaderBlob = nullptr; + ID3DBlob* errorBlob = nullptr; + const auto errorCode = D3DCompile( + shaderData.get(), shaderSize, assetName.c_str(), nullptr, &shaderIncluder, "VSMain", "vs_3_0", shaderFlags, 0u, &shaderBlob, &errorBlob); + + if (FAILED(errorCode)) + { + con::error("Invalid vertex shader \"{}\": Compilation error", assetName); + + if (errorBlob) + { + std::cerr << " " << static_cast(errorBlob->GetBufferPointer()) << "\n"; + errorBlob->Release(); + } + + if (shaderBlob) + shaderBlob->Release(); + + return AssetCreationResult::Failure(); + } + + con::info("Compiled vertex shader \"{}\"", assetName); + + const auto shaderBlobSize = static_cast(shaderBlob->GetBufferSize()); + assert(shaderBlobSize % sizeof(uint32_t) == 0); + + auto* vertexShader = m_memory.Alloc(); + vertexShader->name = m_memory.Dup(assetName.c_str()); + vertexShader->prog.loadDef.programSize = static_cast(shaderBlobSize / sizeof(uint32_t)); + vertexShader->prog.loadDef.loadForRenderer = 0; + vertexShader->prog.vs = nullptr; + + auto* assetShaderBuffer = m_memory.Alloc(shaderBlobSize); + memcpy(assetShaderBuffer, shaderBlob->GetBufferPointer(), shaderBlobSize); + vertexShader->prog.loadDef.program = reinterpret_cast(assetShaderBuffer); + + shaderBlob->Release(); + + return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, vertexShader))); +#else + // Shader compilation is only support with Windows + return AssetCreationResult::NoAction(); +#endif + } + + void FinalizeZone(AssetCreationContext& context) override {} + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace techset +{ + std::unique_ptr CreateVertexShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace techset diff --git a/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.h b/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.h new file mode 100644 index 000000000..c9f5042bb --- /dev/null +++ b/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Utils/MemoryManager.h" + +#include + +namespace techset +{ + std::unique_ptr CreateVertexShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath); +} diff --git a/src/ObjCompiling/Techset/ShaderIncludeHandler.cpp b/src/ObjCompiling/Techset/ShaderIncludeHandler.cpp new file mode 100644 index 000000000..d77a04390 --- /dev/null +++ b/src/ObjCompiling/Techset/ShaderIncludeHandler.cpp @@ -0,0 +1,59 @@ +#include "ShaderIncludeHandler.h" + +#include "Shader/ShaderCommon.h" +#include "Utils/Logging/Log.h" + +#include +#include + +#ifdef _WIN32 + +namespace techset +{ + ShaderIncludeHandler::ShaderIncludeHandler(ISearchPath& searchPath) + : m_search_path(searchPath) + { + } + + HRESULT ShaderIncludeHandler::Open(D3D_INCLUDE_TYPE includeType, const LPCSTR pFileName, LPCVOID pParentData, LPCVOID* ppData, UINT* pBytes) + { + const auto fileName = shader::GetSourceFileNameForShaderAssetName(pFileName); + auto file = m_search_path.Open(fileName); + if (!file.IsOpen() || file.m_length <= 0) + return E_FAIL; + + if (std::cmp_greater(file.m_length, MAX_SHADER_SIZE)) + { + con::error("Invalid shader source \"{}\": File too big: {}\n", pFileName, file.m_length); + return E_FAIL; + } + + const auto shaderSize = static_cast(file.m_length); + auto shaderData = std::make_unique(shaderSize); + file.m_stream->read(shaderData.get(), shaderSize); + file.m_stream.reset(); + + *ppData = shaderData.get(); + *pBytes = shaderSize; + + m_file_buffers_in_use.push_back(std::move(shaderData)); + + return S_OK; + } + + HRESULT ShaderIncludeHandler::Close(const LPCVOID pData) + { + for (auto i = m_file_buffers_in_use.begin(); i != m_file_buffers_in_use.end(); ++i) + { + if (i->get() == pData) + { + m_file_buffers_in_use.erase(i); + return S_OK; + } + } + + return E_FAIL; + } +} // namespace techset + +#endif diff --git a/src/ObjCompiling/Techset/ShaderIncludeHandler.h b/src/ObjCompiling/Techset/ShaderIncludeHandler.h new file mode 100644 index 000000000..e9558521e --- /dev/null +++ b/src/ObjCompiling/Techset/ShaderIncludeHandler.h @@ -0,0 +1,27 @@ +#pragma once + +#include "SearchPath/ISearchPath.h" + +// Shader compilation only available on Windows +#ifdef _WIN32 +#include + +namespace techset +{ + class ShaderIncludeHandler : public ID3DInclude + { + public: + static constexpr size_t MAX_SHADER_SIZE = 0x1900000u; + + explicit ShaderIncludeHandler(ISearchPath& searchPath); + virtual ~ShaderIncludeHandler() = default; + + HRESULT __declspec(nothrow) __stdcall Open(D3D_INCLUDE_TYPE includeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID* ppData, UINT* pBytes) override; + HRESULT __declspec(nothrow) __stdcall Close(LPCVOID pData) override; + + private: + ISearchPath& m_search_path; + std::vector> m_file_buffers_in_use; + }; +} // namespace techset +#endif diff --git a/src/Utils/Utils/Logging/Log.h b/src/Utils/Utils/Logging/Log.h index 814d57d59..2a5a537e2 100644 --- a/src/Utils/Utils/Logging/Log.h +++ b/src/Utils/Utils/Logging/Log.h @@ -5,6 +5,11 @@ #include #include +// Thanks wingdi.h +#ifdef ERROR +#undef ERROR +#endif + namespace con { enum class LogLevel : std::uint8_t From e814f7382c4432a4704d45e1dd0f92fd5014b536 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Tue, 24 Mar 2026 23:10:36 +0100 Subject: [PATCH 03/10] chore: add base hlsl for IW4 --- raw/iw4/shader/include/IW4.hlsl | 132 ++++++++++++++++++ raw/iw4/shader/trivial_vertcol_simple.hlsl | 33 +++++ .../Techset/ShaderIncludeHandler.cpp | 4 +- 3 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 raw/iw4/shader/include/IW4.hlsl create mode 100644 raw/iw4/shader/trivial_vertcol_simple.hlsl diff --git a/raw/iw4/shader/include/IW4.hlsl b/raw/iw4/shader/include/IW4.hlsl new file mode 100644 index 000000000..278d5631d --- /dev/null +++ b/raw/iw4/shader/include/IW4.hlsl @@ -0,0 +1,132 @@ +// ============================= +// IW4 code constants +// ============================= + +extern float4 baseLightingCoords; +extern float4 lightprobeAmbient; +extern float4 fullscreenDistortion; +extern float4 fadeEffect; +extern float4 lightingLookupScale; +extern float4 debugBumpmap; +extern float4 pixelCostFracs; +extern float4 pixelCostDecode; +extern float4 materialColor; +extern float4 fogConsts; +extern float4 fogColorLinear; +extern float4 fogColorGamma; +extern float4 fogSunConsts; +extern float4 fogSunColorLinear; +extern float4 fogSunColorGamma; +extern float4 fogSunDir; +extern float4 glowSetup; +extern float4 glowApply; +extern float4 filterTap[8]; +extern float4 codeMeshArg[2]; +extern float4 renderTargetSize; +extern float4 shadowmapSwitchPartition; +extern float4 shadowmapScale; +extern float4 shadowmapPolygonOffset; +extern float4 zNear; +extern float4 clipSpaceLookupScale; +extern float4 clipSpaceLookupOffset; +extern float4 dofEquationViewModelAndFarBlur; +extern float4 dofEquationScene; +extern float4 dofLerpScale; +extern float4 dofLerpBias; +extern float4 dofRowDelta; +extern float4 depthFromClip; +extern float4 outdoorFeatherParms; +extern float4 envMapParms; +extern float4 colorMatrixR; +extern float4 colorMatrixG; +extern float4 colorMatrixB; +extern float4 colorBias; +extern float4 colorTintBase; +extern float4 colorTintDelta; +extern float4 colorTintQuadraticDelta; +extern float4 motionMatrixX; +extern float4 motionMatrixY; +extern float4 motionMatrixW; +extern float4 gameTime; +extern float4 particleCloudColor; +extern float4 particleCloudMatrix; +extern float4 particleCloudMatrix1; +extern float4 particleCloudMatrix2; +extern float4 particleCloudSparkColor0; +extern float4 particleCloudSparkColor1; +extern float4 particleCloudSparkColor2; +extern float4 particleFountainParms0; +extern float4 particleFountainParms1; +extern float4 viewportDimensions; +extern float4 framebufferRead; + +extern float4 nearPlaneOrg; +extern float4 nearPlaneDx; +extern float4 nearPlaneDy; + +extern float4 lightPosition; +extern float4 lightDiffuse; +extern float4 lightSpecular; +extern float4 lightSpotDir; +extern float4 lightSpotFactors; +extern float4 lightFalloffPlacement; + +extern float4 sunShadowmapPixelAdjust; +extern float4 spotShadowmapPixelAdjust; + +extern float4x4 viewMatrix; +extern float4x4 inverseViewMatrix; +extern float4x4 transposeViewMatrix; +extern float4x4 inverseTransposeViewMatrix; +extern float4x4 projectionMatrix; +extern float4x4 inverseProjectionMatrix; +extern float4x4 transposeProjectionMatrix; +extern float4x4 inverseTransposeProjectionMatrix; +extern float4x4 viewProjectionMatrix; +extern float4x4 inverseViewProjectionMatrix; +extern float4x4 transposeViewProjectionMatrix; +extern float4x4 inverseTransposeViewProjectionMatrix; +extern float4x4 shadowLookupMatrix; +extern float4x4 inverseShadowLookupMatrix; +extern float4x4 transposeShadowLookupMatrix; +extern float4x4 inverseTransposeShadowLookupMatrix; +extern float4x4 worldOutdoorLookupMatrix; +extern float4x4 inverseWorldOutdoorLookupMatrix; +extern float4x4 transposeWorldOutdoorLookupMatrix; +extern float4x4 inverseTransposeWorldOutdoorLookupMatrix; +extern float4x4 worldMatrix; +extern float4x4 inverseWorldMatrix; +extern float4x4 transposeWorldMatrix; +extern float4x4 inverseTransposeWorldMatrix; +extern float4x4 worldViewMatrix; +extern float4x4 inverseWorldViewMatrix; +extern float4x4 transposeWorldViewMatrix; +extern float4x4 inverseTransposeWorldViewMatrix; +extern float4x4 worldViewProjectionMatrix; +extern float4x4 inverseWorldViewProjectionMatrix; +extern float4x4 transposeWorldViewProjectionMatrix; +extern float4x4 inverseTransposeWorldViewProjectionMatrix; +extern float4x4 worldMatrix1; +extern float4x4 inverseWorldMatrix1; +extern float4x4 transposeWorldMatrix1; +extern float4x4 inverseTransposeWorldMatrix1; +extern float4x4 worldViewMatrix1; +extern float4x4 inverseWorldViewMatrix1; +extern float4x4 transposeWorldViewMatrix1; +extern float4x4 inverseTransposeWorldViewMatrix1; +extern float4x4 worldViewProjectionMatrix1; +extern float4x4 inverseWorldViewProjectionMatrix1; +extern float4x4 transposeWorldViewProjectionMatrix1; +extern float4x4 inverseTransposeWorldViewProjectionMatrix1; +extern float4x4 worldMatrix2; +extern float4x4 inverseWorldMatrix2; +extern float4x4 transposeWorldMatrix2; +extern float4x4 inverseTransposeWorldMatrix2; +extern float4x4 worldViewMatrix2; +extern float4x4 inverseWorldViewMatrix2; +extern float4x4 transposeWorldViewMatrix2; +extern float4x4 inverseTransposeWorldViewMatrix2; +extern float4x4 worldViewProjectionMatrix2; +extern float4x4 inverseWorldViewProjectionMatrix2; +extern float4x4 transposeWorldViewProjectionMatrix2; +extern float4x4 inverseTransposeWorldViewProjectionMatrix2; diff --git a/raw/iw4/shader/trivial_vertcol_simple.hlsl b/raw/iw4/shader/trivial_vertcol_simple.hlsl new file mode 100644 index 000000000..bce15a889 --- /dev/null +++ b/raw/iw4/shader/trivial_vertcol_simple.hlsl @@ -0,0 +1,33 @@ +#include "include/IW4.hlsl" + +struct VSInput +{ + float3 position : POSITION; + half4 color : COLOR0; + half2 texcoord : TEXCOORD0; +}; + +struct VSOutput +{ + float4 position : SV_POSITION; + half4 color : COLOR0; + half2 texcoord : TEXCOORD0; +}; + +VSOutput VSMain(VSInput vin) +{ + VSOutput vout = (VSOutput)0; + + vout.position = mul(mul(float4(vin.position, 1.0f), worldMatrix), viewProjectionMatrix); + vout.color = vin.color; + vout.texcoord = vin.texcoord; + + return vout; +} + +extern sampler2D colorMapSampler; + +half4 PSMain(VSOutput input) : SV_TARGET +{ + return half4(tex2D(colorMapSampler, input.texcoord)) * input.color; +} diff --git a/src/ObjCompiling/Techset/ShaderIncludeHandler.cpp b/src/ObjCompiling/Techset/ShaderIncludeHandler.cpp index d77a04390..a24557157 100644 --- a/src/ObjCompiling/Techset/ShaderIncludeHandler.cpp +++ b/src/ObjCompiling/Techset/ShaderIncludeHandler.cpp @@ -30,11 +30,11 @@ namespace techset const auto shaderSize = static_cast(file.m_length); auto shaderData = std::make_unique(shaderSize); - file.m_stream->read(shaderData.get(), shaderSize); + file.m_stream->read(shaderData.get(), static_cast(shaderSize)); file.m_stream.reset(); *ppData = shaderData.get(); - *pBytes = shaderSize; + *pBytes = static_cast(shaderSize); m_file_buffers_in_use.push_back(std::move(shaderData)); From b283695e1c194668b95a3ce51a1fa56b0df561d7 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Wed, 25 Mar 2026 22:47:50 +0100 Subject: [PATCH 04/10] chore: dynamically enable shader compilation if available --- .../IW4/Techset/PixelShaderCompilerIW4.cpp | 86 ++--- .../IW4/Techset/VertexShaderCompilerIW4.cpp | 86 ++--- src/ObjCompiling/Shader/D3DShaderCompiler.cpp | 302 ++++++++++++++++++ src/ObjCompiling/Shader/D3DShaderCompiler.h | 23 ++ .../Techset/ShaderIncludeHandler.cpp | 59 ---- .../Techset/ShaderIncludeHandler.h | 27 -- .../Asset/AssetCreatorCollection.cpp | 12 + 7 files changed, 373 insertions(+), 222 deletions(-) create mode 100644 src/ObjCompiling/Shader/D3DShaderCompiler.cpp create mode 100644 src/ObjCompiling/Shader/D3DShaderCompiler.h delete mode 100644 src/ObjCompiling/Techset/ShaderIncludeHandler.cpp delete mode 100644 src/ObjCompiling/Techset/ShaderIncludeHandler.h diff --git a/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp index e59ade53d..670790f77 100644 --- a/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp +++ b/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp @@ -1,20 +1,13 @@ #include "PixelShaderCompilerIW4.h" #include "Game/IW4/IW4.h" -#include "Shader/ShaderCommon.h" -#include "Techset/ShaderIncludeHandler.h" +#include "Shader/D3DShaderCompiler.h" #include "Utils/Logging/Log.h" #include #include #include -#ifdef _WIN32 -#include - -#pragma comment(lib, "d3dcompiler.lib") -#endif - using namespace IW4; namespace @@ -30,74 +23,28 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { -#ifdef _WIN32 - const auto fileName = shader::GetSourceFileNameForShaderAssetName(assetName); - auto file = m_search_path.Open(fileName); - if (!file.IsOpen() || file.m_length <= 0) - return AssetCreationResult::NoAction(); + auto result = shader::CompileShader(assetName, "PSMain", "ps_3_0", false, m_search_path, m_memory); - if (std::cmp_greater(file.m_length, techset::ShaderIncludeHandler::MAX_SHADER_SIZE)) + if (result.has_value()) { - con::error("Invalid shader source \"{}\": File too big: {}", assetName, file.m_length); - return AssetCreationResult::Failure(); - } - - const auto shaderSize = static_cast(file.m_length); - const auto shaderData = std::make_unique(shaderSize); - file.m_stream->read(shaderData.get(), shaderSize); - file.m_stream.reset(); - - constexpr unsigned shaderFlags = D3DCOMPILE_OPTIMIZATION_LEVEL1 -#ifdef _DEBUG - | D3DCOMPILE_DEBUG -#endif - ; - - techset::ShaderIncludeHandler shaderIncluder(m_search_path); - - ID3DBlob* shaderBlob = nullptr; - ID3DBlob* errorBlob = nullptr; - const auto errorCode = D3DCompile( - shaderData.get(), shaderSize, assetName.c_str(), nullptr, &shaderIncluder, "PSMain", "ps_3_0", shaderFlags, 0u, &shaderBlob, &errorBlob); + const std::optional maybeShader(*std::move(result)); + if (!maybeShader.has_value()) + return AssetCreationResult::NoAction(); - if (FAILED(errorCode)) - { - con::error("Invalid pixel shader \"{}\": Compilation error", assetName); + con::info("Compiled pixel shader \"{}\"", assetName); - if (errorBlob) - { - std::cerr << " " << static_cast(errorBlob->GetBufferPointer()) << "\n"; - errorBlob->Release(); - } + assert(maybeShader->m_shader_size % sizeof(uint32_t) == 0); - if (shaderBlob) - shaderBlob->Release(); + auto* pixelShader = m_memory.Alloc(); + pixelShader->name = m_memory.Dup(assetName.c_str()); + pixelShader->prog.loadDef.program = static_cast(maybeShader->m_shader_bin); + pixelShader->prog.loadDef.programSize = static_cast(maybeShader->m_shader_size / sizeof(uint32_t)); - return AssetCreationResult::Failure(); + return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, pixelShader))); } - con::info("Compiled pixel shader \"{}\"", assetName); - - const auto shaderBlobSize = static_cast(shaderBlob->GetBufferSize()); - assert(shaderBlobSize % sizeof(uint32_t) == 0); - - auto* pixelShader = m_memory.Alloc(); - pixelShader->name = m_memory.Dup(assetName.c_str()); - pixelShader->prog.loadDef.programSize = static_cast(shaderBlobSize / sizeof(uint32_t)); - pixelShader->prog.loadDef.loadForRenderer = 0; - pixelShader->prog.ps = nullptr; - - auto* assetShaderBuffer = m_memory.Alloc(shaderBlobSize); - memcpy(assetShaderBuffer, shaderBlob->GetBufferPointer(), shaderBlobSize); - pixelShader->prog.loadDef.program = reinterpret_cast(assetShaderBuffer); - - shaderBlob->Release(); - - return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, pixelShader))); -#else - // Shader compilation is only support with Windows - return AssetCreationResult::NoAction(); -#endif + con::error("Failed to compile pixel shader \"{}\": {}", assetName, result.error()); + return AssetCreationResult::Failure(); } void FinalizeZone(AssetCreationContext& context) override {} @@ -112,6 +59,9 @@ namespace techset { std::unique_ptr CreatePixelShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath) { + if (!shader::ShaderCompilationAvailable()) + return nullptr; + return std::make_unique(memory, searchPath); } } // namespace techset diff --git a/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp index be8181aa3..58db1ae42 100644 --- a/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp +++ b/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp @@ -1,20 +1,13 @@ #include "VertexShaderCompilerIW4.h" #include "Game/IW4/IW4.h" -#include "Shader/ShaderCommon.h" -#include "Techset/ShaderIncludeHandler.h" +#include "Shader/D3DShaderCompiler.h" #include "Utils/Logging/Log.h" #include #include #include -#ifdef _WIN32 -#include - -#pragma comment(lib, "d3dcompiler.lib") -#endif - using namespace IW4; namespace @@ -30,74 +23,28 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { -#ifdef _WIN32 - const auto fileName = shader::GetSourceFileNameForShaderAssetName(assetName); - auto file = m_search_path.Open(fileName); - if (!file.IsOpen() || file.m_length <= 0) - return AssetCreationResult::NoAction(); + auto result = shader::CompileShader(assetName, "VSMain", "vs_3_0", false, m_search_path, m_memory); - if (std::cmp_greater(file.m_length, techset::ShaderIncludeHandler::MAX_SHADER_SIZE)) + if (result.has_value()) { - con::error("Invalid shader source \"{}\": File too big: {}", assetName, file.m_length); - return AssetCreationResult::Failure(); - } - - const auto shaderSize = static_cast(file.m_length); - const auto shaderData = std::make_unique(shaderSize); - file.m_stream->read(shaderData.get(), shaderSize); - file.m_stream.reset(); - - constexpr unsigned shaderFlags = D3DCOMPILE_OPTIMIZATION_LEVEL1 -#ifdef _DEBUG - | D3DCOMPILE_DEBUG -#endif - ; - - techset::ShaderIncludeHandler shaderIncluder(m_search_path); - - ID3DBlob* shaderBlob = nullptr; - ID3DBlob* errorBlob = nullptr; - const auto errorCode = D3DCompile( - shaderData.get(), shaderSize, assetName.c_str(), nullptr, &shaderIncluder, "VSMain", "vs_3_0", shaderFlags, 0u, &shaderBlob, &errorBlob); + const std::optional maybeShader(*std::move(result)); + if (!maybeShader.has_value()) + return AssetCreationResult::NoAction(); - if (FAILED(errorCode)) - { - con::error("Invalid vertex shader \"{}\": Compilation error", assetName); + con::info("Compiled vertex shader \"{}\"", assetName); - if (errorBlob) - { - std::cerr << " " << static_cast(errorBlob->GetBufferPointer()) << "\n"; - errorBlob->Release(); - } + assert(maybeShader->m_shader_size % sizeof(uint32_t) == 0); - if (shaderBlob) - shaderBlob->Release(); + auto* vertexShader = m_memory.Alloc(); + vertexShader->name = m_memory.Dup(assetName.c_str()); + vertexShader->prog.loadDef.program = static_cast(maybeShader->m_shader_bin); + vertexShader->prog.loadDef.programSize = static_cast(maybeShader->m_shader_size / sizeof(uint32_t)); - return AssetCreationResult::Failure(); + return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, vertexShader))); } - con::info("Compiled vertex shader \"{}\"", assetName); - - const auto shaderBlobSize = static_cast(shaderBlob->GetBufferSize()); - assert(shaderBlobSize % sizeof(uint32_t) == 0); - - auto* vertexShader = m_memory.Alloc(); - vertexShader->name = m_memory.Dup(assetName.c_str()); - vertexShader->prog.loadDef.programSize = static_cast(shaderBlobSize / sizeof(uint32_t)); - vertexShader->prog.loadDef.loadForRenderer = 0; - vertexShader->prog.vs = nullptr; - - auto* assetShaderBuffer = m_memory.Alloc(shaderBlobSize); - memcpy(assetShaderBuffer, shaderBlob->GetBufferPointer(), shaderBlobSize); - vertexShader->prog.loadDef.program = reinterpret_cast(assetShaderBuffer); - - shaderBlob->Release(); - - return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, vertexShader))); -#else - // Shader compilation is only support with Windows - return AssetCreationResult::NoAction(); -#endif + con::error("Failed to compile vertex shader \"{}\": {}", assetName, result.error()); + return AssetCreationResult::Failure(); } void FinalizeZone(AssetCreationContext& context) override {} @@ -112,6 +59,9 @@ namespace techset { std::unique_ptr CreateVertexShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath) { + if (!shader::ShaderCompilationAvailable()) + return nullptr; + return std::make_unique(memory, searchPath); } } // namespace techset diff --git a/src/ObjCompiling/Shader/D3DShaderCompiler.cpp b/src/ObjCompiling/Shader/D3DShaderCompiler.cpp new file mode 100644 index 000000000..9e6e623be --- /dev/null +++ b/src/ObjCompiling/Shader/D3DShaderCompiler.cpp @@ -0,0 +1,302 @@ +#include "D3DShaderCompiler.h" + +#include "Shader/ShaderCommon.h" +#include "Utils/Logging/Log.h" + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +namespace +{ + // The types based on vkd3d which is licensed under the + // GNU Lesser General Public License as published by the Free Software Foundation + // All types are prefixed with OAT_ to not cause conflicts as the original definition may be included + // depending on the platform. + // Types were duplicated to be available on any platform and to not require the corresponding library + // to be installed + + typedef int OAT_HRESULT; +#define OAT_SUCCEEDED(hr) ((OAT_HRESULT)(hr) >= 0) +#define OAT_FAILED(hr) ((OAT_HRESULT)(hr) < 0) + + typedef unsigned int OAT_ULONG; + typedef unsigned long OAT_ULONG_PTR; + typedef OAT_ULONG_PTR OAT_SIZE_T; + +#define OAT_HRESULT_TYPEDEF(x) ((OAT_HRESULT)x) + +#define OAT_S_OK OAT_HRESULT_TYPEDEF(0) +#define OAT_S_FALSE OAT_HRESULT_TYPEDEF(1) + +#define OAT_E_FAIL OAT_HRESULT_TYPEDEF(0x80004005) + +#define OAT_D3DCOMPILE_DEBUG 0x00000001 +#define OAT_D3DCOMPILE_SKIP_VALIDATION 0x00000002 +#define OAT_D3DCOMPILE_SKIP_OPTIMIZATION 0x00000004 +#define OAT_D3DCOMPILE_PACK_MATRIX_ROW_MAJOR 0x00000008 +#define OAT_D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR 0x00000010 +#define OAT_D3DCOMPILE_PARTIAL_PRECISION 0x00000020 +#define OAT_D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT 0x00000040 +#define OAT_D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT 0x00000080 +#define OAT_D3DCOMPILE_NO_PRESHADER 0x00000100 +#define OAT_D3DCOMPILE_AVOID_FLOW_CONTROL 0x00000200 +#define OAT_D3DCOMPILE_PREFER_FLOW_CONTROL 0x00000400 +#define OAT_D3DCOMPILE_ENABLE_STRICTNESS 0x00000800 +#define OAT_D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY 0x00001000 +#define OAT_D3DCOMPILE_IEEE_STRICTNESS 0x00002000 +#define OAT_D3DCOMPILE_OPTIMIZATION_LEVEL0 0x00004000 +#define OAT_D3DCOMPILE_OPTIMIZATION_LEVEL1 0x00000000 +#define OAT_D3DCOMPILE_OPTIMIZATION_LEVEL2 0x0000c000 +#define OAT_D3DCOMPILE_OPTIMIZATION_LEVEL3 0x00008000 +#define OAT_D3DCOMPILE_RESERVED16 0x00010000 +#define OAT_D3DCOMPILE_RESERVED17 0x00020000 +#define OAT_D3DCOMPILE_WARNINGS_ARE_ERRORS 0x00040000 +#define OAT_D3DCOMPILE_RESOURCES_MAY_ALIAS 0x00080000 +#define OAT_D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES 0x00100000 +#define OAT_D3DCOMPILE_ALL_RESOURCES_BOUND 0x00200000 +#define OAT_D3DCOMPILE_DEBUG_NAME_FOR_SOURCE 0x00400000 +#define OAT_D3DCOMPILE_DEBUG_NAME_FOR_BINARY 0x00800000 + + enum OAT_D3D_INCLUDE_TYPE : uint32_t + { + OAT_D3D_INCLUDE_LOCAL = 0, + OAT_D3D_INCLUDE_SYSTEM = 1 + }; + + struct OAT_ID3DInclude + { + virtual OAT_HRESULT __stdcall Open( + OAT_D3D_INCLUDE_TYPE includeType, const char* fileName, const void* parentData, const void** data, unsigned int* size) = 0; + virtual OAT_HRESULT __stdcall Close(const void* data) = 0; + }; + + struct OAT_GUID + { + unsigned int Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; + }; + + typedef OAT_GUID OAT_IID; + + struct OAT_IUnknown + { + virtual OAT_HRESULT __stdcall QueryInterface(const OAT_IID& riid, void** object) = 0; + + virtual OAT_ULONG __stdcall AddRef() = 0; + + virtual OAT_ULONG __stdcall Release() = 0; + }; + + struct OAT_ID3DBlob : OAT_IUnknown + { + virtual void* __stdcall GetBufferPointer() = 0; + + virtual OAT_SIZE_T __stdcall GetBufferSize() = 0; + }; + + struct OAT_D3D_SHADER_MACRO + { + const char* Name; + const char* Definition; + }; + + typedef OAT_HRESULT(__stdcall* D3DCompile_t)(const void* data, + OAT_SIZE_T dataSize, + const char* filename, + const OAT_D3D_SHADER_MACRO* defines, + OAT_ID3DInclude* include, + const char* entrypoint, + const char* target, + unsigned int flags, + unsigned int effectFlags, + OAT_ID3DBlob** shader, + OAT_ID3DBlob** errorMessages); + + constexpr size_t MAX_SHADER_SIZE = 0x1900000u; + + class ShaderIncludeHandler : public OAT_ID3DInclude + { + public: + explicit ShaderIncludeHandler(ISearchPath& searchPath) + : m_search_path(searchPath) + { + } + + OAT_HRESULT + __stdcall Open(OAT_D3D_INCLUDE_TYPE includeType, const char* fileName, const void* parentData, const void** data, unsigned int* size) override + { + const auto fullFileName = shader::GetSourceFileNameForShaderAssetName(fileName); + auto file = m_search_path.Open(fullFileName); + if (!file.IsOpen() || file.m_length <= 0) + return OAT_E_FAIL; + + if (std::cmp_greater(file.m_length, MAX_SHADER_SIZE)) + { + con::error("Invalid shader source \"{}\": File too big: {}\n", fileName, file.m_length); + return OAT_E_FAIL; + } + + const auto shaderSize = static_cast(file.m_length); + auto shaderData = std::make_unique(shaderSize); + file.m_stream->read(shaderData.get(), static_cast(shaderSize)); + file.m_stream.reset(); + + *data = shaderData.get(); + *size = static_cast(shaderSize); + + m_file_buffers_in_use.push_back(std::move(shaderData)); + + return OAT_S_OK; + } + + OAT_HRESULT __stdcall Close(const void* data) override + { + for (auto i = m_file_buffers_in_use.begin(); i != m_file_buffers_in_use.end(); ++i) + { + if (i->get() == data) + { + m_file_buffers_in_use.erase(i); + return OAT_S_OK; + } + } + + return OAT_E_FAIL; + } + + private: + ISearchPath& m_search_path; + std::vector> m_file_buffers_in_use; + }; + + bool initialized = false; + bool compilationAvailable = false; + D3DCompile_t d3dCompile = nullptr; + + void PrintInitializationFailedMessage() + { +#ifdef _WIN32 + con::warn("Could not initialize shader compilation. Make sure DirectX is installed on your machine if you want to make use of it."); +#endif + } + + void InitializeShaderCompilation() + { + initialized = true; + +#ifdef _WIN32 + const auto d3dCompiler = LoadLibraryA("D3DCOMPILER_47.dll"); + if (!d3dCompiler) + { + PrintInitializationFailedMessage(); + return; + } + + const auto d3dCompileAddress = GetProcAddress(d3dCompiler, "D3DCompile"); + if (!d3dCompileAddress) + { + PrintInitializationFailedMessage(); + return; + } + + d3dCompile = reinterpret_cast(d3dCompileAddress); + compilationAvailable = true; +#endif + } +} // namespace + +namespace shader +{ + bool ShaderCompilationAvailable() + { + if (!initialized) + InitializeShaderCompilation(); + + return compilationAvailable; + } + + result::Expected, std::string> CompileShader(const std::string& shaderFile, + const std::string& entryPoint, + const std::string& target, + const bool debug, + ISearchPath& searchPath, + MemoryManager& memory) + { + if (!initialized) + InitializeShaderCompilation(); + if (!compilationAvailable) + return result::Unexpected("Shader compilation unavailable"); + + const auto fileName = GetSourceFileNameForShaderAssetName(shaderFile); + auto file = searchPath.Open(fileName); + if (!file.IsOpen() || file.m_length <= 0) + return std::optional(std::nullopt); + + if (std::cmp_greater(file.m_length, MAX_SHADER_SIZE)) + return result::Unexpected(std::format("File too big: {}", file.m_length)); + + const auto shaderSize = file.m_length; + const auto shaderData = std::make_unique(static_cast(shaderSize)); + file.m_stream->read(shaderData.get(), static_cast(shaderSize)); + file.m_stream.reset(); + + unsigned shaderFlags = OAT_D3DCOMPILE_OPTIMIZATION_LEVEL1; + if (debug) + shaderFlags |= OAT_D3DCOMPILE_DEBUG; + + ShaderIncludeHandler shaderIncluder(searchPath); + + OAT_ID3DBlob* shaderBlob = nullptr; + OAT_ID3DBlob* errorBlob = nullptr; + const auto errorCode = d3dCompile(shaderData.get(), + static_cast(shaderSize), + fileName.c_str(), + nullptr, + &shaderIncluder, + entryPoint.c_str(), + target.c_str(), + shaderFlags, + 0u, + &shaderBlob, + &errorBlob); + + if (OAT_FAILED(errorCode)) + { + std::string errorMessage; + + if (errorBlob) + { + errorMessage = std::format("Compilation error: {}", static_cast(errorBlob->GetBufferPointer())); + errorBlob->Release(); + } + else + { + errorMessage = "Unknown compilation error"; + } + + if (shaderBlob) + shaderBlob->Release(); + + return result::Unexpected(std::move(errorMessage)); + } + + const auto shaderBlobSize = static_cast(shaderBlob->GetBufferSize()); + auto* assetShaderBuffer = memory.Alloc(shaderBlobSize); + memcpy(assetShaderBuffer, shaderBlob->GetBufferPointer(), shaderBlobSize); + + shaderBlob->Release(); + + return std::optional(CompiledShader{ + .m_shader_bin = assetShaderBuffer, + .m_shader_size = shaderBlobSize, + }); + } +} // namespace shader diff --git a/src/ObjCompiling/Shader/D3DShaderCompiler.h b/src/ObjCompiling/Shader/D3DShaderCompiler.h new file mode 100644 index 000000000..c281a80e7 --- /dev/null +++ b/src/ObjCompiling/Shader/D3DShaderCompiler.h @@ -0,0 +1,23 @@ +#pragma once + +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" +#include "Utils/Result.h" + +#include +#include + +namespace shader +{ + class CompiledShader + { + public: + void* m_shader_bin; + size_t m_shader_size; + }; + + bool ShaderCompilationAvailable(); + + result::Expected, std::string> CompileShader( + const std::string& shaderFile, const std::string& entryPoint, const std::string& target, bool debug, ISearchPath& searchPath, MemoryManager& memory); +} // namespace shader diff --git a/src/ObjCompiling/Techset/ShaderIncludeHandler.cpp b/src/ObjCompiling/Techset/ShaderIncludeHandler.cpp deleted file mode 100644 index a24557157..000000000 --- a/src/ObjCompiling/Techset/ShaderIncludeHandler.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "ShaderIncludeHandler.h" - -#include "Shader/ShaderCommon.h" -#include "Utils/Logging/Log.h" - -#include -#include - -#ifdef _WIN32 - -namespace techset -{ - ShaderIncludeHandler::ShaderIncludeHandler(ISearchPath& searchPath) - : m_search_path(searchPath) - { - } - - HRESULT ShaderIncludeHandler::Open(D3D_INCLUDE_TYPE includeType, const LPCSTR pFileName, LPCVOID pParentData, LPCVOID* ppData, UINT* pBytes) - { - const auto fileName = shader::GetSourceFileNameForShaderAssetName(pFileName); - auto file = m_search_path.Open(fileName); - if (!file.IsOpen() || file.m_length <= 0) - return E_FAIL; - - if (std::cmp_greater(file.m_length, MAX_SHADER_SIZE)) - { - con::error("Invalid shader source \"{}\": File too big: {}\n", pFileName, file.m_length); - return E_FAIL; - } - - const auto shaderSize = static_cast(file.m_length); - auto shaderData = std::make_unique(shaderSize); - file.m_stream->read(shaderData.get(), static_cast(shaderSize)); - file.m_stream.reset(); - - *ppData = shaderData.get(); - *pBytes = static_cast(shaderSize); - - m_file_buffers_in_use.push_back(std::move(shaderData)); - - return S_OK; - } - - HRESULT ShaderIncludeHandler::Close(const LPCVOID pData) - { - for (auto i = m_file_buffers_in_use.begin(); i != m_file_buffers_in_use.end(); ++i) - { - if (i->get() == pData) - { - m_file_buffers_in_use.erase(i); - return S_OK; - } - } - - return E_FAIL; - } -} // namespace techset - -#endif diff --git a/src/ObjCompiling/Techset/ShaderIncludeHandler.h b/src/ObjCompiling/Techset/ShaderIncludeHandler.h deleted file mode 100644 index e9558521e..000000000 --- a/src/ObjCompiling/Techset/ShaderIncludeHandler.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "SearchPath/ISearchPath.h" - -// Shader compilation only available on Windows -#ifdef _WIN32 -#include - -namespace techset -{ - class ShaderIncludeHandler : public ID3DInclude - { - public: - static constexpr size_t MAX_SHADER_SIZE = 0x1900000u; - - explicit ShaderIncludeHandler(ISearchPath& searchPath); - virtual ~ShaderIncludeHandler() = default; - - HRESULT __declspec(nothrow) __stdcall Open(D3D_INCLUDE_TYPE includeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID* ppData, UINT* pBytes) override; - HRESULT __declspec(nothrow) __stdcall Close(LPCVOID pData) override; - - private: - ISearchPath& m_search_path; - std::vector> m_file_buffers_in_use; - }; -} // namespace techset -#endif diff --git a/src/ObjLoading/Asset/AssetCreatorCollection.cpp b/src/ObjLoading/Asset/AssetCreatorCollection.cpp index 3edaabaa7..d6208bbc5 100644 --- a/src/ObjLoading/Asset/AssetCreatorCollection.cpp +++ b/src/ObjLoading/Asset/AssetCreatorCollection.cpp @@ -13,6 +13,9 @@ AssetCreatorCollection::AssetCreatorCollection(const Zone& zone) void AssetCreatorCollection::AddAssetCreator(std::unique_ptr creator) { + if (!creator) + return; + const auto maybeHandlingAssetType = creator->GetHandlingAssetType(); assert(!maybeHandlingAssetType || static_cast(*maybeHandlingAssetType) < m_asset_creators_by_type.size()); if (maybeHandlingAssetType && static_cast(*maybeHandlingAssetType) < m_asset_creators_by_type.size()) @@ -23,6 +26,9 @@ void AssetCreatorCollection::AddAssetCreator(std::unique_ptr crea void AssetCreatorCollection::AddSubAssetCreator(std::unique_ptr creator) { + if (!creator) + return; + const auto maybeHandlingSubAssetType = creator->GetHandlingSubAssetType(); assert(!maybeHandlingSubAssetType || static_cast(*maybeHandlingSubAssetType) < m_sub_asset_creators_by_type.size()); if (maybeHandlingSubAssetType && static_cast(*maybeHandlingSubAssetType) < m_sub_asset_creators_by_type.size()) @@ -33,6 +39,9 @@ void AssetCreatorCollection::AddSubAssetCreator(std::unique_ptr postProcessor) { + if (!postProcessor) + return; + const auto handlingAssetType = postProcessor->GetHandlingAssetType(); assert(static_cast(handlingAssetType) < m_asset_post_processors_by_type.size()); if (static_cast(handlingAssetType) < m_asset_post_processors_by_type.size()) @@ -43,6 +52,9 @@ void AssetCreatorCollection::AddAssetPostProcessor(std::unique_ptr defaultAssetCreator) { + if (!defaultAssetCreator) + return; + const auto handlingAssetType = defaultAssetCreator->GetHandlingAssetType(); assert(static_cast(handlingAssetType) < m_default_asset_creators_by_type.size()); assert(!m_default_asset_creators_by_type[handlingAssetType]); From 273ea0ae30e315472509c187a23b0dde7a6f3fa0 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Wed, 25 Mar 2026 23:20:09 +0100 Subject: [PATCH 05/10] feat: compile shaders on linux via vkd3d --- src/ObjCompiling/Shader/D3DShaderCompiler.cpp | 83 ++++++++++++++----- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/src/ObjCompiling/Shader/D3DShaderCompiler.cpp b/src/ObjCompiling/Shader/D3DShaderCompiler.cpp index 9e6e623be..8eefdc263 100644 --- a/src/ObjCompiling/Shader/D3DShaderCompiler.cpp +++ b/src/ObjCompiling/Shader/D3DShaderCompiler.cpp @@ -5,12 +5,15 @@ #include #include +#include #include #include #include #ifdef _WIN32 #include +#else +#include #endif namespace @@ -64,6 +67,19 @@ namespace #define OAT_D3DCOMPILE_DEBUG_NAME_FOR_SOURCE 0x00400000 #define OAT_D3DCOMPILE_DEBUG_NAME_FOR_BINARY 0x00800000 +#ifndef _WIN32 +#ifdef __x86_64__ +#define __stdcall __attribute__((ms_abi)) +#else +#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || defined(__APPLE__) +#define __stdcall __attribute__((__stdcall__)) __attribute__((__force_align_arg_pointer__)) +#else +#define __stdcall __attribute__((__stdcall__)) +#endif +#endif +#endif +#define STDMETHODCALLTYPE __stdcall + enum OAT_D3D_INCLUDE_TYPE : uint32_t { OAT_D3D_INCLUDE_LOCAL = 0, @@ -72,9 +88,10 @@ namespace struct OAT_ID3DInclude { - virtual OAT_HRESULT __stdcall Open( - OAT_D3D_INCLUDE_TYPE includeType, const char* fileName, const void* parentData, const void** data, unsigned int* size) = 0; - virtual OAT_HRESULT __stdcall Close(const void* data) = 0; + // clang-format off + virtual OAT_HRESULT STDMETHODCALLTYPE Open(OAT_D3D_INCLUDE_TYPE includeType, const char* fileName, const void* parentData, const void** data, unsigned int* size) = 0; + virtual OAT_HRESULT STDMETHODCALLTYPE Close(const void* data) = 0; + // clang-format on }; struct OAT_GUID @@ -89,18 +106,18 @@ namespace struct OAT_IUnknown { - virtual OAT_HRESULT __stdcall QueryInterface(const OAT_IID& riid, void** object) = 0; + virtual OAT_HRESULT STDMETHODCALLTYPE QueryInterface(const OAT_IID& riid, void** object) = 0; - virtual OAT_ULONG __stdcall AddRef() = 0; + virtual OAT_ULONG STDMETHODCALLTYPE AddRef() = 0; - virtual OAT_ULONG __stdcall Release() = 0; + virtual OAT_ULONG STDMETHODCALLTYPE Release() = 0; }; struct OAT_ID3DBlob : OAT_IUnknown { - virtual void* __stdcall GetBufferPointer() = 0; + virtual void* STDMETHODCALLTYPE GetBufferPointer() = 0; - virtual OAT_SIZE_T __stdcall GetBufferSize() = 0; + virtual OAT_SIZE_T STDMETHODCALLTYPE GetBufferSize() = 0; }; struct OAT_D3D_SHADER_MACRO @@ -109,17 +126,17 @@ namespace const char* Definition; }; - typedef OAT_HRESULT(__stdcall* D3DCompile_t)(const void* data, - OAT_SIZE_T dataSize, - const char* filename, - const OAT_D3D_SHADER_MACRO* defines, - OAT_ID3DInclude* include, - const char* entrypoint, - const char* target, - unsigned int flags, - unsigned int effectFlags, - OAT_ID3DBlob** shader, - OAT_ID3DBlob** errorMessages); + typedef OAT_HRESULT(STDMETHODCALLTYPE* D3DCompile_t)(const void* data, + OAT_SIZE_T dataSize, + const char* filename, + const OAT_D3D_SHADER_MACRO* defines, + OAT_ID3DInclude* include, + const char* entrypoint, + const char* target, + unsigned int flags, + unsigned int effectFlags, + OAT_ID3DBlob** shader, + OAT_ID3DBlob** errorMessages); constexpr size_t MAX_SHADER_SIZE = 0x1900000u; @@ -132,7 +149,7 @@ namespace } OAT_HRESULT - __stdcall Open(OAT_D3D_INCLUDE_TYPE includeType, const char* fileName, const void* parentData, const void** data, unsigned int* size) override + STDMETHODCALLTYPE Open(OAT_D3D_INCLUDE_TYPE includeType, const char* fileName, const void* parentData, const void** data, unsigned int* size) override { const auto fullFileName = shader::GetSourceFileNameForShaderAssetName(fileName); auto file = m_search_path.Open(fullFileName); @@ -158,7 +175,7 @@ namespace return OAT_S_OK; } - OAT_HRESULT __stdcall Close(const void* data) override + OAT_HRESULT STDMETHODCALLTYPE Close(const void* data) override { for (auto i = m_file_buffers_in_use.begin(); i != m_file_buffers_in_use.end(); ++i) { @@ -185,6 +202,13 @@ namespace { #ifdef _WIN32 con::warn("Could not initialize shader compilation. Make sure DirectX is installed on your machine if you want to make use of it."); +#else +#ifdef ARCH_x86 +#define REQUIRED_VKD3D "lib32-vkd3d" +#else +#define REQUIRED_VKD3D "vkd3d" +#endif + con::warn("Could not initialize shader compilation. Make sure " REQUIRED_VKD3D " is installed if you want to make use of it."); #endif } @@ -207,6 +231,23 @@ namespace return; } + d3dCompile = reinterpret_cast(d3dCompileAddress); + compilationAvailable = true; +#else + const auto libvkd3dUtils = dlopen("libvkd3d-utils.so", RTLD_NOW); + if (!libvkd3dUtils) + { + PrintInitializationFailedMessage(); + return; + } + + const auto d3dCompileAddress = dlsym(libvkd3dUtils, "D3DCompile"); + if (!d3dCompileAddress) + { + PrintInitializationFailedMessage(); + return; + } + d3dCompile = reinterpret_cast(d3dCompileAddress); compilationAvailable = true; #endif From 4801b59b2ce353e7d1676d1a1ec663b7ffba3630 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Fri, 3 Apr 2026 14:01:06 +0200 Subject: [PATCH 06/10] chore: remove vkd3d shader compilation * It does not produce usable output for DirectX unfortunately --- src/ObjCompiling/Shader/D3DShaderCompiler.cpp | 198 +++--------------- 1 file changed, 30 insertions(+), 168 deletions(-) diff --git a/src/ObjCompiling/Shader/D3DShaderCompiler.cpp b/src/ObjCompiling/Shader/D3DShaderCompiler.cpp index 8eefdc263..e4302833a 100644 --- a/src/ObjCompiling/Shader/D3DShaderCompiler.cpp +++ b/src/ObjCompiling/Shader/D3DShaderCompiler.cpp @@ -11,136 +11,15 @@ #include #ifdef _WIN32 -#include -#else -#include +#include #endif namespace { - // The types based on vkd3d which is licensed under the - // GNU Lesser General Public License as published by the Free Software Foundation - // All types are prefixed with OAT_ to not cause conflicts as the original definition may be included - // depending on the platform. - // Types were duplicated to be available on any platform and to not require the corresponding library - // to be installed - - typedef int OAT_HRESULT; -#define OAT_SUCCEEDED(hr) ((OAT_HRESULT)(hr) >= 0) -#define OAT_FAILED(hr) ((OAT_HRESULT)(hr) < 0) - - typedef unsigned int OAT_ULONG; - typedef unsigned long OAT_ULONG_PTR; - typedef OAT_ULONG_PTR OAT_SIZE_T; - -#define OAT_HRESULT_TYPEDEF(x) ((OAT_HRESULT)x) - -#define OAT_S_OK OAT_HRESULT_TYPEDEF(0) -#define OAT_S_FALSE OAT_HRESULT_TYPEDEF(1) - -#define OAT_E_FAIL OAT_HRESULT_TYPEDEF(0x80004005) - -#define OAT_D3DCOMPILE_DEBUG 0x00000001 -#define OAT_D3DCOMPILE_SKIP_VALIDATION 0x00000002 -#define OAT_D3DCOMPILE_SKIP_OPTIMIZATION 0x00000004 -#define OAT_D3DCOMPILE_PACK_MATRIX_ROW_MAJOR 0x00000008 -#define OAT_D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR 0x00000010 -#define OAT_D3DCOMPILE_PARTIAL_PRECISION 0x00000020 -#define OAT_D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT 0x00000040 -#define OAT_D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT 0x00000080 -#define OAT_D3DCOMPILE_NO_PRESHADER 0x00000100 -#define OAT_D3DCOMPILE_AVOID_FLOW_CONTROL 0x00000200 -#define OAT_D3DCOMPILE_PREFER_FLOW_CONTROL 0x00000400 -#define OAT_D3DCOMPILE_ENABLE_STRICTNESS 0x00000800 -#define OAT_D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY 0x00001000 -#define OAT_D3DCOMPILE_IEEE_STRICTNESS 0x00002000 -#define OAT_D3DCOMPILE_OPTIMIZATION_LEVEL0 0x00004000 -#define OAT_D3DCOMPILE_OPTIMIZATION_LEVEL1 0x00000000 -#define OAT_D3DCOMPILE_OPTIMIZATION_LEVEL2 0x0000c000 -#define OAT_D3DCOMPILE_OPTIMIZATION_LEVEL3 0x00008000 -#define OAT_D3DCOMPILE_RESERVED16 0x00010000 -#define OAT_D3DCOMPILE_RESERVED17 0x00020000 -#define OAT_D3DCOMPILE_WARNINGS_ARE_ERRORS 0x00040000 -#define OAT_D3DCOMPILE_RESOURCES_MAY_ALIAS 0x00080000 -#define OAT_D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES 0x00100000 -#define OAT_D3DCOMPILE_ALL_RESOURCES_BOUND 0x00200000 -#define OAT_D3DCOMPILE_DEBUG_NAME_FOR_SOURCE 0x00400000 -#define OAT_D3DCOMPILE_DEBUG_NAME_FOR_BINARY 0x00800000 - -#ifndef _WIN32 -#ifdef __x86_64__ -#define __stdcall __attribute__((ms_abi)) -#else -#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || defined(__APPLE__) -#define __stdcall __attribute__((__stdcall__)) __attribute__((__force_align_arg_pointer__)) -#else -#define __stdcall __attribute__((__stdcall__)) -#endif -#endif -#endif -#define STDMETHODCALLTYPE __stdcall - - enum OAT_D3D_INCLUDE_TYPE : uint32_t - { - OAT_D3D_INCLUDE_LOCAL = 0, - OAT_D3D_INCLUDE_SYSTEM = 1 - }; - - struct OAT_ID3DInclude - { - // clang-format off - virtual OAT_HRESULT STDMETHODCALLTYPE Open(OAT_D3D_INCLUDE_TYPE includeType, const char* fileName, const void* parentData, const void** data, unsigned int* size) = 0; - virtual OAT_HRESULT STDMETHODCALLTYPE Close(const void* data) = 0; - // clang-format on - }; - - struct OAT_GUID - { - unsigned int Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; - }; - - typedef OAT_GUID OAT_IID; - - struct OAT_IUnknown - { - virtual OAT_HRESULT STDMETHODCALLTYPE QueryInterface(const OAT_IID& riid, void** object) = 0; - - virtual OAT_ULONG STDMETHODCALLTYPE AddRef() = 0; - - virtual OAT_ULONG STDMETHODCALLTYPE Release() = 0; - }; - - struct OAT_ID3DBlob : OAT_IUnknown - { - virtual void* STDMETHODCALLTYPE GetBufferPointer() = 0; - - virtual OAT_SIZE_T STDMETHODCALLTYPE GetBufferSize() = 0; - }; - - struct OAT_D3D_SHADER_MACRO - { - const char* Name; - const char* Definition; - }; - - typedef OAT_HRESULT(STDMETHODCALLTYPE* D3DCompile_t)(const void* data, - OAT_SIZE_T dataSize, - const char* filename, - const OAT_D3D_SHADER_MACRO* defines, - OAT_ID3DInclude* include, - const char* entrypoint, - const char* target, - unsigned int flags, - unsigned int effectFlags, - OAT_ID3DBlob** shader, - OAT_ID3DBlob** errorMessages); - +#ifdef _WIN32 constexpr size_t MAX_SHADER_SIZE = 0x1900000u; - class ShaderIncludeHandler : public OAT_ID3DInclude + class ShaderIncludeHandler : public ID3DInclude { public: explicit ShaderIncludeHandler(ISearchPath& searchPath) @@ -148,18 +27,17 @@ namespace { } - OAT_HRESULT - STDMETHODCALLTYPE Open(OAT_D3D_INCLUDE_TYPE includeType, const char* fileName, const void* parentData, const void** data, unsigned int* size) override + HRESULT __stdcall Open(D3D_INCLUDE_TYPE includeType, const char* fileName, const void* parentData, const void** data, unsigned int* size) override { const auto fullFileName = shader::GetSourceFileNameForShaderAssetName(fileName); auto file = m_search_path.Open(fullFileName); if (!file.IsOpen() || file.m_length <= 0) - return OAT_E_FAIL; + return E_FAIL; if (std::cmp_greater(file.m_length, MAX_SHADER_SIZE)) { con::error("Invalid shader source \"{}\": File too big: {}\n", fileName, file.m_length); - return OAT_E_FAIL; + return E_FAIL; } const auto shaderSize = static_cast(file.m_length); @@ -172,21 +50,21 @@ namespace m_file_buffers_in_use.push_back(std::move(shaderData)); - return OAT_S_OK; + return S_OK; } - OAT_HRESULT STDMETHODCALLTYPE Close(const void* data) override + HRESULT STDMETHODCALLTYPE Close(const void* data) override { for (auto i = m_file_buffers_in_use.begin(); i != m_file_buffers_in_use.end(); ++i) { if (i->get() == data) { m_file_buffers_in_use.erase(i); - return OAT_S_OK; + return S_OK; } } - return OAT_E_FAIL; + return E_FAIL; } private: @@ -196,28 +74,21 @@ namespace bool initialized = false; bool compilationAvailable = false; - D3DCompile_t d3dCompile = nullptr; + pD3DCompile d3dCompile = nullptr; void PrintInitializationFailedMessage() { -#ifdef _WIN32 con::warn("Could not initialize shader compilation. Make sure DirectX is installed on your machine if you want to make use of it."); -#else -#ifdef ARCH_x86 -#define REQUIRED_VKD3D "lib32-vkd3d" -#else -#define REQUIRED_VKD3D "vkd3d" -#endif - con::warn("Could not initialize shader compilation. Make sure " REQUIRED_VKD3D " is installed if you want to make use of it."); -#endif } +#endif + void InitializeShaderCompilation() { +#ifdef _WIN32 initialized = true; -#ifdef _WIN32 - const auto d3dCompiler = LoadLibraryA("D3DCOMPILER_47.dll"); + const auto d3dCompiler = LoadLibraryA("d3dcompiler_47.dll"); if (!d3dCompiler) { PrintInitializationFailedMessage(); @@ -231,24 +102,7 @@ namespace return; } - d3dCompile = reinterpret_cast(d3dCompileAddress); - compilationAvailable = true; -#else - const auto libvkd3dUtils = dlopen("libvkd3d-utils.so", RTLD_NOW); - if (!libvkd3dUtils) - { - PrintInitializationFailedMessage(); - return; - } - - const auto d3dCompileAddress = dlsym(libvkd3dUtils, "D3DCompile"); - if (!d3dCompileAddress) - { - PrintInitializationFailedMessage(); - return; - } - - d3dCompile = reinterpret_cast(d3dCompileAddress); + d3dCompile = reinterpret_cast(d3dCompileAddress); compilationAvailable = true; #endif } @@ -258,10 +112,14 @@ namespace shader { bool ShaderCompilationAvailable() { +#ifdef _WIN32 if (!initialized) InitializeShaderCompilation(); return compilationAvailable; +#else + return false; +#endif } result::Expected, std::string> CompileShader(const std::string& shaderFile, @@ -271,6 +129,7 @@ namespace shader ISearchPath& searchPath, MemoryManager& memory) { +#ifdef _WIN32 if (!initialized) InitializeShaderCompilation(); if (!compilationAvailable) @@ -289,16 +148,16 @@ namespace shader file.m_stream->read(shaderData.get(), static_cast(shaderSize)); file.m_stream.reset(); - unsigned shaderFlags = OAT_D3DCOMPILE_OPTIMIZATION_LEVEL1; + unsigned shaderFlags = D3DCOMPILE_OPTIMIZATION_LEVEL1; if (debug) - shaderFlags |= OAT_D3DCOMPILE_DEBUG; + shaderFlags |= D3DCOMPILE_DEBUG; ShaderIncludeHandler shaderIncluder(searchPath); - OAT_ID3DBlob* shaderBlob = nullptr; - OAT_ID3DBlob* errorBlob = nullptr; + ID3DBlob* shaderBlob = nullptr; + ID3DBlob* errorBlob = nullptr; const auto errorCode = d3dCompile(shaderData.get(), - static_cast(shaderSize), + static_cast(shaderSize), fileName.c_str(), nullptr, &shaderIncluder, @@ -309,7 +168,7 @@ namespace shader &shaderBlob, &errorBlob); - if (OAT_FAILED(errorCode)) + if (FAILED(errorCode)) { std::string errorMessage; @@ -339,5 +198,8 @@ namespace shader .m_shader_bin = assetShaderBuffer, .m_shader_size = shaderBlobSize, }); +#else + return result::Unexpected("Shader compilation unavailable"); +#endif } } // namespace shader From 1d1b9cc4d18b2b0a1b216410ef4dcea8ea77103f Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Wed, 8 Apr 2026 10:13:30 +0100 Subject: [PATCH 07/10] chore: use templating for iw4 shader compilation --- src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp | 4 +- .../IW4/Techset/PixelShaderCompilerIW4.cpp | 67 ----------- .../Game/IW4/Techset/PixelShaderCompilerIW4.h | 11 -- .../IW4/Techset/VertexShaderCompilerIW4.cpp | 67 ----------- .../IW4/Techset/VertexShaderCompilerIW4.h | 11 -- .../Techset/PixelShaderCompiler.cpp.template | 112 ++++++++++++++++++ .../Techset/PixelShaderCompiler.h.template | 41 +++++++ .../Techset/VertexShaderCompiler.cpp.template | 112 ++++++++++++++++++ .../Techset/VertexShaderCompiler.h.template | 41 +++++++ 9 files changed, 308 insertions(+), 158 deletions(-) delete mode 100644 src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp delete mode 100644 src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.h delete mode 100644 src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp delete mode 100644 src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.h create mode 100644 src/ObjCompiling/Techset/PixelShaderCompiler.cpp.template create mode 100644 src/ObjCompiling/Techset/PixelShaderCompiler.h.template create mode 100644 src/ObjCompiling/Techset/VertexShaderCompiler.cpp.template create mode 100644 src/ObjCompiling/Techset/VertexShaderCompiler.h.template diff --git a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp index 95a24fe0b..4504d761b 100644 --- a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp +++ b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp @@ -1,13 +1,13 @@ #include "ObjCompilerIW4.h" #include "Game/IW4/IW4.h" +#include "Game/IW4/Techset/PixelShaderCompilerIW4.h" #include "Game/IW4/Techset/TechniqueCompilerIW4.h" #include "Game/IW4/Techset/TechsetCompilerIW4.h" #include "Game/IW4/Techset/VertexDeclCompilerIW4.h" +#include "Game/IW4/Techset/VertexShaderCompilerIW4.h" #include "Image/ImageIwdPostProcessor.h" #include "Material/CompilerMaterialIW4.h" -#include "Techset/PixelShaderCompilerIW4.h" -#include "Techset/VertexShaderCompilerIW4.h" #include diff --git a/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp deleted file mode 100644 index 670790f77..000000000 --- a/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "PixelShaderCompilerIW4.h" - -#include "Game/IW4/IW4.h" -#include "Shader/D3DShaderCompiler.h" -#include "Utils/Logging/Log.h" - -#include -#include -#include - -using namespace IW4; - -namespace -{ - class PixelShaderCompilerIW4 final : public AssetCreator - { - public: - PixelShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath) - : m_memory(memory), - m_search_path(searchPath) - { - } - - AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override - { - auto result = shader::CompileShader(assetName, "PSMain", "ps_3_0", false, m_search_path, m_memory); - - if (result.has_value()) - { - const std::optional maybeShader(*std::move(result)); - if (!maybeShader.has_value()) - return AssetCreationResult::NoAction(); - - con::info("Compiled pixel shader \"{}\"", assetName); - - assert(maybeShader->m_shader_size % sizeof(uint32_t) == 0); - - auto* pixelShader = m_memory.Alloc(); - pixelShader->name = m_memory.Dup(assetName.c_str()); - pixelShader->prog.loadDef.program = static_cast(maybeShader->m_shader_bin); - pixelShader->prog.loadDef.programSize = static_cast(maybeShader->m_shader_size / sizeof(uint32_t)); - - return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, pixelShader))); - } - - con::error("Failed to compile pixel shader \"{}\": {}", assetName, result.error()); - return AssetCreationResult::Failure(); - } - - void FinalizeZone(AssetCreationContext& context) override {} - - private: - MemoryManager& m_memory; - ISearchPath& m_search_path; - }; -} // namespace - -namespace techset -{ - std::unique_ptr CreatePixelShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath) - { - if (!shader::ShaderCompilationAvailable()) - return nullptr; - - return std::make_unique(memory, searchPath); - } -} // namespace techset diff --git a/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.h b/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.h deleted file mode 100644 index 0486277b1..000000000 --- a/src/ObjCompiling/Game/IW4/Techset/PixelShaderCompilerIW4.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Asset/IAssetCreator.h" -#include "Utils/MemoryManager.h" - -#include - -namespace techset -{ - std::unique_ptr CreatePixelShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath); -} diff --git a/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp deleted file mode 100644 index 58db1ae42..000000000 --- a/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "VertexShaderCompilerIW4.h" - -#include "Game/IW4/IW4.h" -#include "Shader/D3DShaderCompiler.h" -#include "Utils/Logging/Log.h" - -#include -#include -#include - -using namespace IW4; - -namespace -{ - class VertexShaderCompilerIW4 final : public AssetCreator - { - public: - VertexShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath) - : m_memory(memory), - m_search_path(searchPath) - { - } - - AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override - { - auto result = shader::CompileShader(assetName, "VSMain", "vs_3_0", false, m_search_path, m_memory); - - if (result.has_value()) - { - const std::optional maybeShader(*std::move(result)); - if (!maybeShader.has_value()) - return AssetCreationResult::NoAction(); - - con::info("Compiled vertex shader \"{}\"", assetName); - - assert(maybeShader->m_shader_size % sizeof(uint32_t) == 0); - - auto* vertexShader = m_memory.Alloc(); - vertexShader->name = m_memory.Dup(assetName.c_str()); - vertexShader->prog.loadDef.program = static_cast(maybeShader->m_shader_bin); - vertexShader->prog.loadDef.programSize = static_cast(maybeShader->m_shader_size / sizeof(uint32_t)); - - return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, vertexShader))); - } - - con::error("Failed to compile vertex shader \"{}\": {}", assetName, result.error()); - return AssetCreationResult::Failure(); - } - - void FinalizeZone(AssetCreationContext& context) override {} - - private: - MemoryManager& m_memory; - ISearchPath& m_search_path; - }; -} // namespace - -namespace techset -{ - std::unique_ptr CreateVertexShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath) - { - if (!shader::ShaderCompilationAvailable()) - return nullptr; - - return std::make_unique(memory, searchPath); - } -} // namespace techset diff --git a/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.h b/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.h deleted file mode 100644 index c9f5042bb..000000000 --- a/src/ObjCompiling/Game/IW4/Techset/VertexShaderCompilerIW4.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Asset/IAssetCreator.h" -#include "Utils/MemoryManager.h" - -#include - -namespace techset -{ - std::unique_ptr CreateVertexShaderCompilerIW4(MemoryManager& memory, ISearchPath& searchPath); -} diff --git a/src/ObjCompiling/Techset/PixelShaderCompiler.cpp.template b/src/ObjCompiling/Techset/PixelShaderCompiler.cpp.template new file mode 100644 index 000000000..14fc8e6e2 --- /dev/null +++ b/src/ObjCompiling/Techset/PixelShaderCompiler.cpp.template @@ -0,0 +1,112 @@ +#options GAME(IW4) + +#filename "Game/" + GAME + "/Techset/PixelShaderCompiler" + GAME + ".cpp" + +#set COMPILER_HEADER "\"PixelShaderCompiler" + GAME + ".h\"" +#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\"" + +#if GAME == "IW3" +#define FEATURE_IW3 +#define IS_DX9 +#define IS_SUB_ASSET +#elif GAME == "IW4" +#define FEATURE_IW4 +#define IS_DX9 +#elif GAME == "IW5" +#define FEATURE_IW5 +#define IS_DX9 +#elif GAME == "T5" +#define FEATURE_T5 +#define IS_DX9 +#define IS_SUB_ASSET +#elif GAME == "T6" +#define FEATURE_T6 +#define IS_DX11 +#define IS_SUB_ASSET +#endif + +#include COMPILER_HEADER + +#include GAME_HEADER +#include "Shader/D3DShaderCompiler.h" +#include "Utils/Logging/Log.h" + +#include +#include +#include + +using namespace GAME; + +#set COMPILER_CLASS_NAME "PixelShaderCompiler" + GAME + +#if defined(IS_SUB_ASSET) +#define ABSTRACT_CREATOR_NAME SubAssetCreator +#define OVERRIDDEN_CREATOR_METHOD CreateSubAsset +#define ADD_ASSET_METHOD AddSubAsset +#define ASSET_NAME SubAssetPixelShader +#define INTERFACE_NAME ISubAssetCreator +#else +#define ABSTRACT_CREATOR_NAME AssetCreator +#define OVERRIDDEN_CREATOR_METHOD CreateAsset +#define ADD_ASSET_METHOD AddAsset +#define ASSET_NAME AssetPixelShader +#define INTERFACE_NAME IAssetCreator +#endif + +namespace +{ + class COMPILER_CLASS_NAME final : public ABSTRACT_CREATOR_NAME + { + public: + COMPILER_CLASS_NAME(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult OVERRIDDEN_CREATOR_METHOD(const std::string& assetName, AssetCreationContext& context) override + { + auto result = shader::CompileShader(assetName, "PSMain", "ps_3_0", false, m_search_path, m_memory); + + if (result.has_value()) + { + const std::optional maybeShader(*std::move(result)); + if (!maybeShader.has_value()) + return AssetCreationResult::NoAction(); + + con::info("Compiled pixel shader \"{}\"", assetName); + + assert(maybeShader->m_shader_size % sizeof(uint32_t) == 0); + + auto* pixelShader = m_memory.Alloc(); + pixelShader->name = m_memory.Dup(assetName.c_str()); + pixelShader->prog.loadDef.program = static_cast(maybeShader->m_shader_bin); + pixelShader->prog.loadDef.programSize = static_cast(maybeShader->m_shader_size / sizeof(uint32_t)); + + return AssetCreationResult::Success(context.ADD_ASSET_METHOD(AssetRegistration(assetName, pixelShader))); + } + + con::error("Failed to compile pixel shader \"{}\": {}", assetName, result.error()); + return AssetCreationResult::Failure(); + } + + void FinalizeZone(AssetCreationContext& context) override {} + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +#set CREATE_COMPILER_METHOD "CreatePixelShaderCompiler" + GAME + +namespace techset +{ + std::unique_ptr CREATE_COMPILER_METHOD(MemoryManager& memory, ISearchPath& searchPath) + { + if (!shader::ShaderCompilationAvailable()) + return nullptr; + + return std::make_unique(memory, searchPath); + } +} // namespace techset diff --git a/src/ObjCompiling/Techset/PixelShaderCompiler.h.template b/src/ObjCompiling/Techset/PixelShaderCompiler.h.template new file mode 100644 index 000000000..8c5f1e818 --- /dev/null +++ b/src/ObjCompiling/Techset/PixelShaderCompiler.h.template @@ -0,0 +1,41 @@ +#options GAME(IW4) + +#filename "Game/" + GAME + "/Techset/PixelShaderCompiler" + GAME + ".h" + +#if GAME == "IW3" +#define FEATURE_IW3 +#define IS_SUB_ASSET +#elif GAME == "IW4" +#define FEATURE_IW4 +#elif GAME == "IW5" +#define FEATURE_IW5 +#elif GAME == "T5" +#define FEATURE_T5 +#define IS_SUB_ASSET +#elif GAME == "T6" +#define FEATURE_T6 +#define IS_SUB_ASSET +#endif + +// This file was templated. +// See PixelShaderCompiler.h.template. +// Do not modify, changes will be lost. +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Utils/MemoryManager.h" + +#include + +#set CREATE_COMPILER_METHOD "CreatePixelShaderCompiler" + GAME + +#if defined(IS_SUB_ASSET) +#define INTERFACE_NAME ISubAssetCreator +#else +#define INTERFACE_NAME IAssetCreator +#endif + +namespace techset +{ + std::unique_ptr CREATE_COMPILER_METHOD(MemoryManager& memory, ISearchPath& searchPath); +} diff --git a/src/ObjCompiling/Techset/VertexShaderCompiler.cpp.template b/src/ObjCompiling/Techset/VertexShaderCompiler.cpp.template new file mode 100644 index 000000000..653421a1e --- /dev/null +++ b/src/ObjCompiling/Techset/VertexShaderCompiler.cpp.template @@ -0,0 +1,112 @@ +#options GAME(IW4) + +#filename "Game/" + GAME + "/Techset/VertexShaderCompiler" + GAME + ".cpp" + +#set COMPILER_HEADER "\"VertexShaderCompiler" + GAME + ".h\"" +#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\"" + +#if GAME == "IW3" +#define FEATURE_IW3 +#define IS_DX9 +#define IS_SUB_ASSET +#elif GAME == "IW4" +#define FEATURE_IW4 +#define IS_DX9 +#elif GAME == "IW5" +#define FEATURE_IW5 +#define IS_DX9 +#elif GAME == "T5" +#define FEATURE_T5 +#define IS_DX9 +#define IS_SUB_ASSET +#elif GAME == "T6" +#define FEATURE_T6 +#define IS_DX11 +#define IS_SUB_ASSET +#endif + +#include COMPILER_HEADER + +#include GAME_HEADER +#include "Shader/D3DShaderCompiler.h" +#include "Utils/Logging/Log.h" + +#include +#include +#include + +using namespace GAME; + +#set COMPILER_CLASS_NAME "VertexShaderCompiler" + GAME + +#if defined(IS_SUB_ASSET) +#define ABSTRACT_CREATOR_NAME SubAssetCreator +#define OVERRIDDEN_CREATOR_METHOD CreateSubAsset +#define ADD_ASSET_METHOD AddSubAsset +#define ASSET_NAME SubAssetVertexShader +#define INTERFACE_NAME ISubAssetCreator +#else +#define ABSTRACT_CREATOR_NAME AssetCreator +#define OVERRIDDEN_CREATOR_METHOD CreateAsset +#define ADD_ASSET_METHOD AddAsset +#define ASSET_NAME AssetVertexShader +#define INTERFACE_NAME IAssetCreator +#endif + +namespace +{ + class COMPILER_CLASS_NAME final : public ABSTRACT_CREATOR_NAME + { + public: + COMPILER_CLASS_NAME(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult OVERRIDDEN_CREATOR_METHOD(const std::string& assetName, AssetCreationContext& context) override + { + auto result = shader::CompileShader(assetName, "VSMain", "vs_3_0", false, m_search_path, m_memory); + + if (result.has_value()) + { + const std::optional maybeShader(*std::move(result)); + if (!maybeShader.has_value()) + return AssetCreationResult::NoAction(); + + con::info("Compiled vertex shader \"{}\"", assetName); + + assert(maybeShader->m_shader_size % sizeof(uint32_t) == 0); + + auto* vertexShader = m_memory.Alloc(); + vertexShader->name = m_memory.Dup(assetName.c_str()); + vertexShader->prog.loadDef.program = static_cast(maybeShader->m_shader_bin); + vertexShader->prog.loadDef.programSize = static_cast(maybeShader->m_shader_size / sizeof(uint32_t)); + + return AssetCreationResult::Success(context.ADD_ASSET_METHOD(AssetRegistration(assetName, vertexShader))); + } + + con::error("Failed to compile vertex shader \"{}\": {}", assetName, result.error()); + return AssetCreationResult::Failure(); + } + + void FinalizeZone(AssetCreationContext& context) override {} + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +#set CREATE_COMPILER_METHOD "CreateVertexShaderCompiler" + GAME + +namespace techset +{ + std::unique_ptr CREATE_COMPILER_METHOD(MemoryManager& memory, ISearchPath& searchPath) + { + if (!shader::ShaderCompilationAvailable()) + return nullptr; + + return std::make_unique(memory, searchPath); + } +} // namespace techset diff --git a/src/ObjCompiling/Techset/VertexShaderCompiler.h.template b/src/ObjCompiling/Techset/VertexShaderCompiler.h.template new file mode 100644 index 000000000..f4076334f --- /dev/null +++ b/src/ObjCompiling/Techset/VertexShaderCompiler.h.template @@ -0,0 +1,41 @@ +#options GAME(IW4) + +#filename "Game/" + GAME + "/Techset/VertexShaderCompiler" + GAME + ".h" + +#if GAME == "IW3" +#define FEATURE_IW3 +#define IS_SUB_ASSET +#elif GAME == "IW4" +#define FEATURE_IW4 +#elif GAME == "IW5" +#define FEATURE_IW5 +#elif GAME == "T5" +#define FEATURE_T5 +#define IS_SUB_ASSET +#elif GAME == "T6" +#define FEATURE_T6 +#define IS_SUB_ASSET +#endif + +// This file was templated. +// See VertexShaderCompiler.h.template. +// Do not modify, changes will be lost. +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Utils/MemoryManager.h" + +#include + +#set CREATE_COMPILER_METHOD "CreateVertexShaderCompiler" + GAME + +#if defined(IS_SUB_ASSET) +#define INTERFACE_NAME ISubAssetCreator +#else +#define INTERFACE_NAME IAssetCreator +#endif + +namespace techset +{ + std::unique_ptr CREATE_COMPILER_METHOD(MemoryManager& memory, ISearchPath& searchPath); +} From 388c0272b0a9686667a4e583e5620c0ee3581032 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Wed, 8 Apr 2026 10:39:24 +0100 Subject: [PATCH 08/10] feat: add shader compilers for IW3,IW5,T5,T6 --- src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp | 4 ++++ src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp | 4 ++++ src/ObjCompiling/Game/T5/ObjCompilerT5.cpp | 4 ++++ src/ObjCompiling/Game/T6/ObjCompilerT6.cpp | 4 ++++ .../Techset/PixelShaderCompiler.cpp.template | 24 +++++++++++++++---- .../Techset/PixelShaderCompiler.h.template | 2 +- .../Techset/VertexShaderCompiler.cpp.template | 24 +++++++++++++++---- .../Techset/VertexShaderCompiler.h.template | 2 +- 8 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp index ad084e43e..a1b03bbb6 100644 --- a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp +++ b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp @@ -1,9 +1,11 @@ #include "ObjCompilerIW3.h" #include "Game/IW3/IW3.h" +#include "Game/IW3/Techset/PixelShaderCompilerIW3.h" #include "Game/IW3/Techset/TechniqueCompilerIW3.h" #include "Game/IW3/Techset/TechsetCompilerIW3.h" #include "Game/IW3/Techset/VertexDeclCompilerIW3.h" +#include "Game/IW3/Techset/VertexShaderCompilerIW3.h" #include "Image/ImageIwdPostProcessor.h" #include @@ -20,6 +22,8 @@ namespace collection.AddSubAssetCreator(techset::CreateTechniqueCompilerIW3(memory, zone, searchPath)); collection.AddSubAssetCreator(techset::CreateVertexDeclCompilerIW3(memory)); + collection.AddSubAssetCreator(techset::CreateVertexShaderCompilerIW3(memory, searchPath)); + collection.AddSubAssetCreator(techset::CreatePixelShaderCompilerIW3(memory, searchPath)); } void ConfigurePostProcessors(AssetCreatorCollection& collection, diff --git a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp index 5a6ba6d35..e2338bc52 100644 --- a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp +++ b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp @@ -1,9 +1,11 @@ #include "ObjCompilerIW5.h" #include "Game/IW5/IW5.h" +#include "Game/IW5/Techset/PixelShaderCompilerIW5.h" #include "Game/IW5/Techset/TechniqueCompilerIW5.h" #include "Game/IW5/Techset/TechsetCompilerIW5.h" #include "Game/IW5/Techset/VertexDeclCompilerIW5.h" +#include "Game/IW5/Techset/VertexShaderCompilerIW5.h" #include "Image/ImageIwdPostProcessor.h" #include @@ -17,6 +19,8 @@ namespace auto& memory = zone.Memory(); collection.AddAssetCreator(techset::CreateVertexDeclCompilerIW5(memory)); + collection.AddAssetCreator(techset::CreateVertexShaderCompilerIW5(memory, searchPath)); + collection.AddAssetCreator(techset::CreatePixelShaderCompilerIW5(memory, searchPath)); collection.AddAssetCreator(techset::CreateTechsetCompilerIW5(memory, searchPath)); collection.AddSubAssetCreator(techset::CreateTechniqueCompilerIW5(memory, zone, searchPath)); diff --git a/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp index 12a635564..cea01648b 100644 --- a/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp +++ b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp @@ -1,9 +1,11 @@ #include "ObjCompilerT5.h" #include "Game/T5/T5.h" +#include "Game/T5/Techset/PixelShaderCompilerT5.h" #include "Game/T5/Techset/TechniqueCompilerT5.h" #include "Game/T5/Techset/TechsetCompilerT5.h" #include "Game/T5/Techset/VertexDeclCompilerT5.h" +#include "Game/T5/Techset/VertexShaderCompilerT5.h" #include "Image/ImageIwdPostProcessor.h" #include @@ -20,6 +22,8 @@ namespace collection.AddSubAssetCreator(techset::CreateTechniqueCompilerT5(memory, zone, searchPath)); collection.AddSubAssetCreator(techset::CreateVertexDeclCompilerT5(memory)); + collection.AddSubAssetCreator(techset::CreateVertexShaderCompilerT5(memory, searchPath)); + collection.AddSubAssetCreator(techset::CreatePixelShaderCompilerT5(memory, searchPath)); } void ConfigurePostProcessors(AssetCreatorCollection& collection, diff --git a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp index 37ac95293..0577f4403 100644 --- a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp +++ b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp @@ -1,9 +1,11 @@ #include "ObjCompilerT6.h" #include "Game/T6/T6.h" +#include "Game/T6/Techset/PixelShaderCompilerT6.h" #include "Game/T6/Techset/TechniqueCompilerT6.h" #include "Game/T6/Techset/TechsetCompilerT6.h" #include "Game/T6/Techset/VertexDeclCompilerT6.h" +#include "Game/T6/Techset/VertexShaderCompilerT6.h" #include "Image/ImageIPakPostProcessor.h" #include "Image/ImageIwdPostProcessor.h" #include "KeyValuePairs/KeyValuePairsCompilerT6.h" @@ -27,6 +29,8 @@ namespace collection.AddSubAssetCreator(techset::CreateTechniqueCompilerT6(memory, zone, searchPath)); collection.AddSubAssetCreator(techset::CreateVertexDeclCompilerT6(memory)); + collection.AddSubAssetCreator(techset::CreateVertexShaderCompilerT6(memory, searchPath)); + collection.AddSubAssetCreator(techset::CreatePixelShaderCompilerT6(memory, searchPath)); } void ConfigurePostProcessors(AssetCreatorCollection& collection, diff --git a/src/ObjCompiling/Techset/PixelShaderCompiler.cpp.template b/src/ObjCompiling/Techset/PixelShaderCompiler.cpp.template index 14fc8e6e2..765532597 100644 --- a/src/ObjCompiling/Techset/PixelShaderCompiler.cpp.template +++ b/src/ObjCompiling/Techset/PixelShaderCompiler.cpp.template @@ -1,4 +1,4 @@ -#options GAME(IW4) +#options GAME(IW3, IW4, IW5, T5, T6) #filename "Game/" + GAME + "/Techset/PixelShaderCompiler" + GAME + ".cpp" @@ -66,7 +66,16 @@ namespace AssetCreationResult OVERRIDDEN_CREATOR_METHOD(const std::string& assetName, AssetCreationContext& context) override { - auto result = shader::CompileShader(assetName, "PSMain", "ps_3_0", false, m_search_path, m_memory); + auto result = shader::CompileShader(assetName, + "PSMain", +#ifdef IS_DX9 + "ps_3_0", +#else + "ps_4_0", +#endif + false, + m_search_path, + m_memory); if (result.has_value()) { @@ -76,12 +85,19 @@ namespace con::info("Compiled pixel shader \"{}\"", assetName); +#ifdef IS_DX9 assert(maybeShader->m_shader_size % sizeof(uint32_t) == 0); +#endif auto* pixelShader = m_memory.Alloc(); pixelShader->name = m_memory.Dup(assetName.c_str()); - pixelShader->prog.loadDef.program = static_cast(maybeShader->m_shader_bin); - pixelShader->prog.loadDef.programSize = static_cast(maybeShader->m_shader_size / sizeof(uint32_t)); + pixelShader->prog.loadDef.program = static_cast(maybeShader->m_shader_bin); +#ifdef IS_DX9 + pixelShader->prog.loadDef.programSize = static_cast( + maybeShader->m_shader_size / sizeof(std::remove_pointer_t)); +#else + pixelShader->prog.loadDef.programSize = static_cast(maybeShader->m_shader_size); +#endif return AssetCreationResult::Success(context.ADD_ASSET_METHOD(AssetRegistration(assetName, pixelShader))); } diff --git a/src/ObjCompiling/Techset/PixelShaderCompiler.h.template b/src/ObjCompiling/Techset/PixelShaderCompiler.h.template index 8c5f1e818..67bfd9aeb 100644 --- a/src/ObjCompiling/Techset/PixelShaderCompiler.h.template +++ b/src/ObjCompiling/Techset/PixelShaderCompiler.h.template @@ -1,4 +1,4 @@ -#options GAME(IW4) +#options GAME(IW3, IW4, IW5, T5, T6) #filename "Game/" + GAME + "/Techset/PixelShaderCompiler" + GAME + ".h" diff --git a/src/ObjCompiling/Techset/VertexShaderCompiler.cpp.template b/src/ObjCompiling/Techset/VertexShaderCompiler.cpp.template index 653421a1e..0282ffe0d 100644 --- a/src/ObjCompiling/Techset/VertexShaderCompiler.cpp.template +++ b/src/ObjCompiling/Techset/VertexShaderCompiler.cpp.template @@ -1,4 +1,4 @@ -#options GAME(IW4) +#options GAME(IW3, IW4, IW5, T5, T6) #filename "Game/" + GAME + "/Techset/VertexShaderCompiler" + GAME + ".cpp" @@ -66,7 +66,16 @@ namespace AssetCreationResult OVERRIDDEN_CREATOR_METHOD(const std::string& assetName, AssetCreationContext& context) override { - auto result = shader::CompileShader(assetName, "VSMain", "vs_3_0", false, m_search_path, m_memory); + auto result = shader::CompileShader(assetName, + "VSMain", +#ifdef IS_DX9 + "vs_3_0", +#else + "vs_4_0", +#endif + false, + m_search_path, + m_memory); if (result.has_value()) { @@ -76,12 +85,19 @@ namespace con::info("Compiled vertex shader \"{}\"", assetName); +#ifdef IS_DX9 assert(maybeShader->m_shader_size % sizeof(uint32_t) == 0); +#endif auto* vertexShader = m_memory.Alloc(); vertexShader->name = m_memory.Dup(assetName.c_str()); - vertexShader->prog.loadDef.program = static_cast(maybeShader->m_shader_bin); - vertexShader->prog.loadDef.programSize = static_cast(maybeShader->m_shader_size / sizeof(uint32_t)); + vertexShader->prog.loadDef.program = static_cast(maybeShader->m_shader_bin); +#ifdef IS_DX9 + vertexShader->prog.loadDef.programSize = static_cast( + maybeShader->m_shader_size / sizeof(std::remove_pointer_t)); +#else + vertexShader->prog.loadDef.programSize = static_cast(maybeShader->m_shader_size); +#endif return AssetCreationResult::Success(context.ADD_ASSET_METHOD(AssetRegistration(assetName, vertexShader))); } diff --git a/src/ObjCompiling/Techset/VertexShaderCompiler.h.template b/src/ObjCompiling/Techset/VertexShaderCompiler.h.template index f4076334f..509ebdf13 100644 --- a/src/ObjCompiling/Techset/VertexShaderCompiler.h.template +++ b/src/ObjCompiling/Techset/VertexShaderCompiler.h.template @@ -1,4 +1,4 @@ -#options GAME(IW4) +#options GAME(IW3, IW4, IW5, T5, T6) #filename "Game/" + GAME + "/Techset/VertexShaderCompiler" + GAME + ".h" From b90feffe14d4eee4f8d0c161509bf1d705db6907 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Wed, 8 Apr 2026 11:15:48 +0100 Subject: [PATCH 09/10] chore: add and fixup hlsl game defs for iw3,iw4,iw5,t5 --- raw/iw3/shader/include/IW3.hlsl | 114 ++++++++ raw/iw4/shader/include/IW4.hlsl | 120 +++++---- .../techniques/distortion_scale.tech.template | 2 +- .../techniques/particle_cloud.tech.template | 20 +- .../techniques/trivial_vertcol_simple2d.tech | 2 - raw/iw5/shader/include/IW5.hlsl | 167 ++++++++++++ raw/iw5/shader/trivial_vertcol_simple.hlsl | 33 +++ raw/t5/shader/include/T5.hlsl | 254 ++++++++++++++++++ 8 files changed, 651 insertions(+), 61 deletions(-) create mode 100644 raw/iw3/shader/include/IW3.hlsl create mode 100644 raw/iw5/shader/include/IW5.hlsl create mode 100644 raw/iw5/shader/trivial_vertcol_simple.hlsl create mode 100644 raw/t5/shader/include/T5.hlsl diff --git a/raw/iw3/shader/include/IW3.hlsl b/raw/iw3/shader/include/IW3.hlsl new file mode 100644 index 000000000..6414ee3e9 --- /dev/null +++ b/raw/iw3/shader/include/IW3.hlsl @@ -0,0 +1,114 @@ +// ============================= +// IW3 code constants +// ============================= + +extern float4 lightPosition; +extern float4 lightDiffuse; +extern float4 lightSpecular; +extern float4 lightSpotDir; +extern float4 lightSpotFactors; +extern float4 nearPlaneOrg; +extern float4 nearPlaneDx; +extern float4 nearPlaneDy; +extern float4 shadowParms; +extern float4 shadowmapPolygonOffset; +extern float4 renderTargetSize; +extern float4 lightFalloffPlacement; +extern float4 dofEquationViewModelAndFarBlur; +extern float4 dofEquationScene; +extern float4 dofLerpScale; +extern float4 dofLerpBias; +extern float4 dofRowDelta; +extern float4 particleCloudColor; +extern float4 gameTime; +extern float4 pixelCostFracs; +extern float4 pixelCostDecode; +extern float4 filterTap[8]; +extern float4 colorMatrixR; +extern float4 colorMatrixG; +extern float4 colorMatrixB; +extern float4 shadowmapSwitchPartition; +extern float4 shadowmapScale; +extern float4 zNear; +extern float4 sunPosition; +extern float4 sunDiffuse; +extern float4 sunSpecular; +extern float4 lightingLookupScale; +extern float4 debugBumpmap; +extern float4 materialColor; +extern float4 fogConsts; +extern float4 fogColor; +extern float4 glowSetup; +extern float4 glowApply; +extern float4 colorBias; +extern float4 colorTintBase; +extern float4 colorTintDelta; +extern float4 outdoorFeatherParms; +extern float4 envMapParms; +extern float4 spotShadowmapPixelAdjust; +extern float4 clipSpaceLookupScale; +extern float4 clipSpaceLookupOffset; +extern float4 particleCloudMatrix; +extern float4 depthFromClip; +extern float4 codeMeshArg[2]; +extern float4 baseLightingCoords; +extern float4x4 worldMatrix; +extern float4x4 inverseWorldMatrix; +extern float4x4 transposeWorldMatrix; +extern float4x4 inverseTransposeWorldMatrix; +extern float4x4 viewMatrix; +extern float4x4 inverseViewMatrix; +extern float4x4 transposeViewMatrix; +extern float4x4 inverseTransposeViewMatrix; +extern float4x4 projectionMatrix; +extern float4x4 inverseProjectionMatrix; +extern float4x4 transposeProjectionMatrix; +extern float4x4 inverseTransposeProjectionMatrix; +extern float4x4 worldViewMatrix; +extern float4x4 inverseWorldViewMatrix; +extern float4x4 transposeWorldViewMatrix; +extern float4x4 inverseTransposeWorldViewMatrix; +extern float4x4 viewProjectionMatrix; +extern float4x4 inverseViewProjectionMatrix; +extern float4x4 transposeViewProjectionMatrix; +extern float4x4 inverseTransposeViewProjectionMatrix; +extern float4x4 worldViewProjectionMatrix; +extern float4x4 inverseWorldViewProjectionMatrix; +extern float4x4 transposeWorldViewProjectionMatrix; +extern float4x4 inverseTransposeWorldViewProjectionMatrix; +extern float4x4 shadowLookupMatrix; +extern float4x4 inverseShadowLookupMatrix; +extern float4x4 transposeShadowLookupMatrix; +extern float4x4 inverseTransposeShadowLookupMatrix; +extern float4x4 worldOutdoorLookupMatrix; +extern float4x4 inverseWorldOutdoorLookupMatrix; +extern float4x4 transposeWorldOutdoorLookupMatrix; +extern float4x4 inverseTransposeWorldOutdoorLookupMatrix; + +extern sampler2D black; +extern sampler2D white; +extern sampler2D identityNormalMap; +extern sampler2D modelLightingSampler; +extern sampler2D lightmapSamplerPrimary; +extern sampler2D lightmapSamplerSecondary; +extern sampler2D shadowCookieSampler; +extern sampler2D shadowmapSamplerSun; +extern sampler2D shadowmapSamplerSpot; +extern sampler2D feedbackSampler; +extern sampler2D resolvedPostSun; +extern sampler2D resolvedScene; +extern sampler2D postEffect0; +extern sampler2D postEffect1; +extern sampler2D sky; +extern sampler2D attenuationSampler; +extern sampler2D dynamicShadowSampler; +extern sampler2D outdoor; +extern sampler2D floatZSampler; +extern sampler2D processedFloatZSampler; +extern sampler2D rawFloatZSampler; +extern sampler2D caseTexture; +extern sampler2D cinematicYSampler; +extern sampler2D cinematicCrSampler; +extern sampler2D cinematicCbSampler; +extern sampler2D cinematicASampler; +extern sampler2D reflectionProbeSampler; diff --git a/raw/iw4/shader/include/IW4.hlsl b/raw/iw4/shader/include/IW4.hlsl index 278d5631d..00811b626 100644 --- a/raw/iw4/shader/include/IW4.hlsl +++ b/raw/iw4/shader/include/IW4.hlsl @@ -2,14 +2,35 @@ // IW4 code constants // ============================= -extern float4 baseLightingCoords; -extern float4 lightprobeAmbient; -extern float4 fullscreenDistortion; -extern float4 fadeEffect; -extern float4 lightingLookupScale; -extern float4 debugBumpmap; +extern float4 lightPosition; +extern float4 lightDiffuse; +extern float4 lightSpecular; +extern float4 lightSpotDir; +extern float4 lightSpotFactors; +extern float4 lightFalloffPlacement; +extern float4 particleCloudColor; +extern float4 gameTime; extern float4 pixelCostFracs; extern float4 pixelCostDecode; +extern float4 filterTap[8]; +extern float4 colorMatrixR; +extern float4 colorMatrixG; +extern float4 colorMatrixB; +extern float4 shadowmapPolygonOffset; +extern float4 renderTargetSize; +extern float4 dofEquationViewModelAndFarBlur; +extern float4 dofEquationScene; +extern float4 dofLerpScale; +extern float4 dofLerpBias; +extern float4 dofRowDelta; +extern float4 motionMatrixX; +extern float4 motionMatrixY; +extern float4 motionMatrixW; +extern float4 shadowmapSwitchPartition; +extern float4 shadowmapScale; +extern float4 zNear; +extern float4 lightingLookupScale; +extern float4 debugBumpmap; extern float4 materialColor; extern float4 fogConsts; extern float4 fogColorLinear; @@ -20,35 +41,25 @@ extern float4 fogSunColorGamma; extern float4 fogSunDir; extern float4 glowSetup; extern float4 glowApply; -extern float4 filterTap[8]; -extern float4 codeMeshArg[2]; -extern float4 renderTargetSize; -extern float4 shadowmapSwitchPartition; -extern float4 shadowmapScale; -extern float4 shadowmapPolygonOffset; -extern float4 zNear; -extern float4 clipSpaceLookupScale; -extern float4 clipSpaceLookupOffset; -extern float4 dofEquationViewModelAndFarBlur; -extern float4 dofEquationScene; -extern float4 dofLerpScale; -extern float4 dofLerpBias; -extern float4 dofRowDelta; -extern float4 depthFromClip; -extern float4 outdoorFeatherParms; -extern float4 envMapParms; -extern float4 colorMatrixR; -extern float4 colorMatrixG; -extern float4 colorMatrixB; extern float4 colorBias; extern float4 colorTintBase; extern float4 colorTintDelta; extern float4 colorTintQuadraticDelta; -extern float4 motionMatrixX; -extern float4 motionMatrixY; -extern float4 motionMatrixW; -extern float4 gameTime; -extern float4 particleCloudColor; +extern float4 outdoorFeatherParms; +extern float4 envMapParms; +extern float4 sunShadowmapPixelAdjust; +extern float4 spotShadowmapPixelAdjust; +extern float4 fullscreenDistortion; +extern float4 fadeEffect; +extern float4 viewportDimensions; +extern float4 framebufferRead; +extern float4 baseLightingCoords; +extern float4 lightprobeAmbient; +extern float4 nearPlaneOrg; +extern float4 nearPlaneDx; +extern float4 nearPlaneDy; +extern float4 clipSpaceLookupScale; +extern float4 clipSpaceLookupOffset; extern float4 particleCloudMatrix; extern float4 particleCloudMatrix1; extern float4 particleCloudMatrix2; @@ -57,23 +68,8 @@ extern float4 particleCloudSparkColor1; extern float4 particleCloudSparkColor2; extern float4 particleFountainParms0; extern float4 particleFountainParms1; -extern float4 viewportDimensions; -extern float4 framebufferRead; - -extern float4 nearPlaneOrg; -extern float4 nearPlaneDx; -extern float4 nearPlaneDy; - -extern float4 lightPosition; -extern float4 lightDiffuse; -extern float4 lightSpecular; -extern float4 lightSpotDir; -extern float4 lightSpotFactors; -extern float4 lightFalloffPlacement; - -extern float4 sunShadowmapPixelAdjust; -extern float4 spotShadowmapPixelAdjust; - +extern float4 depthFromClip; +extern float4 codeMeshArg[2]; extern float4x4 viewMatrix; extern float4x4 inverseViewMatrix; extern float4x4 transposeViewMatrix; @@ -130,3 +126,31 @@ extern float4x4 worldViewProjectionMatrix2; extern float4x4 inverseWorldViewProjectionMatrix2; extern float4x4 transposeWorldViewProjectionMatrix2; extern float4x4 inverseTransposeWorldViewProjectionMatrix2; + +extern sampler2D black; +extern sampler2D white; +extern sampler2D identityNormalMap; +extern sampler2D modelLightingSampler; +extern sampler2D lightmapSamplerPrimary; +extern sampler2D lightmapSamplerSecondary; +extern sampler2D shadowmapSamplerSun; +extern sampler2D shadowmapSamplerSpot; +extern sampler2D feedbackSampler; +extern sampler2D resolvedPostSun; +extern sampler2D resolvedScene; +extern sampler2D postEffect0; +extern sampler2D postEffect1; +extern sampler2D attenuationSampler; +extern sampler2D outdoor; +extern sampler2D floatZSampler; +extern sampler2D processedFloatZSampler; +extern sampler2D rawFloatZSampler; +extern sampler2D halfParticleColorSampler; +extern sampler2D halfParticleDepthSampler; +extern sampler2D caseTexture; +extern sampler2D cinematicYSampler; +extern sampler2D cinematicCrSampler; +extern sampler2D cinematicCbSampler; +extern sampler2D cinematicASampler; +extern sampler2D reflectionProbeSampler; +extern sampler2D alternateSceneSampler; diff --git a/raw/iw4/techniques/distortion_scale.tech.template b/raw/iw4/techniques/distortion_scale.tech.template index 9797b66cf..136f18783 100644 --- a/raw/iw4/techniques/distortion_scale.tech.template +++ b/raw/iw4/techniques/distortion_scale.tech.template @@ -30,7 +30,7 @@ vertexShader 3.0 VERTEX_SHADER { - worldViewProjectionMatrix = constant.transposeWorldViewProjectionMatrix; + worldViewProjectionMatrix = constant.worldViewProjectionMatrix; #ifdef UV_ANIM uvAnimParms = material.uvAnimParms; #endif diff --git a/raw/iw4/techniques/particle_cloud.tech.template b/raw/iw4/techniques/particle_cloud.tech.template index 0b27dab10..7a4e0e23c 100644 --- a/raw/iw4/techniques/particle_cloud.tech.template +++ b/raw/iw4/techniques/particle_cloud.tech.template @@ -48,17 +48,17 @@ vertexShader 3.0 VERTEX_SHADER { - worldViewMatrix = constant.transposeWorldViewMatrix; + worldViewMatrix = constant.worldViewMatrix; #if MODE == "spark" - worldViewMatrix1 = constant.transposeWorldViewMatrix1; - worldViewMatrix2 = constant.transposeWorldViewMatrix2; + worldViewMatrix1 = constant.worldViewMatrix1; + worldViewMatrix2 = constant.worldViewMatrix2; #endif #ifdef OUTDOOR - worldOutdoorLookupMatrix = constant.transposeWorldOutdoorLookupMatrix; + worldOutdoorLookupMatrix = constant.worldOutdoorLookupMatrix; #endif - projectionMatrix = constant.transposeProjectionMatrix; + projectionMatrix = constant.projectionMatrix; #ifdef SPOT - inverseViewMatrix = constant.inverseTransposeViewMatrix; + inverseViewMatrix = constant.inverseViewMatrix; #endif } @@ -72,10 +72,10 @@ shadowmapSamplerSpot = sampler.shadowmapSpot; #endif #ifdef SPOT - lightSpotDir = constant.light.spotDir; - lightSpotFactors = constant.light.spotFactors; - lightPosition = constant.light.position; - lightDiffuse = constant.light.diffuse; + lightSpotDir = constant.lightSpotDir; + lightSpotFactors = constant.lightSpotFactors; + lightPosition = constant.lightPosition; + lightDiffuse = constant.lightDiffuse; #endif } diff --git a/raw/iw4/techniques/trivial_vertcol_simple2d.tech b/raw/iw4/techniques/trivial_vertcol_simple2d.tech index d10e9a3c9..92e89f8d0 100644 --- a/raw/iw4/techniques/trivial_vertcol_simple2d.tech +++ b/raw/iw4/techniques/trivial_vertcol_simple2d.tech @@ -3,8 +3,6 @@ vertexShader 3.0 "trivial_vertcol_simple.hlsl" { - worldMatrix = constant.transposeWorldMatrix; - viewProjectionMatrix = constant.transposeViewProjectionMatrix; } pixelShader 3.0 "trivial_vertcol_simple.hlsl" diff --git a/raw/iw5/shader/include/IW5.hlsl b/raw/iw5/shader/include/IW5.hlsl new file mode 100644 index 000000000..376346540 --- /dev/null +++ b/raw/iw5/shader/include/IW5.hlsl @@ -0,0 +1,167 @@ +// ============================= +// IW5 code constants +// ============================= + +extern float4 lightPosition; +extern float4 lightDiffuse; +extern float4 lightSpecular; +extern float4 lightSpotDir; +extern float4 lightSpotFactors; +extern float4 lightFalloffPlacement; +extern float4 particleCloudColor; +extern float4 gameTime; +extern float4 eyeOffset; +extern float4 colorSaturationR; +extern float4 colorSaturationG; +extern float4 colorSaturationB; +extern float4 ssaoParms; +extern float4 pixelCostFracs; +extern float4 pixelCostDecode; +extern float4 filterTap[8]; +extern float4 colorMatrixR; +extern float4 colorMatrixG; +extern float4 colorMatrixB; +extern float4 shadowmapPolygonOffset; +extern float4 renderTargetSize; +extern float4 renderSourceSize; +extern float4 dofEquationViewModelAndFarBlur; +extern float4 dofEquationScene; +extern float4 dofLerpScale; +extern float4 dofLerpBias; +extern float4 dofRowDelta; +extern float4 motionMatrixX; +extern float4 motionMatrixY; +extern float4 motionMatrixW; +extern float4 shadowmapSwitchPartition; +extern float4 shadowmapScale; +extern float4 zNear; +extern float4 lightingLookupScale; +extern float4 debugBumpmap; +extern float4 materialColor; +extern float4 fogConsts; +extern float4 fogColorLinear; +extern float4 fogColorGamma; +extern float4 fogSunConsts; +extern float4 fogSunColorLinear; +extern float4 fogSunColorGamma; +extern float4 fogSunDir; +extern float4 glowSetup; +extern float4 glowApply; +extern float4 colorBias; +extern float4 colorTintBase; +extern float4 colorTintDelta; +extern float4 colorTintQuadraticDelta; +extern float4 outdoorFeatherParms; +extern float4 envMapParms; +extern float4 sunShadowmapPixelAdjust; +extern float4 spotShadowmapPixelAdjust; +extern float4 fullscreenDistortion; +extern float4 fadeEffect; +extern float4 viewportDimensions; +extern float4 framebufferRead; +extern float4 thermalColorOffset; +extern float4 playlistPopulationParams; +extern float4 baseLightingCoords; +extern float4 lightprobeAmbient; +extern float4 nearPlaneOrg; +extern float4 nearPlaneDx; +extern float4 nearPlaneDy; +extern float4 clipSpaceLookupScale; +extern float4 clipSpaceLookupOffset; +extern float4 particleCloudMatrix; +extern float4 particleCloudMatrix1; +extern float4 particleCloudMatrix2; +extern float4 particleCloudSparkColor0; +extern float4 particleCloudSparkColor1; +extern float4 particleCloudSparkColor2; +extern float4 particleFountainParms0; +extern float4 particleFountainParms1; +extern float4 depthFromClip; +extern float4 codeMeshArg[2]; +extern float4x4 viewMatrix; +extern float4x4 inverseViewMatrix; +extern float4x4 transposeViewMatrix; +extern float4x4 inverseTransposeViewMatrix; +extern float4x4 projectionMatrix; +extern float4x4 inverseProjectionMatrix; +extern float4x4 transposeProjectionMatrix; +extern float4x4 inverseTransposeProjectionMatrix; +extern float4x4 viewProjectionMatrix; +extern float4x4 inverseViewProjectionMatrix; +extern float4x4 transposeViewProjectionMatrix; +extern float4x4 inverseTransposeViewProjectionMatrix; +extern float4x4 shadowLookupMatrix; +extern float4x4 inverseShadowLookupMatrix; +extern float4x4 transposeShadowLookupMatrix; +extern float4x4 inverseTransposeShadowLookupMatrix; +extern float4x4 worldOutdoorLookupMatrix; +extern float4x4 inverseWorldOutdoorLookupMatrix; +extern float4x4 transposeWorldOutdoorLookupMatrix; +extern float4x4 inverseTransposeWorldOutdoorLookupMatrix; +extern float4x4 worldMatrix; +extern float4x4 inverseWorldMatrix; +extern float4x4 transposeWorldMatrix; +extern float4x4 inverseTransposeWorldMatrix; +extern float4x4 worldViewMatrix; +extern float4x4 inverseWorldViewMatrix; +extern float4x4 transposeWorldViewMatrix; +extern float4x4 inverseTransposeWorldViewMatrix; +extern float4x4 worldViewProjectionMatrix; +extern float4x4 inverseWorldViewProjectionMatrix; +extern float4x4 transposeWorldViewProjectionMatrix; +extern float4x4 inverseTransposeWorldViewProjectionMatrix; +extern float4x4 worldMatrix1; +extern float4x4 inverseWorldMatrix1; +extern float4x4 transposeWorldMatrix1; +extern float4x4 inverseTransposeWorldMatrix1; +extern float4x4 worldViewMatrix1; +extern float4x4 inverseWorldViewMatrix1; +extern float4x4 transposeWorldViewMatrix1; +extern float4x4 inverseTransposeWorldViewMatrix1; +extern float4x4 worldViewProjectionMatrix1; +extern float4x4 inverseWorldViewProjectionMatrix1; +extern float4x4 transposeWorldViewProjectionMatrix1; +extern float4x4 inverseTransposeWorldViewProjectionMatrix1; +extern float4x4 worldMatrix2; +extern float4x4 inverseWorldMatrix2; +extern float4x4 transposeWorldMatrix2; +extern float4x4 inverseTransposeWorldMatrix2; +extern float4x4 worldViewMatrix2; +extern float4x4 inverseWorldViewMatrix2; +extern float4x4 transposeWorldViewMatrix2; +extern float4x4 inverseTransposeWorldViewMatrix2; +extern float4x4 worldViewProjectionMatrix2; +extern float4x4 inverseWorldViewProjectionMatrix2; +extern float4x4 transposeWorldViewProjectionMatrix2; +extern float4x4 inverseTransposeWorldViewProjectionMatrix2; + +extern sampler2D black; +extern sampler2D white; +extern sampler2D identityNormalMap; +extern sampler2D modelLightingSampler; +extern sampler2D lightmapSamplerPrimary; +extern sampler2D lightmapSamplerSecondary; +extern sampler2D shadowmapSamplerSun; +extern sampler2D shadowmapSamplerSpot; +extern sampler2D feedbackSampler; +extern sampler2D resolvedPostSun; +extern sampler2D resolvedScene; +extern sampler2D postEffect0; +extern sampler2D postEffect1; +extern sampler2D attenuationSampler; +extern sampler2D cucolorisSampler; +extern sampler2D outdoor; +extern sampler2D floatZSampler; +extern sampler2D processedFloatZSampler; +extern sampler2D rawFloatZSampler; +extern sampler2D halfParticleColorSampler; +extern sampler2D halfParticleDepthSampler; +extern sampler2D caseTexture; +extern sampler2D cinematicYSampler; +extern sampler2D cinematicCrSampler; +extern sampler2D cinematicCbSampler; +extern sampler2D cinematicASampler; +extern sampler2D reflectionProbeSampler; +extern sampler2D pipSceneSampler; +extern sampler2D colorManipulationSampler; +extern sampler2D ssaoSampler; diff --git a/raw/iw5/shader/trivial_vertcol_simple.hlsl b/raw/iw5/shader/trivial_vertcol_simple.hlsl new file mode 100644 index 000000000..a67cf1656 --- /dev/null +++ b/raw/iw5/shader/trivial_vertcol_simple.hlsl @@ -0,0 +1,33 @@ +#include "include/IW5.hlsl" + +struct VSInput +{ + float3 position : POSITION; + half4 color : COLOR0; + half2 texcoord : TEXCOORD0; +}; + +struct VSOutput +{ + float4 position : SV_POSITION; + half4 color : COLOR0; + half2 texcoord : TEXCOORD0; +}; + +VSOutput VSMain(VSInput vin) +{ + VSOutput vout = (VSOutput)0; + + vout.position = mul(mul(float4(vin.position, 1.0f), worldMatrix), viewProjectionMatrix); + vout.color = vin.color; + vout.texcoord = vin.texcoord; + + return vout; +} + +extern sampler2D colorMapSampler; + +half4 PSMain(VSOutput input) : SV_TARGET +{ + return half4(tex2D(colorMapSampler, input.texcoord)) * input.color; +} diff --git a/raw/t5/shader/include/T5.hlsl b/raw/t5/shader/include/T5.hlsl new file mode 100644 index 000000000..c958e168c --- /dev/null +++ b/raw/t5/shader/include/T5.hlsl @@ -0,0 +1,254 @@ +// ============================= +// T5 code constants +// ============================= + +extern float4 lightPosition; +extern float4 lightDiffuse; +extern float4 lightSpecular; +extern float4 lightSpotDir; +extern float4 lightSpotFactors; +extern float4 lightAttenuation; +extern float4 lightFallOffA; +extern float4 lightFallOffB; +extern float4 lightSpotMatrix0; +extern float4 lightSpotMatrix1; +extern float4 lightSpotMatrix2; +extern float4 lightSpotMatrix3; +extern float4 lightSpotAABB; +extern float4 lightConeControl1; +extern float4 lightConeControl2; +extern float4 lightSpotCookieSlideControl; +extern float4 nearPlaneOrg; +extern float4 nearPlaneDx; +extern float4 nearPlaneDy; +extern float4 shadowParms; +extern float4 shadowmapPolygonOffset; +extern float4 renderTargetSize; +extern float4 vposx_to_world; +extern float4 vposy_to_world; +extern float4 vpos1_to_world; +extern float4 lightFalloffPlacement; +extern float4 dofEquationViewModelAndFarBlur; +extern float4 dofEquationScene; +extern float4 dofLerpScale; +extern float4 dofLerpBias; +extern float4 dofRowDelta; +extern float4 particleCloudColor; +extern float4 gameTime; +extern float4 alphaFade; +extern float4 pixelCostFracs; +extern float4 pixelCostDecode; +extern float4 filterTap[8]; +extern float4 colorMatrixR; +extern float4 colorMatrixG; +extern float4 colorMatrixB; +extern float4 shadowmapSwitchPartition; +extern float4 shadowmapScale; +extern float4 zNear; +extern float4 sunPosition; +extern float4 sunDiffuse; +extern float4 sunSpecular; +extern float4 lightingLookupScale; +extern float4 debugBumpmap; +extern float4 materialColor; +extern float4 fogConsts; +extern float4 fogConsts2; +extern float4 fogColor; +extern float4 sunFog; +extern float4 sunFogDir; +extern float4 sunFogColor; +extern float4 glowSetup; +extern float4 glowApply; +extern float4 colorBias; +extern float4 colorTintBase; +extern float4 colorTintDelta; +extern float4 outdoorFeatherParms; +extern float4 skyTransition; +extern float4 envMapParms; +extern float4 spotShadowmapPixelAdjust; +extern float4 dlightSpotShadowmapPixelAdjust; +extern float4 clipSpaceLookupScale; +extern float4 clipSpaceLookupOffset; +extern float4 particleCloudMatrix; +extern float4 depthFromClip; +extern float4 codeMeshArg[2]; +extern float4 baseLightingCoords; +extern float4 windDirection; +extern float4 waterParms; +extern float4 grassParms; +extern float4 grassForce0; +extern float4 grassForce1; +extern float4 grassWindForce0; +extern float4 motionblurDirectionAndMagnitude; +extern float4 flameDistortion; +extern float4 bloomScale; +extern float4 overlayTexCoord; +extern float4 colorBias1; +extern float4 colorTintBase1; +extern float4 colorTintDelta1; +extern float4 fadeEffect; +extern float4 viewportDimensions; +extern float4 framebufferRead; +extern float4 resizeParams1; +extern float4 resizeParams2; +extern float4 resizeParams3; +extern float4 variantWindSpring[16]; +extern float4 destructibleParms; +extern float4 cloudWorldArea; +extern float4 waterScroll; +extern float4 crossFadeAlpha; +extern float4 __characterCharredAmount; +extern float4 treeCanopyParms; +extern float4 marksHitNormal; +extern float4 postFxControl0; +extern float4 postFxControl1; +extern float4 postFxControl2; +extern float4 postFxControl3; +extern float4 postFxControl4; +extern float4 postFxControl5; +extern float4 postFxControl6; +extern float4 postFxControl7; +extern float4 postFxControl8; +extern float4 postFxControl9; +extern float4 postFxControlA; +extern float4 postFxControlB; +extern float4 postFxControlC; +extern float4 postFxControlD; +extern float4 postFxControlE; +extern float4 postFxControlF; +extern float4 hdrControl0; +extern float4 hdrControl1; +extern float4 glightPosXs; +extern float4 glightPosYs; +extern float4 glightPosZs; +extern float4 glightFallOffs; +extern float4 glightReds; +extern float4 glightGreens; +extern float4 glightBlues; +extern float4 dlightPosition; +extern float4 dlightDiffuse; +extern float4 dlightSpecular; +extern float4 dlightAttenuation; +extern float4 dlightFallOff; +extern float4 dlightSpotMatrix0; +extern float4 dlightSpotMatrix1; +extern float4 dlightSpotMatrix2; +extern float4 dlightSpotMatrix3; +extern float4 dlightSpotDir; +extern float4 dlightSpotFactors; +extern float4 dlightShadowLookupMatrix0; +extern float4 dlightShadowLookupMatrix1; +extern float4 dlightShadowLookupMatrix2; +extern float4 dlightShadowLookupMatrix3; +extern float4 cloudLayerControl0; +extern float4 cloudLayerControl1; +extern float4 cloudLayerControl2; +extern float4 cloudLayerControl3; +extern float4 cloudLayerControl4; +extern float4 heroLightingR; +extern float4 heroLightingG; +extern float4 heroLightingB; +extern float4 lightHeroScale; +extern float4 cinematicBlurBox; +extern float4 cinematicBlurBox2; +extern float4 adsZScale; +extern float4 ui3dUVSetup0; +extern float4 ui3dUVSetup1; +extern float4 ui3dUVSetup2; +extern float4 ui3dUVSetup3; +extern float4 ui3dUVSetup4; +extern float4 ui3dUVSetup5; +extern float4 __characterDissolveColor; +extern float4 cameraLook; +extern float4 cameraUp; +extern float4 cameraSide; +extern float4 scriptVector0; +extern float4 scriptVector1; +extern float4 scriptVector2; +extern float4 scriptVector3; +extern float4 scriptVector4; +extern float4 scriptVector5; +extern float4 scriptVector6; +extern float4 scriptVector7; +extern float4 eyeOffset; +extern float4 u_customWindCenter; +extern float4 u_customWindSpring; +extern float4 skyColorMultiplier; +extern float4 extraCamParam; +extern float4 emblemLUTSelector; +extern float4x4 worldMatrix; +extern float4x4 inverseWorldMatrix; +extern float4x4 transposeWorldMatrix; +extern float4x4 inverseTransposeWorldMatrix; +extern float4x4 viewMatrix; +extern float4x4 inverseViewMatrix; +extern float4x4 transposeViewMatrix; +extern float4x4 inverseTransposeViewMatrix; +extern float4x4 projectionMatrix; +extern float4x4 inverseProjectionMatrix; +extern float4x4 transposeProjectionMatrix; +extern float4x4 inverseTransposeProjectionMatrix; +extern float4x4 worldViewMatrix; +extern float4x4 inverseWorldViewMatrix; +extern float4x4 transposeWorldViewMatrix; +extern float4x4 inverseTransposeWorldViewMatrix; +extern float4x4 viewProjectionMatrix; +extern float4x4 inverseViewProjectionMatrix; +extern float4x4 transposeViewProjectionMatrix; +extern float4x4 inverseTransposeViewProjectionMatrix; +extern float4x4 worldViewProjectionMatrix; +extern float4x4 inverseWorldViewProjectionMatrix; +extern float4x4 transposeWorldViewProjectionMatrix; +extern float4x4 inverseTransposeWorldViewProjectionMatrix; +extern float4x4 shadowLookupMatrix; +extern float4x4 inverseShadowLookupMatrix; +extern float4x4 transposeShadowLookupMatrix; +extern float4x4 inverseTransposeShadowLookupMatrix; +extern float4x4 worldOutdoorLookupMatrix; +extern float4x4 inverseWorldOutdoorLookupMatrix; +extern float4x4 transposeWorldOutdoorLookupMatrix; +extern float4x4 inverseTransposeWorldOutdoorLookupMatrix; + +extern sampler2D black; +extern sampler2D white; +extern sampler2D identityNormalMap; +extern sampler2D modelLightingSampler; +extern sampler2D lightmapSamplerPrimary; +extern sampler2D lightmapSamplerSecondary; +extern sampler2D shadowmapSamplerSun; +extern sampler2D shadowmapSamplerSpot; +extern sampler2D feedbackSampler; +extern sampler2D resolvedPostSun; +extern sampler2D resolvedScene; +extern sampler2D postEffectSrc; +extern sampler2D postEffectGodRays; +extern sampler2D postEffect0; +extern sampler2D postEffect1; +extern sampler2D sky; +extern sampler2D attenuationSampler; +extern sampler2D dlightAttenuationSampler; +extern sampler2D outdoor; +extern sampler2D floatZSampler; +extern sampler2D processedFloatZSampler; +extern sampler2D rawFloatZSampler; +extern sampler2D caseTextureSampler; +extern sampler2D cinematicYSampler; +extern sampler2D cinematicCrSampler; +extern sampler2D cinematicCbSampler; +extern sampler2D cinematicASampler; +extern sampler2D reflectionProbeSampler; +extern sampler2D featherFloatZSampler; +extern sampler2D terrainScorchTextureSampler0; +extern sampler2D terrainScorchTextureSampler1; +extern sampler2D terrainScorchTextureSampler2; +extern sampler2D terrainScorchTextureSampler3; +extern sampler2D lightmapSamplerSecondaryB; +extern sampler2D codeTexture0; +extern sampler2D codeTexture1; +extern sampler2D codeTexture2; +extern sampler2D codeTexture3; +extern sampler2D impactMaskSampler; +extern sampler2D ui3dSampler; +extern sampler2D missileCamSampler; +extern sampler2D compositeResult; +extern sampler2D heatmapSampler; From 73f6f5573dc40c07fd68812d0c917c992cb94104 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Wed, 8 Apr 2026 11:47:14 +0100 Subject: [PATCH 10/10] chore: make sure shader compiler uses std expected --- src/ObjCompiling/Shader/D3DShaderCompiler.cpp | 20 +++++++++---------- src/ObjCompiling/Shader/D3DShaderCompiler.h | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ObjCompiling/Shader/D3DShaderCompiler.cpp b/src/ObjCompiling/Shader/D3DShaderCompiler.cpp index e4302833a..657b3c299 100644 --- a/src/ObjCompiling/Shader/D3DShaderCompiler.cpp +++ b/src/ObjCompiling/Shader/D3DShaderCompiler.cpp @@ -122,18 +122,18 @@ namespace shader #endif } - result::Expected, std::string> CompileShader(const std::string& shaderFile, - const std::string& entryPoint, - const std::string& target, - const bool debug, - ISearchPath& searchPath, - MemoryManager& memory) + std::expected, std::string> CompileShader(const std::string& shaderFile, + const std::string& entryPoint, + const std::string& target, + const bool debug, + ISearchPath& searchPath, + MemoryManager& memory) { #ifdef _WIN32 if (!initialized) InitializeShaderCompilation(); if (!compilationAvailable) - return result::Unexpected("Shader compilation unavailable"); + return std::unexpected("Shader compilation unavailable"); const auto fileName = GetSourceFileNameForShaderAssetName(shaderFile); auto file = searchPath.Open(fileName); @@ -141,7 +141,7 @@ namespace shader return std::optional(std::nullopt); if (std::cmp_greater(file.m_length, MAX_SHADER_SIZE)) - return result::Unexpected(std::format("File too big: {}", file.m_length)); + return std::unexpected(std::format("File too big: {}", file.m_length)); const auto shaderSize = file.m_length; const auto shaderData = std::make_unique(static_cast(shaderSize)); @@ -185,7 +185,7 @@ namespace shader if (shaderBlob) shaderBlob->Release(); - return result::Unexpected(std::move(errorMessage)); + return std::unexpected(std::move(errorMessage)); } const auto shaderBlobSize = static_cast(shaderBlob->GetBufferSize()); @@ -199,7 +199,7 @@ namespace shader .m_shader_size = shaderBlobSize, }); #else - return result::Unexpected("Shader compilation unavailable"); + return std::unexpected("Shader compilation unavailable"); #endif } } // namespace shader diff --git a/src/ObjCompiling/Shader/D3DShaderCompiler.h b/src/ObjCompiling/Shader/D3DShaderCompiler.h index c281a80e7..e79e313ea 100644 --- a/src/ObjCompiling/Shader/D3DShaderCompiler.h +++ b/src/ObjCompiling/Shader/D3DShaderCompiler.h @@ -2,8 +2,8 @@ #include "SearchPath/ISearchPath.h" #include "Utils/MemoryManager.h" -#include "Utils/Result.h" +#include #include #include @@ -18,6 +18,6 @@ namespace shader bool ShaderCompilationAvailable(); - result::Expected, std::string> CompileShader( + std::expected, std::string> CompileShader( const std::string& shaderFile, const std::string& entryPoint, const std::string& target, bool debug, ISearchPath& searchPath, MemoryManager& memory); } // namespace shader