From 65c9267b06c375d85e2bece51a3691fac3210dc4 Mon Sep 17 00:00:00 2001 From: Jan Date: Fri, 15 Apr 2022 16:01:39 +0200 Subject: [PATCH] Correctly identify update frequencies for shader arguments --- src/Common/Game/IW4/IW4_Assets.h | 24 ++- src/ObjCommon/Game/IW4/TechsetConstantsIW4.h | 169 ++++++++++++++++++ .../AssetLoaders/AssetLoaderTechniqueSet.cpp | 99 +++++++--- 3 files changed, 264 insertions(+), 28 deletions(-) diff --git a/src/Common/Game/IW4/IW4_Assets.h b/src/Common/Game/IW4/IW4_Assets.h index da48d0d7..471d7efe 100644 --- a/src/Common/Game/IW4/IW4_Assets.h +++ b/src/Common/Game/IW4/IW4_Assets.h @@ -1148,24 +1148,32 @@ namespace IW4 enum MaterialShaderArgumentType { - MTL_ARG_MATERIAL_VERTEX_CONST = 0x0, - MTL_ARG_LITERAL_VERTEX_CONST = 0x1, - MTL_ARG_MATERIAL_PIXEL_SAMPLER = 0x2, + MTL_ARG_MATERIAL_VERTEX_CONST = 0x0, // stable + MTL_ARG_LITERAL_VERTEX_CONST = 0x1, // stable + MTL_ARG_MATERIAL_PIXEL_SAMPLER = 0x2, // stable MTL_ARG_CODE_PRIM_BEGIN = 0x3, - MTL_ARG_CODE_VERTEX_CONST = 0x3, - MTL_ARG_CODE_PIXEL_SAMPLER = 0x4, - MTL_ARG_CODE_PIXEL_CONST = 0x5, + MTL_ARG_CODE_VERTEX_CONST = 0x3, // stable object prim + MTL_ARG_CODE_PIXEL_SAMPLER = 0x4, // stable object + MTL_ARG_CODE_PIXEL_CONST = 0x5, // stable MTL_ARG_CODE_PRIM_END = 0x6, - MTL_ARG_MATERIAL_PIXEL_CONST = 0x6, - MTL_ARG_LITERAL_PIXEL_CONST = 0x7, + MTL_ARG_MATERIAL_PIXEL_CONST = 0x6, // stable + MTL_ARG_LITERAL_PIXEL_CONST = 0x7, // stable MTL_ARG_COUNT }; + enum MaterialUpdateFrequency + { + MTL_UPDATE_PER_PRIM = 0x0, + MTL_UPDATE_PER_OBJECT = 0x1, + MTL_UPDATE_RARELY = 0x2, + MTL_UPDATE_CUSTOM = 0x3, + }; + struct MaterialShaderArgument { uint16_t type; diff --git a/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h b/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h index d341e2a6..ce281988 100644 --- a/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h +++ b/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h @@ -338,6 +338,175 @@ namespace IW4 {} }; + inline MaterialUpdateFrequency s_codeConstUpdateFreq[] + { + MTL_UPDATE_RARELY, // LIGHT_POSITION + MTL_UPDATE_RARELY, // LIGHT_DIFFUSE + MTL_UPDATE_RARELY, // LIGHT_SPECULAR + MTL_UPDATE_RARELY, // LIGHT_SPOTDIR + MTL_UPDATE_RARELY, // LIGHT_SPOTFACTORS + MTL_UPDATE_RARELY, // LIGHT_FALLOFF_PLACEMENT + MTL_UPDATE_RARELY, // PARTICLE_CLOUD_COLOR + MTL_UPDATE_RARELY, // GAMETIME + MTL_UPDATE_RARELY, // PIXEL_COST_FRACS + MTL_UPDATE_RARELY, // PIXEL_COST_DECODE + MTL_UPDATE_RARELY, // FILTER_TAP_0 + MTL_UPDATE_RARELY, // FILTER_TAP_1 + MTL_UPDATE_RARELY, // FILTER_TAP_2 + MTL_UPDATE_RARELY, // FILTER_TAP_3 + MTL_UPDATE_RARELY, // FILTER_TAP_4 + MTL_UPDATE_RARELY, // FILTER_TAP_5 + MTL_UPDATE_RARELY, // FILTER_TAP_6 + MTL_UPDATE_RARELY, // FILTER_TAP_7 + MTL_UPDATE_RARELY, // COLOR_MATRIX_R + MTL_UPDATE_RARELY, // COLOR_MATRIX_G + MTL_UPDATE_RARELY, // COLOR_MATRIX_B + MTL_UPDATE_RARELY, // SHADOWMAP_POLYGON_OFFSET + MTL_UPDATE_RARELY, // RENDER_TARGET_SIZE + MTL_UPDATE_RARELY, // DOF_EQUATION_VIEWMODEL_AND_FAR_BLUR + MTL_UPDATE_RARELY, // DOF_EQUATION_SCENE + MTL_UPDATE_RARELY, // DOF_LERP_SCALE + MTL_UPDATE_RARELY, // DOF_LERP_BIAS + MTL_UPDATE_RARELY, // DOF_ROW_DELTA + MTL_UPDATE_RARELY, // MOTION_MATRIX_X + MTL_UPDATE_RARELY, // MOTION_MATRIX_Y + MTL_UPDATE_RARELY, // MOTION_MATRIX_W + MTL_UPDATE_RARELY, // SHADOWMAP_SWITCH_PARTITION + MTL_UPDATE_RARELY, // SHADOWMAP_SCALE + MTL_UPDATE_RARELY, // ZNEAR + MTL_UPDATE_RARELY, // LIGHTING_LOOKUP_SCALE + MTL_UPDATE_RARELY, // DEBUG_BUMPMAP + MTL_UPDATE_RARELY, // MATERIAL_COLOR + MTL_UPDATE_RARELY, // FOG + MTL_UPDATE_RARELY, // FOG_COLOR_LINEAR + MTL_UPDATE_RARELY, // FOG_COLOR_GAMMA + MTL_UPDATE_RARELY, // FOG_SUN_CONSTS + MTL_UPDATE_RARELY, // FOG_SUN_COLOR_LINEAR + MTL_UPDATE_RARELY, // FOG_SUN_COLOR_GAMMA + MTL_UPDATE_RARELY, // FOG_SUN_DIR + MTL_UPDATE_RARELY, // GLOW_SETUP + MTL_UPDATE_RARELY, // GLOW_APPLY + MTL_UPDATE_RARELY, // COLOR_BIAS + MTL_UPDATE_RARELY, // COLOR_TINT_BASE + MTL_UPDATE_RARELY, // COLOR_TINT_DELTA + MTL_UPDATE_RARELY, // COLOR_TINT_QUADRATIC_DELTA + MTL_UPDATE_RARELY, // OUTDOOR_FEATHER_PARMS + MTL_UPDATE_RARELY, // ENVMAP_PARMS + MTL_UPDATE_RARELY, // SUN_SHADOWMAP_PIXEL_ADJUST + MTL_UPDATE_RARELY, // SPOT_SHADOWMAP_PIXEL_ADJUST + MTL_UPDATE_RARELY, // COMPOSITE_FX_DISTORTION + MTL_UPDATE_RARELY, // POSTFX_FADE_EFFECT + MTL_UPDATE_RARELY, // VIEWPORT_DIMENSIONS + MTL_UPDATE_RARELY, // FRAMEBUFFER_READ + MTL_UPDATE_PER_PRIM, // BASE_LIGHTING_COORDS + MTL_UPDATE_PER_PRIM, // LIGHT_PROBE_AMBIENT + MTL_UPDATE_RARELY, // NEARPLANE_ORG + MTL_UPDATE_RARELY, // NEARPLANE_DX + MTL_UPDATE_RARELY, // NEARPLANE_DY + MTL_UPDATE_RARELY, // CLIP_SPACE_LOOKUP_SCALE + MTL_UPDATE_RARELY, // CLIP_SPACE_LOOKUP_OFFSET + MTL_UPDATE_PER_OBJECT, // PARTICLE_CLOUD_MATRIX0 + MTL_UPDATE_PER_OBJECT, // PARTICLE_CLOUD_MATRIX1 + MTL_UPDATE_PER_OBJECT, // PARTICLE_CLOUD_MATRIX2 + MTL_UPDATE_PER_OBJECT, // PARTICLE_CLOUD_SPARK_COLOR0 + MTL_UPDATE_PER_OBJECT, // PARTICLE_CLOUD_SPARK_COLOR1 + MTL_UPDATE_PER_OBJECT, // PARTICLE_CLOUD_SPARK_COLOR2 + MTL_UPDATE_PER_OBJECT, // PARTICLE_FOUNTAIN_PARM0 + MTL_UPDATE_PER_OBJECT, // PARTICLE_FOUNTAIN_PARM1 + MTL_UPDATE_PER_OBJECT, // DEPTH_FROM_CLIP + MTL_UPDATE_PER_OBJECT, // CODE_MESH_ARG_0 + MTL_UPDATE_PER_OBJECT, // CODE_MESH_ARG_1 + MTL_UPDATE_PER_OBJECT, // VIEW_MATRIX + MTL_UPDATE_PER_OBJECT, // INVERSE_VIEW_MATRIX + MTL_UPDATE_PER_OBJECT, // TRANSPOSE_VIEW_MATRIX + MTL_UPDATE_PER_OBJECT, // INVERSE_TRANSPOSE_VIEW_MATRIX + MTL_UPDATE_PER_OBJECT, // PROJECTION_MATRIX + MTL_UPDATE_PER_OBJECT, // INVERSE_PROJECTION_MATRIX + MTL_UPDATE_PER_OBJECT, // TRANSPOSE_PROJECTION_MATRIX + MTL_UPDATE_PER_OBJECT, // INVERSE_TRANSPOSE_PROJECTION_MATRIX + MTL_UPDATE_PER_OBJECT, // VIEW_PROJECTION_MATRIX + MTL_UPDATE_PER_OBJECT, // INVERSE_VIEW_PROJECTION_MATRIX + MTL_UPDATE_PER_OBJECT, // TRANSPOSE_VIEW_PROJECTION_MATRIX + MTL_UPDATE_PER_OBJECT, // INVERSE_TRANSPOSE_VIEW_PROJECTION_MATRIX + MTL_UPDATE_PER_OBJECT, // SHADOW_LOOKUP_MATRIX + MTL_UPDATE_PER_OBJECT, // INVERSE_SHADOW_LOOKUP_MATRIX + MTL_UPDATE_PER_OBJECT, // TRANSPOSE_SHADOW_LOOKUP_MATRIX + MTL_UPDATE_PER_OBJECT, // INVERSE_TRANSPOSE_SHADOW_LOOKUP_MATRIX + MTL_UPDATE_PER_PRIM, // WORLD_OUTDOOR_LOOKUP_MATRIX + MTL_UPDATE_PER_PRIM, // INVERSE_WORLD_OUTDOOR_LOOKUP_MATRIX + MTL_UPDATE_PER_PRIM, // TRANSPOSE_WORLD_OUTDOOR_LOOKUP_MATRIX + MTL_UPDATE_PER_PRIM, // INVERSE_TRANSPOSE_WORLD_OUTDOOR_LOOKUP_MATRIX + MTL_UPDATE_PER_PRIM, // WORLD_MATRIX0 + MTL_UPDATE_PER_PRIM, // INVERSE_WORLD_MATRIX0 + MTL_UPDATE_PER_PRIM, // TRANSPOSE_WORLD_MATRIX0 + MTL_UPDATE_PER_PRIM, // INVERSE_TRANSPOSE_WORLD_MATRIX0 + MTL_UPDATE_PER_PRIM, // WORLD_VIEW_MATRIX0 + MTL_UPDATE_PER_PRIM, // INVERSE_WORLD_VIEW_MATRIX0 + MTL_UPDATE_PER_PRIM, // TRANSPOSE_WORLD_VIEW_MATRIX0 + MTL_UPDATE_PER_PRIM, // INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX0 + MTL_UPDATE_PER_PRIM, // WORLD_VIEW_PROJECTION_MATRIX0 + MTL_UPDATE_PER_PRIM, // INVERSE_WORLD_VIEW_PROJECTION_MATRIX0 + MTL_UPDATE_PER_PRIM, // TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX0 + MTL_UPDATE_PER_PRIM, // INVERSE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX0 + MTL_UPDATE_PER_PRIM, // WORLD_MATRIX1 + MTL_UPDATE_PER_PRIM, // INVERSE_WORLD_MATRIX1 + MTL_UPDATE_PER_PRIM, // TRANSPOSE_WORLD_MATRIX1 + MTL_UPDATE_PER_PRIM, // INVERSE_TRANSPOSE_WORLD_MATRIX1 + MTL_UPDATE_PER_PRIM, // WORLD_VIEW_MATRIX1 + MTL_UPDATE_PER_PRIM, // INVERSE_WORLD_VIEW_MATRIX1 + MTL_UPDATE_PER_PRIM, // TRANSPOSE_WORLD_VIEW_MATRIX1 + MTL_UPDATE_PER_PRIM, // INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX1 + MTL_UPDATE_PER_PRIM, // WORLD_VIEW_PROJECTION_MATRIX1 + MTL_UPDATE_PER_PRIM, // INVERSE_WORLD_VIEW_PROJECTION_MATRIX1 + MTL_UPDATE_PER_PRIM, // TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX1 + MTL_UPDATE_PER_PRIM, // INVERSE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX1 + MTL_UPDATE_PER_PRIM, // WORLD_MATRIX2 + MTL_UPDATE_PER_PRIM, // INVERSE_WORLD_MATRIX2 + MTL_UPDATE_PER_PRIM, // TRANSPOSE_WORLD_MATRIX2 + MTL_UPDATE_PER_PRIM, // INVERSE_TRANSPOSE_WORLD_MATRIX2 + MTL_UPDATE_PER_PRIM, // WORLD_VIEW_MATRIX2 + MTL_UPDATE_PER_PRIM, // INVERSE_WORLD_VIEW_MATRIX2 + MTL_UPDATE_PER_PRIM, // TRANSPOSE_WORLD_VIEW_MATRIX2 + MTL_UPDATE_PER_PRIM, // INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX2 + MTL_UPDATE_PER_PRIM, // WORLD_VIEW_PROJECTION_MATRIX2 + MTL_UPDATE_PER_PRIM, // INVERSE_WORLD_VIEW_PROJECTION_MATRIX2 + MTL_UPDATE_PER_PRIM, // TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX2 + MTL_UPDATE_PER_PRIM, // INVERSE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX2 + }; + static_assert(std::extent_v == CONST_SRC_TOTAL_COUNT); + + inline MaterialUpdateFrequency s_codeSamplerUpdateFreq[] + { + MTL_UPDATE_RARELY, // BLACK + MTL_UPDATE_RARELY, // WHITE + MTL_UPDATE_RARELY, // IDENTITY_NORMAL_MAP + MTL_UPDATE_RARELY, // MODEL_LIGHTING + MTL_UPDATE_CUSTOM, // LIGHTMAP_PRIMARY + MTL_UPDATE_CUSTOM, // LIGHTMAP_SECONDARY + MTL_UPDATE_RARELY, // SHADOWMAP_SUN + MTL_UPDATE_RARELY, // SHADOWMAP_SPOT + MTL_UPDATE_PER_OBJECT, // FEEDBACK + MTL_UPDATE_RARELY, // RESOLVED_POST_SUN + MTL_UPDATE_RARELY, // RESOLVED_SCENE + MTL_UPDATE_RARELY, // POST_EFFECT_0 + MTL_UPDATE_RARELY, // POST_EFFECT_1 + MTL_UPDATE_PER_OBJECT, // LIGHT_ATTENUATION + MTL_UPDATE_RARELY, // OUTDOOR + MTL_UPDATE_RARELY, // FLOATZ + MTL_UPDATE_RARELY, // PROCESSED_FLOATZ + MTL_UPDATE_RARELY, // RAW_FLOATZ + MTL_UPDATE_RARELY, // HALF_PARTICLES + MTL_UPDATE_RARELY, // HALF_PARTICLES_Z + MTL_UPDATE_PER_OBJECT, // CASE_TEXTURE + MTL_UPDATE_PER_OBJECT, // CINEMATIC_Y + MTL_UPDATE_PER_OBJECT, // CINEMATIC_CR + MTL_UPDATE_PER_OBJECT, // CINEMATIC_CB + MTL_UPDATE_PER_OBJECT, // CINEMATIC_A + MTL_UPDATE_CUSTOM, // REFLECTION_PROBE + MTL_UPDATE_RARELY, // ALTERNATE_SCENE + }; + static_assert(std::extent_v == TEXTURE_SRC_CODE_COUNT); + static constexpr std::pair KnownMaterialSource(const char* name) { return std::make_pair(Common::R_HashString(name, 0u), name); diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp index 78a384c5..b4319f90 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp @@ -123,6 +123,50 @@ namespace IW4 ShaderInfoFromFileSystemCacheState* const m_shader_info_cache; public: + class PassShaderArgument + { + public: + MaterialShaderArgument m_arg; + MaterialUpdateFrequency m_update_frequency; + + static MaterialUpdateFrequency GetUpdateFrequencyForArg(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; + } + } + + explicit PassShaderArgument(const MaterialShaderArgument arg) + : m_arg(arg), + m_update_frequency(GetUpdateFrequencyForArg(arg)) + { + } + }; + struct Pass { XAssetInfo* m_vertex_shader; @@ -139,11 +183,13 @@ namespace IW4 MaterialVertexDeclaration m_vertex_decl; XAssetInfo* m_vertex_decl_asset; - std::vector m_arguments; + std::vector m_arguments; 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) { @@ -230,7 +276,7 @@ namespace IW4 if (elementOffset >= std::max(arrayCount, 1u)) return false; - pass.m_arguments.push_back(argument); + pass.m_arguments.emplace_back(argument); return true; } @@ -332,9 +378,18 @@ namespace IW4 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::sort(pass.m_arguments.begin(), pass.m_arguments.end(), [](const PassShaderArgument& arg1, const PassShaderArgument& arg2) + { + return arg1.m_update_frequency < arg2.m_update_frequency; + }); + AllocateVertexDecl(); return true; @@ -646,7 +701,7 @@ namespace IW4 if (!SetArgumentCodeConst(argument, source, shaderConstant, constantSource->source, constantSource->arrayCount, errorMessage)) return false; - pass.m_arguments.push_back(argument); + pass.m_arguments.emplace_back(argument); pass.m_handled_vertex_shader_arguments[pass.m_vertex_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; return true; @@ -725,7 +780,7 @@ namespace IW4 } - pass.m_arguments.push_back(argument); + pass.m_arguments.emplace_back(argument); pass.m_handled_pixel_shader_arguments[pass.m_pixel_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; return true; @@ -800,7 +855,7 @@ namespace IW4 argument.dest = static_cast(shaderConstant.m_register_index + registerOffset); argument.u.literalConst = m_zone_state->GetAllocatedLiteral(m_memory, source); - pass.m_arguments.push_back(argument); + pass.m_arguments.emplace_back(argument); if (shader == techset::ShaderSelector::VERTEX_SHADER) pass.m_handled_vertex_shader_arguments[pass.m_vertex_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; @@ -864,7 +919,7 @@ namespace IW4 argument.u.nameHash = Common::R_HashString(source.m_name.c_str(), 0u); argument.dest = static_cast(shaderConstant.m_register_index + registerOffset); - pass.m_arguments.push_back(argument); + pass.m_arguments.emplace_back(argument); if (shader == techset::ShaderSelector::VERTEX_SHADER) pass.m_handled_vertex_shader_arguments[pass.m_vertex_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; @@ -935,35 +990,39 @@ namespace IW4 out.pixelShader = in.m_pixel_shader->Asset(); out.vertexDecl = in.m_vertex_decl_asset->Asset(); + const auto argDataSize = sizeof(MaterialShaderArgument) * in.m_arguments.size(); + out.args = static_cast(m_memory->Alloc(argDataSize)); + size_t perObjArgCount = 0u; size_t perPrimArgCount = 0u; size_t stableArgCount = 0u; + size_t argIndex = 0u; for (const auto& arg : in.m_arguments) { - if (arg.type == MTL_ARG_MATERIAL_VERTEX_CONST - || arg.type == MTL_ARG_MATERIAL_PIXEL_CONST - || arg.type == MTL_ARG_MATERIAL_PIXEL_SAMPLER) - { - perObjArgCount++; - } - else if (arg.type >= MTL_ARG_CODE_PRIM_BEGIN && arg.type < MTL_ARG_CODE_PRIM_END) + switch (arg.m_update_frequency) { + case MTL_UPDATE_PER_PRIM: perPrimArgCount++; - } - else - { + break; + case MTL_UPDATE_PER_OBJECT: + perObjArgCount++; + break; + case MTL_UPDATE_RARELY: stableArgCount++; + break; + case MTL_UPDATE_CUSTOM: + default: + assert(false); + break; } + + out.args[argIndex++] = arg.m_arg; } out.perObjArgCount = static_cast(perObjArgCount); out.perPrimArgCount = static_cast(perPrimArgCount); out.stableArgCount = static_cast(stableArgCount); - const auto dataSize = sizeof(MaterialShaderArgument) * in.m_arguments.size(); - out.args = static_cast(m_memory->Alloc(dataSize)); - memcpy(out.args, in.m_arguments.data(), dataSize); - if (in.m_vertex_shader) dependencies.push_back(in.m_vertex_shader); if (in.m_pixel_shader)