mirror of
				https://github.com/hedge-dev/XenosRecomp.git
				synced 2025-10-30 07:12:17 +00:00 
			
		
		
		
	Compare commits
	
		
			22 commits
		
	
	
		
			7be2b82bb3
			...
			5a81a69f9c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 5a81a69f9c | ||
|   | 6c7c8fa87d | ||
|   | 790c8be91b | ||
|   | 2d9e24c52f | ||
|   | 9112665766 | ||
|   | 995d2889d4 | ||
|   | f87e28fbcc | ||
|   | 347fee997c | ||
|   | 4c93ec4e43 | ||
|   | 67467f459a | ||
|   | 4149b8458a | ||
|   | 6c88f0b31e | ||
|   | c3b320e314 | ||
|   | 58e4631dce | ||
|   | 6153094d1f | ||
|   | f328cbbec8 | ||
|   | 8a0c898a7d | ||
|   | a223077258 | ||
|   | 2efa88dbd4 | ||
|   | 342a7224ee | ||
|   | ae64bcf8ea | ||
|   | 0de70f7458 | 
					 3 changed files with 415 additions and 33 deletions
				
			
		|  | @ -4,6 +4,10 @@ if (WIN32) | |||
|     option(XENOS_RECOMP_DXIL "Generate DXIL shader cache" ON) | ||||
| endif() | ||||
| 
 | ||||
| if (APPLE) | ||||
|     option(XENOS_RECOMP_AIR "Generate Metal AIR shader cache" ON) | ||||
| endif() | ||||
| 
 | ||||
| set(SMOLV_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/smol-v/source") | ||||
| 
 | ||||
| add_executable(XenosRecomp  | ||||
|  | @ -51,3 +55,7 @@ if (XENOS_RECOMP_DXIL) | |||
|     target_compile_definitions(XenosRecomp PRIVATE XENOS_RECOMP_DXIL) | ||||
|     target_link_libraries(XenosRecomp PRIVATE Microsoft::DXIL) | ||||
| endif() | ||||
| 
 | ||||
| if (XENOS_RECOMP_AIR) | ||||
|     target_compile_definitions(XenosRecomp PRIVATE XENOS_RECOMP_AIR) | ||||
| endif() | ||||
|  |  | |||
|  | @ -10,10 +10,12 @@ | |||
|     #define SPEC_CONSTANT_REVERSE_Z         (1 << 4) | ||||
| #endif | ||||
| 
 | ||||
| #if !defined(__cplusplus) || defined(__INTELLISENSE__) | ||||
| #if defined(__air__) || !defined(__cplusplus) || defined(__INTELLISENSE__) | ||||
| 
 | ||||
| #ifndef __air__ | ||||
| #define FLT_MIN asfloat(0xff7fffff) | ||||
| #define FLT_MAX asfloat(0x7f7fffff) | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __spirv__ | ||||
| 
 | ||||
|  | @ -34,6 +36,29 @@ struct PushConstants | |||
| 
 | ||||
| #define g_SpecConstants() g_SpecConstants | ||||
| 
 | ||||
| #elif __air__ | ||||
| 
 | ||||
| #include <metal_stdlib> | ||||
| 
 | ||||
| using namespace metal; | ||||
| 
 | ||||
| constant uint G_SPEC_CONSTANT [[function_constant(0)]]; | ||||
| 
 | ||||
| uint g_SpecConstants() { | ||||
|     return G_SPEC_CONSTANT; | ||||
| } | ||||
| 
 | ||||
| struct PushConstants | ||||
| { | ||||
|     ulong VertexShaderConstants; | ||||
|     ulong PixelShaderConstants; | ||||
|     ulong SharedConstants; | ||||
| }; | ||||
| 
 | ||||
| #define g_Booleans (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 256))) | ||||
| #define g_SwappedTexcoords (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 260))) | ||||
| #define g_AlphaThreshold (*(reinterpret_cast<device float*>(g_PushConstants.SharedConstants + 264))) | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| #define DEFINE_SHARED_CONSTANTS() \ | ||||
|  | @ -45,6 +70,56 @@ uint g_SpecConstants(); | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __air__ | ||||
| 
 | ||||
| struct Texture2DDescriptorHeap | ||||
| { | ||||
|     array<texture2d<float>, 1> g [[id(0)]]; | ||||
| }; | ||||
| 
 | ||||
| struct Texture3DDescriptorHeap | ||||
| { | ||||
|     array<texture3d<float>, 1> g [[id(0)]]; | ||||
| }; | ||||
| 
 | ||||
| struct TextureCubeDescriptorHeap | ||||
| { | ||||
|     array<texturecube<float>, 1> g [[id(0)]]; | ||||
| }; | ||||
| 
 | ||||
| struct SamplerDescriptorHeap | ||||
| { | ||||
|     array<sampler, 1> g [[id(0)]]; | ||||
| }; | ||||
| 
 | ||||
| uint2 getTexture2DDimensions(texture2d<float> texture) | ||||
| { | ||||
|     return uint2(texture.get_width(), texture.get_height()); | ||||
| } | ||||
| 
 | ||||
| float4 tfetch2D(constant Texture2DDescriptorHeap& textureHeap, | ||||
|                 constant SamplerDescriptorHeap& samplerHeap, | ||||
|                 uint resourceDescriptorIndex, | ||||
|                 uint samplerDescriptorIndex, | ||||
|                 float2 texCoord, float2 offset) | ||||
| { | ||||
|     texture2d<float> texture = textureHeap.g[resourceDescriptorIndex]; | ||||
|     sampler sampler = samplerHeap.g[samplerDescriptorIndex]; | ||||
|     return texture.sample(sampler, texCoord + offset / (float2)getTexture2DDimensions(texture)); | ||||
| } | ||||
| 
 | ||||
| float2 getWeights2D(constant Texture2DDescriptorHeap& textureHeap, | ||||
|                     constant SamplerDescriptorHeap& samplerHeap, | ||||
|                     uint resourceDescriptorIndex, | ||||
|                     uint samplerDescriptorIndex, | ||||
|                     float2 texCoord, float2 offset) | ||||
| { | ||||
|     texture2d<float> texture = textureHeap.g[resourceDescriptorIndex]; | ||||
|     return select(fract(texCoord * (float2)getTexture2DDimensions(texture) + offset - 0.5), 0.0, isnan(texCoord)); | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| Texture2D<float4> g_Texture2DDescriptorHeap[] : register(t0, space0); | ||||
| Texture3D<float4> g_Texture3DDescriptorHeap[] : register(t0, space1); | ||||
| TextureCube<float4> g_TextureCubeDescriptorHeap[] : register(t0, space2); | ||||
|  | @ -69,6 +144,46 @@ float2 getWeights2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, f | |||
|     return select(isnan(texCoord), 0.0, frac(texCoord * getTexture2DDimensions(texture) + offset - 0.5)); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __air__ | ||||
| #define selectWrapper(a, b, c) select(c, b, a) | ||||
| #else | ||||
| #define selectWrapper(a, b, c) select(a, b, c) | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __air__ | ||||
| #define frac(X) fract(X) | ||||
| 
 | ||||
| template<typename T> | ||||
| void clip(T a) | ||||
| { | ||||
|     if (a < 0.0) { | ||||
|         discard_fragment(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| template<typename T> | ||||
| float rcp(T a) | ||||
| { | ||||
|     return 1.0 / a; | ||||
| } | ||||
| 
 | ||||
| template<typename T> | ||||
| float4x4 mul(T a, T b) | ||||
| { | ||||
|     a * b; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __air__ | ||||
| #define UNROLL | ||||
| #define BRANCH | ||||
| #else | ||||
| #define UNROLL [unroll] | ||||
| #define BRANCH [branch] | ||||
| #endif | ||||
| 
 | ||||
| float w0(float a) | ||||
| { | ||||
|     return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); | ||||
|  | @ -109,6 +224,74 @@ float h1(float a) | |||
|     return 1.0f + w3(a) / (w2(a) + w3(a)) + 0.5f; | ||||
| } | ||||
| 
 | ||||
| struct CubeMapData | ||||
| { | ||||
|     float3 cubeMapDirections[2]; | ||||
|     uint cubeMapIndex; | ||||
| }; | ||||
| 
 | ||||
| #ifdef __air__ | ||||
| 
 | ||||
| float4 tfetch2DBicubic(constant Texture2DDescriptorHeap& textureHeap, | ||||
|                        constant SamplerDescriptorHeap& samplerHeap, | ||||
|                        uint resourceDescriptorIndex, | ||||
|                        uint samplerDescriptorIndex, | ||||
|                        float2 texCoord, float2 offset) | ||||
| { | ||||
|     texture2d<float> texture = textureHeap.g[resourceDescriptorIndex]; | ||||
|     sampler sampler = samplerHeap.g[samplerDescriptorIndex]; | ||||
|     uint2 dimensions = getTexture2DDimensions(texture); | ||||
| 
 | ||||
|     float x = texCoord.x * dimensions.x + offset.x; | ||||
|     float y = texCoord.y * dimensions.y + offset.y; | ||||
| 
 | ||||
|     x -= 0.5f; | ||||
|     y -= 0.5f; | ||||
|     float px = floor(x); | ||||
|     float py = floor(y); | ||||
|     float fx = x - px; | ||||
|     float fy = y - py; | ||||
| 
 | ||||
|     float g0x = g0(fx); | ||||
|     float g1x = g1(fx); | ||||
|     float h0x = h0(fx); | ||||
|     float h1x = h1(fx); | ||||
|     float h0y = h0(fy); | ||||
|     float h1y = h1(fy); | ||||
| 
 | ||||
|     float4 r = | ||||
|         g0(fy) * (g0x * texture.sample(sampler, float2(px + h0x, py + h0y) / float2(dimensions)) + | ||||
|               g1x * texture.sample(sampler, float2(px + h1x, py + h0y) / float2(dimensions))) + | ||||
|         g1(fy) * (g0x * texture.sample(sampler, float2(px + h0x, py + h1y) / float2(dimensions)) + | ||||
|               g1x * texture.sample(sampler, float2(px + h1x, py + h1y) / float2(dimensions))); | ||||
| 
 | ||||
|     return r; | ||||
| } | ||||
| 
 | ||||
| float4 tfetch3D(constant Texture3DDescriptorHeap& textureHeap, | ||||
|                 constant SamplerDescriptorHeap& samplerHeap, | ||||
|                 uint resourceDescriptorIndex, | ||||
|                 uint samplerDescriptorIndex, | ||||
|                 float3 texCoord) | ||||
| { | ||||
|     texture3d<float> texture = textureHeap.g[resourceDescriptorIndex]; | ||||
|     sampler sampler = samplerHeap.g[samplerDescriptorIndex]; | ||||
|     return texture.sample(sampler, texCoord); | ||||
| } | ||||
| 
 | ||||
| float4 tfetchCube(constant TextureCubeDescriptorHeap& textureHeap, | ||||
|                   constant SamplerDescriptorHeap& samplerHeap, | ||||
|                   uint resourceDescriptorIndex, | ||||
|                   uint samplerDescriptorIndex, | ||||
|                   float3 texCoord, thread CubeMapData* cubeMapData) | ||||
| { | ||||
|     texturecube<float> texture = textureHeap.g[resourceDescriptorIndex]; | ||||
|     sampler sampler = samplerHeap.g[samplerDescriptorIndex]; | ||||
|     return texture.sample(sampler, cubeMapData->cubeMapDirections[(uint)texCoord.z]); | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| float4 tfetch2DBicubic(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset) | ||||
| { | ||||
|     Texture2D<float4> texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; | ||||
|  | @ -146,17 +329,13 @@ float4 tfetch3D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float | |||
|     return g_Texture3DDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord); | ||||
| } | ||||
| 
 | ||||
| struct CubeMapData | ||||
| { | ||||
|     float3 cubeMapDirections[2]; | ||||
|     uint cubeMapIndex; | ||||
| }; | ||||
| 
 | ||||
| float4 tfetchCube(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float3 texCoord, inout CubeMapData cubeMapData) | ||||
| { | ||||
|     return g_TextureCubeDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], cubeMapData.cubeMapDirections[texCoord.z]); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| float4 tfetchR11G11B10(uint4 value) | ||||
| { | ||||
|     if (g_SpecConstants() & SPEC_CONSTANT_R11G11B10_NORMAL) | ||||
|  | @ -169,7 +348,11 @@ float4 tfetchR11G11B10(uint4 value) | |||
|     } | ||||
|     else | ||||
|     { | ||||
| #ifdef __air__ | ||||
|         return as_type<float4>(value); | ||||
| #else | ||||
|         return asfloat(value); | ||||
| #endif | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -178,6 +361,19 @@ float4 tfetchTexcoord(uint swappedTexcoords, float4 value, uint semanticIndex) | |||
|     return (swappedTexcoords & (1ull << semanticIndex)) != 0 ? value.yxwz : value; | ||||
| } | ||||
| 
 | ||||
| #ifdef __air__ | ||||
| 
 | ||||
| float4 cube(float4 value, thread CubeMapData* cubeMapData) | ||||
| { | ||||
|     uint index = cubeMapData->cubeMapIndex; | ||||
|     cubeMapData->cubeMapDirections[index] = value.xyz; | ||||
|     ++cubeMapData->cubeMapIndex; | ||||
| 
 | ||||
|     return float4(0.0, 0.0, 0.0, index); | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| float4 cube(float4 value, inout CubeMapData cubeMapData) | ||||
| { | ||||
|     uint index = cubeMapData.cubeMapIndex; | ||||
|  | @ -187,6 +383,8 @@ float4 cube(float4 value, inout CubeMapData cubeMapData) | |||
|     return float4(0.0, 0.0, 0.0, index); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| float4 dst(float4 src0, float4 src1) | ||||
| { | ||||
|     float4 dest; | ||||
|  | @ -202,15 +400,34 @@ float4 max4(float4 src0) | |||
|     return max(max(src0.x, src0.y), max(src0.z, src0.w)); | ||||
| } | ||||
| 
 | ||||
| #ifdef __air__ | ||||
| 
 | ||||
| float2 getPixelCoord(constant Texture2DDescriptorHeap& textureHeap, | ||||
|                      uint resourceDescriptorIndex, | ||||
|                      float2 texCoord) | ||||
| { | ||||
|     texture2d<float> texture = textureHeap.g[resourceDescriptorIndex]; | ||||
|     return (float2)getTexture2DDimensions(texture) * texCoord; | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| float2 getPixelCoord(uint resourceDescriptorIndex, float2 texCoord) | ||||
| { | ||||
|     return getTexture2DDimensions(g_Texture2DDescriptorHeap[resourceDescriptorIndex]) * texCoord; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| float computeMipLevel(float2 pixelCoord) | ||||
| { | ||||
| #ifdef __air__ | ||||
|     float2 dx = dfdx(pixelCoord); | ||||
|     float2 dy = dfdy(pixelCoord); | ||||
| #else | ||||
|     float2 dx = ddx(pixelCoord); | ||||
|     float2 dy = ddy(pixelCoord); | ||||
| #endif | ||||
|     float deltaMaxSqr = max(dot(dx, dx), dot(dy, dy)); | ||||
|     return max(0.0, 0.5 * log2(deltaMaxSqr)); | ||||
| } | ||||
|  |  | |||
|  | @ -271,7 +271,13 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicu | |||
|     if (instr.constIndex == 0 && instr.dimension == TextureDimension::Texture2D) | ||||
|     { | ||||
|         indent(); | ||||
|         print("pixelCoord = getPixelCoord({}_Texture2DDescriptorIndex, ", constNamePtr); | ||||
|         println("pixelCoord = getPixelCoord("); | ||||
|         println("#ifdef __air__"); | ||||
|         indent(); | ||||
|         println("g_Texture2DDescriptorHeap,"); | ||||
|         println("#endif"); | ||||
|         indent(); | ||||
|         print("{}_Texture2DDescriptorIndex, ", constNamePtr); | ||||
|         printSrcRegister(2); | ||||
|         out += ");\n"; | ||||
|     } | ||||
|  | @ -331,7 +337,17 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicu | |||
|         out += "Bicubic"; | ||||
| #endif | ||||
| 
 | ||||
|     print("({0}_Texture{1}DescriptorIndex, {0}_SamplerDescriptorIndex, ", constNamePtr, dimension); | ||||
|     println("("); | ||||
| 
 | ||||
|     println("#ifdef __air__"); | ||||
|     indent(); | ||||
|     println("\tg_Texture{}DescriptorHeap,", dimension); | ||||
|     indent(); | ||||
|     println("\tg_SamplerDescriptorHeap,"); | ||||
|     println("#endif"); | ||||
| 
 | ||||
|     indent(); | ||||
|     print("\t{0}_Texture{1}DescriptorIndex, {0}_SamplerDescriptorIndex, ", constNamePtr, dimension); | ||||
|     printSrcRegister(componentCount); | ||||
| 
 | ||||
|     switch (instr.dimension) | ||||
|  | @ -680,14 +696,24 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|             print("r{}.", instr.vectorDest); | ||||
|         } | ||||
| 
 | ||||
|         uint32_t vectorWriteSize = 0; | ||||
| 
 | ||||
|         for (size_t i = 0; i < 4; i++) | ||||
|         { | ||||
|             if ((vectorWriteMask >> i) & 0x1) | ||||
|             if ((vectorWriteMask >> i) & 0x1) { | ||||
|                 out += SWIZZLES[i]; | ||||
|                 vectorWriteSize++; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         out += " = "; | ||||
| 
 | ||||
|         if (vectorWriteSize > 1) { | ||||
|             print("(float{})(", vectorWriteSize); | ||||
|         } else { | ||||
|             out += "(float)("; | ||||
|         } | ||||
| 
 | ||||
|         if (instr.vectorSaturate) | ||||
|             out += "saturate("; | ||||
| 
 | ||||
|  | @ -743,15 +769,15 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::CndEq: | ||||
|             print("select({} == 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             print("selectWrapper({} == 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::CndGe: | ||||
|             print("select({} >= 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             print("selectWrapper({} >= 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::CndGt: | ||||
|             print("select({} > 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             print("selectWrapper({} > 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::Dp4: | ||||
|  | @ -802,7 +828,7 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|         if (instr.vectorSaturate) | ||||
|             out += ')'; | ||||
| 
 | ||||
|         out += ";\n"; | ||||
|         out += ");\n"; | ||||
|     } | ||||
| 
 | ||||
|     if (instr.scalarOpcode != AluScalarOpcode::RetainPrev) | ||||
|  | @ -1154,7 +1180,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|             { | ||||
|                 uint32_t tailCount = (isPixelShader ? 224 : 256) - constantInfo->registerIndex; | ||||
| 
 | ||||
|                 println("#define {}(INDEX) select((INDEX) < {}, vk::RawBufferLoad<float4>(g_PushConstants.{}ShaderConstants + ({} + min(INDEX, {})) * 16, 0x10), 0.0)", | ||||
|                 println("#define {}(INDEX) selectWrapper((INDEX) < {}, vk::RawBufferLoad<float4>(g_PushConstants.{}ShaderConstants + ({} + min(INDEX, {})) * 16, 0x10), 0.0)", | ||||
|                     constantName, tailCount, shaderName, constantInfo->registerIndex.get(), tailCount - 1); | ||||
|             } | ||||
|             else | ||||
|  | @ -1187,6 +1213,75 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     out += "\n#elif __air__\n\n"; | ||||
| 
 | ||||
|     for (uint32_t i = 0; i < constantTableContainer->constantTable.constants; i++) | ||||
|     { | ||||
|         const auto constantInfo = reinterpret_cast<const ConstantInfo*>( | ||||
|             constantTableData + constantTableContainer->constantTable.constantInfo + i * sizeof(ConstantInfo)); | ||||
| 
 | ||||
|         const char* constantName = reinterpret_cast<const char*>(constantTableData + constantInfo->name); | ||||
| 
 | ||||
|     #ifdef UNLEASHED_RECOMP | ||||
|         if (!isPixelShader) | ||||
|         { | ||||
|             if (strcmp(constantName, "g_MtxProjection") == 0) | ||||
|                 hasMtxProjection = true; | ||||
|             else if (strcmp(constantName, "g_InstanceTypes") == 0) | ||||
|                 isMetaInstancer = true; | ||||
|             else if (strcmp(constantName, "g_IndexCount") == 0) | ||||
|                 hasIndexCount = true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (strcmp(constantName, "g_MtxPrevInvViewProjection") == 0) | ||||
|                 hasMtxPrevInvViewProjection = true; | ||||
|         } | ||||
|     #endif | ||||
| 
 | ||||
|         switch (constantInfo->registerSet) | ||||
|         { | ||||
|         case RegisterSet::Float4: | ||||
|         { | ||||
|             const char* shaderName = isPixelShader ? "Pixel" : "Vertex"; | ||||
| 
 | ||||
|             if (constantInfo->registerCount > 1) | ||||
|             { | ||||
|                 uint32_t tailCount = (isPixelShader ? 224 : 256) - constantInfo->registerIndex; | ||||
| 
 | ||||
|                 println("#define {}(INDEX) selectWrapper((INDEX) < {}, (*(reinterpret_cast<device float4*>(g_PushConstants.{}ShaderConstants + ({} + min(INDEX, {})) * 16))), 0.0)", | ||||
|                     constantName, tailCount, shaderName, constantInfo->registerIndex.get(), tailCount - 1); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 println("#define {} (*(reinterpret_cast<device float4*>(g_PushConstants.{}ShaderConstants + {})))", | ||||
|                     constantName, shaderName, constantInfo->registerIndex * 16); | ||||
|             } | ||||
| 
 | ||||
|             for (uint16_t j = 0; j < constantInfo->registerCount; j++) | ||||
|                 float4Constants.emplace(constantInfo->registerIndex + j, constantInfo); | ||||
| 
 | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case RegisterSet::Sampler: | ||||
|         { | ||||
|             for (size_t j = 0; j < std::size(TEXTURE_DIMENSIONS); j++) | ||||
|             { | ||||
|                 println("#define {}_Texture{}DescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + {})))", | ||||
|                     constantName, TEXTURE_DIMENSIONS[j], j * 64 + constantInfo->registerIndex * 4); | ||||
|             } | ||||
| 
 | ||||
|             println("#define {}_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + {})))", | ||||
|                 constantName, std::size(TEXTURE_DIMENSIONS) * 64 + constantInfo->registerIndex * 4); | ||||
| 
 | ||||
|             samplers.emplace(constantInfo->registerIndex, constantName); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     out += "\n#else\n\n"; | ||||
| 
 | ||||
|     println("cbuffer {}ShaderConstants : register(b{}, space4)", isPixelShader ? "Pixel" : "Vertex", isPixelShader ? 1 : 0); | ||||
|  | @ -1211,7 +1306,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|             if (constantInfo->registerCount > 1) | ||||
|             { | ||||
|                 uint32_t tailCount = (isPixelShader ? 224 : 256) - constantInfo->registerIndex; | ||||
|                 println("#define {0}(INDEX) select((INDEX) < {1}, {0}[min(INDEX, {2})], 0.0)", constantName, tailCount, tailCount - 1); | ||||
|                 println("#define {0}(INDEX) selectWrapper((INDEX) < {1}, {0}[min(INDEX, {2})], 0.0)", constantName, tailCount, tailCount - 1); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -1263,7 +1358,24 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
| 
 | ||||
|     const auto shader = reinterpret_cast<const Shader*>(shaderData + shaderContainer->shaderOffset); | ||||
| 
 | ||||
|     out += "#ifndef __spirv__\n"; | ||||
|     out += "#if __air__\n"; | ||||
| 
 | ||||
|     if (isPixelShader) { | ||||
|         out += "struct StageIn\n"; | ||||
|         out += "{\n"; | ||||
| 
 | ||||
|         for (auto& [usage, usageIndex] : INTERPOLATORS) | ||||
|             println("\tfloat4 i{}{};", USAGE_VARIABLES[uint32_t(usage)], usageIndex); | ||||
| 
 | ||||
|         out += "};\n"; | ||||
|     } | ||||
| 
 | ||||
|     if (isPixelShader) | ||||
|         out += "[[fragment]]\n"; | ||||
|     else | ||||
|         out += "[[vertex]]\n"; | ||||
| 
 | ||||
|     out += "#elifndef __spirv__\n"; | ||||
| 
 | ||||
|     if (isPixelShader) | ||||
|         out += "[shader(\"pixel\")]\n"; | ||||
|  | @ -1272,10 +1384,36 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
| 
 | ||||
|     out += "#endif\n"; | ||||
| 
 | ||||
|     out += "void main(\n"; | ||||
|     out += "void shaderMain(\n"; | ||||
| 
 | ||||
|     if (isPixelShader) | ||||
|     { | ||||
|         out += "#ifdef __air__\n"; | ||||
| 
 | ||||
|         out += "\tStageIn iStageIn [[stage_in]],\n"; | ||||
|         out += "\tfloat4 iPos [[position]],\n"; | ||||
|         out += "\tbool iFace [[front_facing]],\n"; | ||||
| 
 | ||||
|         auto pixelShader = reinterpret_cast<const PixelShader*>(shader); | ||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR0) | ||||
|             out += "\tfloat4 oC0 [[color(0)]],\n"; | ||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR1) | ||||
|             out += "\tfloat4 oC1 [[color(1)]],\n"; | ||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR2) | ||||
|             out += "\tfloat4 oC2 [[color(2)]],\n"; | ||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR3) | ||||
|             out += "\tfloat4 oC3 [[color(3)]],\n"; | ||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_DEPTH) | ||||
|             out += "\tfloat oDepth [[depth(any)]],\n"; | ||||
| 
 | ||||
|         out += "\tconstant Texture2DDescriptorHeap& g_Texture2DDescriptorHeap [[buffer(0)]],\n"; | ||||
|         out += "\tconstant Texture3DDescriptorHeap& g_Texture3DDescriptorHeap [[buffer(1)]],\n"; | ||||
|         out += "\tconstant TextureCubeDescriptorHeap& g_TextureCubeDescriptorHeap [[buffer(2)]],\n"; | ||||
|         out += "\tconstant SamplerDescriptorHeap& g_SamplerDescriptorHeap [[buffer(3)]],\n"; | ||||
|         out += "\tconstant PushConstants& g_PushConstants [[buffer(4)]]\n"; | ||||
| 
 | ||||
|         out += "#else\n"; | ||||
| 
 | ||||
|         out += "\tin float4 iPos : SV_Position,\n"; | ||||
| 
 | ||||
|         for (auto& [usage, usageIndex] : INTERPOLATORS) | ||||
|  | @ -1287,7 +1425,6 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|         out += "\tin uint iFace : SV_IsFrontFace\n"; | ||||
|         out += "#endif\n"; | ||||
| 
 | ||||
|         auto pixelShader = reinterpret_cast<const PixelShader*>(shader); | ||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR0) | ||||
|             out += ",\n\tout float4 oC0 : SV_Target0"; | ||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR1) | ||||
|  | @ -1298,6 +1435,8 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|             out += ",\n\tout float4 oC3 : SV_Target3"; | ||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_DEPTH) | ||||
|             out += ",\n\tout float oDepth : SV_Depth"; | ||||
| 
 | ||||
|         out += "\n#endif\n"; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | @ -1342,8 +1481,13 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|     #ifdef UNLEASHED_RECOMP | ||||
|         if (hasIndexCount) | ||||
|         { | ||||
|             out += "#ifdef __air__\n"; | ||||
|             out += "\tuint iVertexId [[vertex_id]],\n"; | ||||
|             out += "\tuint iInstanceId [[instance_id]],\n"; | ||||
|             out += "#else\n"; | ||||
|             out += "\tin uint iVertexId : SV_VertexID,\n"; | ||||
|             out += "\tin uint iInstanceId : SV_InstanceID,\n"; | ||||
|             out += "#endif\n"; | ||||
|         } | ||||
|     #endif | ||||
| 
 | ||||
|  | @ -1366,7 +1510,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|         out += "\tfloat4x4 mtxProjection = float4x4(g_MtxProjection(0), g_MtxProjection(1), g_MtxProjection(2), g_MtxProjection(3));\n"; | ||||
|         out += "\tfloat4x4 mtxProjectionReverseZ = mul(mtxProjection, float4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 1));\n"; | ||||
| 
 | ||||
|         out += "\t[unroll] for (int iterationIndex = 0; iterationIndex < 2; iterationIndex++)\n"; | ||||
|         out += "\tUNROLL for (int iterationIndex = 0; iterationIndex < 2; iterationIndex++)\n"; | ||||
|         out += "\t{\n"; | ||||
|     } | ||||
| #endif | ||||
|  | @ -1381,8 +1525,13 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|             auto value = reinterpret_cast<const be<uint32_t>*>(shaderData + shaderContainer->virtualSize + definition->physicalOffset); | ||||
|             for (uint16_t i = 0; i < (definition->count + 3) / 4; i++) | ||||
|             { | ||||
|                 println("#ifdef __air__"); | ||||
|                 println("\tfloat4 c{} = as_type<float4>(uint4(0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}));", | ||||
|                     definition->registerIndex + i - (isPixelShader ? 256 : 0), value[0].get(), value[1].get(), value[2].get(), value[3].get()); | ||||
|                 println("#else"); | ||||
|                 println("\tfloat4 c{} = asfloat(uint4(0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}));", | ||||
|                     definition->registerIndex + i - (isPixelShader ? 256 : 0), value[0].get(), value[1].get(), value[2].get(), value[3].get()); | ||||
|                 println("#endif"); | ||||
| 
 | ||||
|                 value += 4; | ||||
|             } | ||||
|  | @ -1433,7 +1582,11 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|         if (isPixelShader) | ||||
|         { | ||||
|             value = reinterpret_cast<const PixelShader*>(shader)->interpolators[i]; | ||||
|             println("#ifdef __air__"); | ||||
|             println("\tfloat4 r{} = iStageIn.i{}{};", uint32_t(interpolator.reg), USAGE_VARIABLES[uint32_t(interpolator.usage)], uint32_t(interpolator.usageIndex)); | ||||
|             println("#else"); | ||||
|             println("\tfloat4 r{} = i{}{};", uint32_t(interpolator.reg), USAGE_VARIABLES[uint32_t(interpolator.usage)], uint32_t(interpolator.usageIndex)); | ||||
|             println("#endif"); | ||||
|             printedRegisters[interpolator.reg] = true; | ||||
|         } | ||||
|         else | ||||
|  | @ -1488,7 +1641,11 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
| #ifdef UNLEASHED_RECOMP | ||||
|         out += "\tfloat2 pixelCoord = 0.0;\n"; | ||||
| #endif | ||||
|         out += "#ifdef __air__\n"; | ||||
|         out += "\tCubeMapData cubeMapdata = CubeMapData{};\n"; | ||||
|         out += "#else\n"; | ||||
|         out += "\tCubeMapData cubeMapData = (CubeMapData)0;\n"; | ||||
|         out += "#endif\n"; | ||||
|     } | ||||
| 
 | ||||
|     const be<uint32_t>* code = reinterpret_cast<const be<uint32_t>*>(shaderData + shaderContainer->virtualSize + shader->physicalOffset); | ||||
|  | @ -1646,7 +1803,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|                 { | ||||
|                     indent(); | ||||
|                 #ifdef UNLEASHED_RECOMP | ||||
|                     print("[unroll] "); | ||||
|                     print("UNROLL "); | ||||
|                 #endif | ||||
|                     println("for (aL = 0; aL < i{}.x; aL++)", uint32_t(cfInstr.loopStart.loopId)); | ||||
|                     indent(); | ||||
|  | @ -1754,27 +1911,27 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|                             specConstantsMask |= SPEC_CONSTANT_BICUBIC_GI_FILTER; | ||||
| 
 | ||||
|                             indent(); | ||||
|                             out += "if (g_SpecConstants() & SPEC_CONSTANT_BICUBIC_GI_FILTER)"; | ||||
|                             out += "if (g_SpecConstants() & SPEC_CONSTANT_BICUBIC_GI_FILTER)\n"; | ||||
|                             indent(); | ||||
|                             out += '{'; | ||||
|                             out += "{\n"; | ||||
| 
 | ||||
|                             ++indentation; | ||||
|                             recompile(textureFetch, true); | ||||
|                             --indentation; | ||||
| 
 | ||||
|                             indent(); | ||||
|                             out += "}"; | ||||
|                             out += "}\n"; | ||||
|                             indent(); | ||||
|                             out += "else"; | ||||
|                             out += "else\n"; | ||||
|                             indent(); | ||||
|                             out += '{'; | ||||
|                             out += "{\n"; | ||||
| 
 | ||||
|                             ++indentation; | ||||
|                             recompile(textureFetch, false); | ||||
|                             --indentation; | ||||
| 
 | ||||
|                             indent(); | ||||
|                             out += '}'; | ||||
|                             out += "}\n"; | ||||
|                         } | ||||
|                         else | ||||
|                     #endif | ||||
|  | @ -1799,23 +1956,23 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|                     specConstantsMask |= SPEC_CONSTANT_ALPHA_TEST; | ||||
| 
 | ||||
|                     indent(); | ||||
|                     out += "[branch] if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TEST)"; | ||||
|                     out += "BRANCH if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TEST)\n"; | ||||
|                     indent(); | ||||
|                     out += '{'; | ||||
|                     out += "{\n"; | ||||
| 
 | ||||
|                     indent(); | ||||
|                     out += "\tclip(oC0.w - g_AlphaThreshold);\n"; | ||||
| 
 | ||||
|                     indent(); | ||||
|                     out += "}"; | ||||
|                     out += "}\n"; | ||||
| 
 | ||||
|                 #ifdef UNLEASHED_RECOMP | ||||
|                     specConstantsMask |= SPEC_CONSTANT_ALPHA_TO_COVERAGE; | ||||
| 
 | ||||
|                     indent(); | ||||
|                     out += "else if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TO_COVERAGE)"; | ||||
|                     out += "else if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TO_COVERAGE)\n"; | ||||
|                     indent(); | ||||
|                     out += '{'; | ||||
|                     out += "{\n"; | ||||
| 
 | ||||
|                     indent(); | ||||
|                     out += "\toC0.w *= 1.0 + computeMipLevel(pixelCoord) * 0.25;\n"; | ||||
|  | @ -1823,7 +1980,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | |||
|                     out += "\toC0.w = 0.5 + (oC0.w - g_AlphaThreshold) / max(fwidth(oC0.w), 1e-6);\n"; | ||||
| 
 | ||||
|                     indent(); | ||||
|                     out += '}'; | ||||
|                     out += "}\n"; | ||||
|                 #endif | ||||
|                 } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue