mirror of
				https://github.com/hedge-dev/XenosRecomp.git
				synced 2025-10-30 07:12:17 +00:00 
			
		
		
		
	MSL Shader Generation
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
This commit is contained in:
		
							parent
							
								
									b15b5e4728
								
							
						
					
					
						commit
						a0e2d16fb0
					
				
					 5 changed files with 607 additions and 95 deletions
				
			
		|  | @ -4,6 +4,10 @@ if (WIN32) | ||||||
|     option(XENOS_RECOMP_DXIL "Generate DXIL shader cache" ON) |     option(XENOS_RECOMP_DXIL "Generate DXIL shader cache" ON) | ||||||
| endif() | 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") | set(SMOLV_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/smol-v/source") | ||||||
| 
 | 
 | ||||||
| add_executable(XenosRecomp  | add_executable(XenosRecomp  | ||||||
|  | @ -51,3 +55,7 @@ if (XENOS_RECOMP_DXIL) | ||||||
|     target_compile_definitions(XenosRecomp PRIVATE XENOS_RECOMP_DXIL) |     target_compile_definitions(XenosRecomp PRIVATE XENOS_RECOMP_DXIL) | ||||||
|     target_link_libraries(XenosRecomp PRIVATE Microsoft::DXIL) |     target_link_libraries(XenosRecomp PRIVATE Microsoft::DXIL) | ||||||
| endif() | endif() | ||||||
|  | 
 | ||||||
|  | if (XENOS_RECOMP_AIR) | ||||||
|  |     target_compile_definitions(XenosRecomp PRIVATE XENOS_RECOMP_AIR) | ||||||
|  | endif() | ||||||
|  |  | ||||||
|  | @ -34,6 +34,11 @@ IDxcBlob* DxcCompiler::compile(const std::string& shaderSource, bool compilePixe | ||||||
|             target = L"-T vs_6_0"; |             target = L"-T vs_6_0"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (!compileLibrary) | ||||||
|  |     { | ||||||
|  |         args[argCount++] = L"-E shaderMain"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     args[argCount++] = target; |     args[argCount++] = target; | ||||||
|     args[argCount++] = L"-HV 2021"; |     args[argCount++] = L"-HV 2021"; | ||||||
|     args[argCount++] = L"-all-resources-bound"; |     args[argCount++] = L"-all-resources-bound"; | ||||||
|  |  | ||||||
|  | @ -10,10 +10,12 @@ | ||||||
|     #define SPEC_CONSTANT_REVERSE_Z         (1 << 4) |     #define SPEC_CONSTANT_REVERSE_Z         (1 << 4) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if !defined(__cplusplus) || defined(__INTELLISENSE__) | #if defined(__air__) || !defined(__cplusplus) || defined(__INTELLISENSE__) | ||||||
| 
 | 
 | ||||||
|  | #ifndef __air__ | ||||||
| #define FLT_MIN asfloat(0xff7fffff) | #define FLT_MIN asfloat(0xff7fffff) | ||||||
| #define FLT_MAX asfloat(0x7f7fffff) | #define FLT_MAX asfloat(0x7f7fffff) | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef __spirv__ | #ifdef __spirv__ | ||||||
| 
 | 
 | ||||||
|  | @ -34,6 +36,30 @@ struct PushConstants | ||||||
| 
 | 
 | ||||||
| #define g_SpecConstants() g_SpecConstants | #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 | #else | ||||||
| 
 | 
 | ||||||
| #define DEFINE_SHARED_CONSTANTS() \ | #define DEFINE_SHARED_CONSTANTS() \ | ||||||
|  | @ -45,6 +71,56 @@ uint g_SpecConstants(); | ||||||
| 
 | 
 | ||||||
| #endif | #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); | Texture2D<float4> g_Texture2DDescriptorHeap[] : register(t0, space0); | ||||||
| Texture3D<float4> g_Texture3DDescriptorHeap[] : register(t0, space1); | Texture3D<float4> g_Texture3DDescriptorHeap[] : register(t0, space1); | ||||||
| TextureCube<float4> g_TextureCubeDescriptorHeap[] : register(t0, space2); | TextureCube<float4> g_TextureCubeDescriptorHeap[] : register(t0, space2); | ||||||
|  | @ -69,6 +145,46 @@ float2 getWeights2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, f | ||||||
|     return select(isnan(texCoord), 0.0, frac(texCoord * getTexture2DDimensions(texture) + offset - 0.5)); |     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) | ||||||
|  | { | ||||||
|  |     return a * b; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #ifdef __air__ | ||||||
|  | #define UNROLL | ||||||
|  | #define BRANCH | ||||||
|  | #else | ||||||
|  | #define UNROLL [unroll] | ||||||
|  | #define BRANCH [branch] | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| float w0(float a) | float w0(float a) | ||||||
| { | { | ||||||
|     return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); |     return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); | ||||||
|  | @ -109,6 +225,74 @@ float h1(float a) | ||||||
|     return 1.0f + w3(a) / (w2(a) + w3(a)) + 0.5f; |     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) | float4 tfetch2DBicubic(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset) | ||||||
| { | { | ||||||
|     Texture2D<float4> texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; |     Texture2D<float4> texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; | ||||||
|  | @ -146,17 +330,13 @@ float4 tfetch3D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float | ||||||
|     return g_Texture3DDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord); |     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) | float4 tfetchCube(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float3 texCoord, inout CubeMapData cubeMapData) | ||||||
| { | { | ||||||
|     return g_TextureCubeDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], cubeMapData.cubeMapDirections[texCoord.z]); |     return g_TextureCubeDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], cubeMapData.cubeMapDirections[texCoord.z]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| float4 tfetchR11G11B10(uint4 value) | float4 tfetchR11G11B10(uint4 value) | ||||||
| { | { | ||||||
|     if (g_SpecConstants() & SPEC_CONSTANT_R11G11B10_NORMAL) |     if (g_SpecConstants() & SPEC_CONSTANT_R11G11B10_NORMAL) | ||||||
|  | @ -169,7 +349,11 @@ float4 tfetchR11G11B10(uint4 value) | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|  | #ifdef __air__ | ||||||
|  |         return as_type<float4>(value); | ||||||
|  | #else | ||||||
|         return asfloat(value); |         return asfloat(value); | ||||||
|  | #endif | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -178,6 +362,19 @@ float4 tfetchTexcoord(uint swappedTexcoords, float4 value, uint semanticIndex) | ||||||
|     return (swappedTexcoords & (1ull << semanticIndex)) != 0 ? value.yxwz : value; |     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) | float4 cube(float4 value, inout CubeMapData cubeMapData) | ||||||
| { | { | ||||||
|     uint index = cubeMapData.cubeMapIndex; |     uint index = cubeMapData.cubeMapIndex; | ||||||
|  | @ -187,6 +384,8 @@ float4 cube(float4 value, inout CubeMapData cubeMapData) | ||||||
|     return float4(0.0, 0.0, 0.0, index); |     return float4(0.0, 0.0, 0.0, index); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| float4 dst(float4 src0, float4 src1) | float4 dst(float4 src0, float4 src1) | ||||||
| { | { | ||||||
|     float4 dest; |     float4 dest; | ||||||
|  | @ -202,15 +401,34 @@ float4 max4(float4 src0) | ||||||
|     return max(max(src0.x, src0.y), max(src0.z, src0.w)); |     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) | float2 getPixelCoord(uint resourceDescriptorIndex, float2 texCoord) | ||||||
| { | { | ||||||
|     return getTexture2DDimensions(g_Texture2DDescriptorHeap[resourceDescriptorIndex]) * texCoord; |     return getTexture2DDimensions(g_Texture2DDescriptorHeap[resourceDescriptorIndex]) * texCoord; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| float computeMipLevel(float2 pixelCoord) | float computeMipLevel(float2 pixelCoord) | ||||||
| { | { | ||||||
|  | #ifdef __air__ | ||||||
|  |     float2 dx = dfdx(pixelCoord); | ||||||
|  |     float2 dy = dfdy(pixelCoord); | ||||||
|  | #else | ||||||
|     float2 dx = ddx(pixelCoord); |     float2 dx = ddx(pixelCoord); | ||||||
|     float2 dy = ddy(pixelCoord); |     float2 dy = ddy(pixelCoord); | ||||||
|  | #endif | ||||||
|     float deltaMaxSqr = max(dot(dx, dx), dot(dy, dy)); |     float deltaMaxSqr = max(dot(dx, dx), dot(dy, dy)); | ||||||
|     return max(0.0, 0.5 * log2(deltaMaxSqr)); |     return max(0.0, 0.5 * log2(deltaMaxSqr)); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -130,14 +130,21 @@ static FetchDestinationSwizzle getDestSwizzle(uint32_t dstSwizzle, uint32_t inde | ||||||
|     return FetchDestinationSwizzle((dstSwizzle >> (index * 3)) & 0x7); |     return FetchDestinationSwizzle((dstSwizzle >> (index * 3)) & 0x7); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShaderRecompiler::printDstSwizzle(uint32_t dstSwizzle, bool operand) | uint32_t ShaderRecompiler::printDstSwizzle(uint32_t dstSwizzle, bool operand) | ||||||
| { | { | ||||||
|  |     uint32_t size = 0; | ||||||
|  | 
 | ||||||
|     for (size_t i = 0; i < 4; i++) |     for (size_t i = 0; i < 4; i++) | ||||||
|     { |     { | ||||||
|         const auto swizzle = getDestSwizzle(dstSwizzle, i); |         const auto swizzle = getDestSwizzle(dstSwizzle, i); | ||||||
|         if (swizzle >= FetchDestinationSwizzle::X && swizzle <= FetchDestinationSwizzle::W) |         if (swizzle >= FetchDestinationSwizzle::X && swizzle <= FetchDestinationSwizzle::W) | ||||||
|  |         { | ||||||
|             out += SWIZZLES[operand ? uint32_t(swizzle) : i]; |             out += SWIZZLES[operand ? uint32_t(swizzle) : i]; | ||||||
|  |             size++; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     return size; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShaderRecompiler::printDstSwizzle01(uint32_t dstRegister, uint32_t dstSwizzle) | void ShaderRecompiler::printDstSwizzle01(uint32_t dstRegister, uint32_t dstSwizzle) | ||||||
|  | @ -172,10 +179,15 @@ void ShaderRecompiler::recompile(const VertexFetchInstruction& instr, uint32_t a | ||||||
| 
 | 
 | ||||||
|     indent(); |     indent(); | ||||||
|     print("r{}.", instr.dstRegister); |     print("r{}.", instr.dstRegister); | ||||||
|     printDstSwizzle(instr.dstSwizzle, false); |     uint32_t size = printDstSwizzle(instr.dstSwizzle, false); | ||||||
| 
 | 
 | ||||||
|     out += " = "; |     out += " = "; | ||||||
| 
 | 
 | ||||||
|  |     if (size <= 1) | ||||||
|  |         out += "(float)("; | ||||||
|  |     else | ||||||
|  |         print("(float{})(", size); | ||||||
|  | 
 | ||||||
|     auto findResult = vertexElements.find(address); |     auto findResult = vertexElements.find(address); | ||||||
|     assert(findResult != vertexElements.end()); |     assert(findResult != vertexElements.end()); | ||||||
| 
 | 
 | ||||||
|  | @ -185,15 +197,15 @@ void ShaderRecompiler::recompile(const VertexFetchInstruction& instr, uint32_t a | ||||||
|     case DeclUsage::Tangent: |     case DeclUsage::Tangent: | ||||||
|     case DeclUsage::Binormal: |     case DeclUsage::Binormal: | ||||||
|         specConstantsMask |= SPEC_CONSTANT_R11G11B10_NORMAL; |         specConstantsMask |= SPEC_CONSTANT_R11G11B10_NORMAL; | ||||||
|         print("tfetchR11G11B10("); |         print("tfetchR11G11B10((uint4)"); | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case DeclUsage::TexCoord: |     case DeclUsage::TexCoord: | ||||||
|         print("tfetchTexcoord(g_SwappedTexcoords, "); |         print("tfetchTexcoord(g_SwappedTexcoords, (float4)"); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     print("i{}{}", USAGE_VARIABLES[uint32_t(findResult->second.usage)], uint32_t(findResult->second.usageIndex)); |     print("(input.i{}{})", USAGE_VARIABLES[uint32_t(findResult->second.usage)], uint32_t(findResult->second.usageIndex)); | ||||||
| 
 | 
 | ||||||
|     switch (findResult->second.usage) |     switch (findResult->second.usage) | ||||||
|     { |     { | ||||||
|  | @ -208,7 +220,7 @@ void ShaderRecompiler::recompile(const VertexFetchInstruction& instr, uint32_t a | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     out += '.'; |     out += ")."; | ||||||
|     printDstSwizzle(instr.dstSwizzle, true); |     printDstSwizzle(instr.dstSwizzle, true); | ||||||
| 
 | 
 | ||||||
|     out += ";\n"; |     out += ";\n"; | ||||||
|  | @ -271,7 +283,13 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicu | ||||||
|     if (instr.constIndex == 0 && instr.dimension == TextureDimension::Texture2D) |     if (instr.constIndex == 0 && instr.dimension == TextureDimension::Texture2D) | ||||||
|     { |     { | ||||||
|         indent(); |         indent(); | ||||||
|         print("pixelCoord = getPixelCoord({}_Texture2DDescriptorIndex, ", constNamePtr); |         println("pixelCoord = getPixelCoord("); | ||||||
|  |         println("#ifdef __air__"); | ||||||
|  |         indent(); | ||||||
|  |         println("g_Texture2DDescriptorHeap,"); | ||||||
|  |         println("#endif"); | ||||||
|  |         indent(); | ||||||
|  |         print("{}_Texture2DDescriptorIndex, ", constNamePtr); | ||||||
|         printSrcRegister(2); |         printSrcRegister(2); | ||||||
|         out += ");\n"; |         out += ");\n"; | ||||||
|     } |     } | ||||||
|  | @ -331,7 +349,17 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicu | ||||||
|         out += "Bicubic"; |         out += "Bicubic"; | ||||||
| #endif | #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); |     printSrcRegister(componentCount); | ||||||
| 
 | 
 | ||||||
|     switch (instr.dimension) |     switch (instr.dimension) | ||||||
|  | @ -340,7 +368,13 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicu | ||||||
|         print(", float2({}, {})", instr.offsetX * 0.5f, instr.offsetY * 0.5f); |         print(", float2({}, {})", instr.offsetX * 0.5f, instr.offsetY * 0.5f); | ||||||
|         break; |         break; | ||||||
|     case TextureDimension::TextureCube: |     case TextureDimension::TextureCube: | ||||||
|         out += ", cubeMapData"; |         println("\n#ifdef __air__"); | ||||||
|  |         indent(); | ||||||
|  |         println(", &cubeMapData"); | ||||||
|  |         println("#else"); | ||||||
|  |         indent(); | ||||||
|  |         println(", cubeMapData"); | ||||||
|  |         println("#endif"); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -578,6 +612,8 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|     bool closeIfBracket = false; |     bool closeIfBracket = false; | ||||||
| 
 | 
 | ||||||
|     std::string_view exportRegister; |     std::string_view exportRegister; | ||||||
|  |     bool vectorRegister = true; | ||||||
|  | 
 | ||||||
|     if (instr.exportData) |     if (instr.exportData) | ||||||
|     { |     { | ||||||
|         if (isPixelShader) |         if (isPixelShader) | ||||||
|  | @ -585,19 +621,20 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|             switch (ExportRegister(instr.vectorDest)) |             switch (ExportRegister(instr.vectorDest)) | ||||||
|             { |             { | ||||||
|             case ExportRegister::PSColor0: |             case ExportRegister::PSColor0: | ||||||
|                 exportRegister = "oC0"; |                 exportRegister = "output.oC0"; | ||||||
|                 break;         |                 break;         | ||||||
|             case ExportRegister::PSColor1: |             case ExportRegister::PSColor1: | ||||||
|                 exportRegister = "oC1"; |                 exportRegister = "output.oC1"; | ||||||
|                 break;         |                 break;         | ||||||
|             case ExportRegister::PSColor2: |             case ExportRegister::PSColor2: | ||||||
|                 exportRegister = "oC2"; |                 exportRegister = "output.oC2"; | ||||||
|                 break;             |                 break;             | ||||||
|             case ExportRegister::PSColor3: |             case ExportRegister::PSColor3: | ||||||
|                 exportRegister = "oC3"; |                 exportRegister = "output.oC3"; | ||||||
|                 break;            |                 break;            | ||||||
|             case ExportRegister::PSDepth: |             case ExportRegister::PSDepth: | ||||||
|                 exportRegister = "oDepth"; |                 exportRegister = "output.oDepth"; | ||||||
|  |                 vectorRegister = false; | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -606,7 +643,7 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|             switch (ExportRegister(instr.vectorDest)) |             switch (ExportRegister(instr.vectorDest)) | ||||||
|             { |             { | ||||||
|             case ExportRegister::VSPosition: |             case ExportRegister::VSPosition: | ||||||
|                 exportRegister = "oPos"; |                 exportRegister = "output.oPos"; | ||||||
| 
 | 
 | ||||||
|             #ifdef UNLEASHED_RECOMP |             #ifdef UNLEASHED_RECOMP | ||||||
|                 if (hasMtxProjection) |                 if (hasMtxProjection) | ||||||
|  | @ -673,21 +710,33 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|         if (!exportRegister.empty()) |         if (!exportRegister.empty()) | ||||||
|         { |         { | ||||||
|             out += exportRegister; |             out += exportRegister; | ||||||
|             out += '.'; |             if (vectorRegister) | ||||||
|  |                 out += '.'; | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             print("r{}.", instr.vectorDest); |             print("r{}.", instr.vectorDest); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         uint32_t vectorWriteSize = 0; | ||||||
|  | 
 | ||||||
|         for (size_t i = 0; i < 4; i++) |         for (size_t i = 0; i < 4; i++) | ||||||
|         { |         { | ||||||
|             if ((vectorWriteMask >> i) & 0x1) |             if ((vectorWriteMask >> i) & 0x1) | ||||||
|                 out += SWIZZLES[i]; |             { | ||||||
|  |                 if (vectorRegister) | ||||||
|  |                     out += SWIZZLES[i]; | ||||||
|  |                 vectorWriteSize++; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         out += " = "; |         out += " = "; | ||||||
| 
 | 
 | ||||||
|  |         if (vectorWriteSize > 1) | ||||||
|  |             print("(float{})(", vectorWriteSize); | ||||||
|  |         else | ||||||
|  |             out += "(float)("; | ||||||
|  | 
 | ||||||
|         if (instr.vectorSaturate) |         if (instr.vectorSaturate) | ||||||
|             out += "saturate("; |             out += "saturate("; | ||||||
| 
 | 
 | ||||||
|  | @ -743,15 +792,15 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::CndEq: |         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; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::CndGe: |         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; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::CndGt: |         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; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::Dp4: |         case AluVectorOpcode::Dp4: | ||||||
|  | @ -764,7 +813,13 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::Cube: |         case AluVectorOpcode::Cube: | ||||||
|  |             println("\n#ifdef __air__"); | ||||||
|  |             indent(); | ||||||
|  |             print("cube(r{}, &cubeMapData)", instr.src1Register); | ||||||
|  |             println("\n#else"); | ||||||
|  |             indent(); | ||||||
|             print("cube(r{}, cubeMapData)", instr.src1Register); |             print("cube(r{}, cubeMapData)", instr.src1Register); | ||||||
|  |             println("\n#endif"); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::Max4: |         case AluVectorOpcode::Max4: | ||||||
|  | @ -802,7 +857,7 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|         if (instr.vectorSaturate) |         if (instr.vectorSaturate) | ||||||
|             out += ')'; |             out += ')'; | ||||||
| 
 | 
 | ||||||
|         out += ";\n"; |         out += ");\n"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (instr.scalarOpcode != AluScalarOpcode::RetainPrev) |     if (instr.scalarOpcode != AluScalarOpcode::RetainPrev) | ||||||
|  | @ -1040,7 +1095,8 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|         if (!exportRegister.empty()) |         if (!exportRegister.empty()) | ||||||
|         { |         { | ||||||
|             out += exportRegister; |             out += exportRegister; | ||||||
|             out += '.'; |             if (vectorRegister) | ||||||
|  |                 out += '.'; | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|  | @ -1049,7 +1105,7 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
| 
 | 
 | ||||||
|         for (size_t i = 0; i < 4; i++) |         for (size_t i = 0; i < 4; i++) | ||||||
|         { |         { | ||||||
|             if ((scalarWriteMask >> i) & 0x1) |             if (((scalarWriteMask >> i) & 0x1) && vectorRegister) | ||||||
|                 out += SWIZZLES[i]; |                 out += SWIZZLES[i]; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1154,7 +1210,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|             { |             { | ||||||
|                 uint32_t tailCount = (isPixelShader ? 224 : 256) - constantInfo->registerIndex; |                 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); |                     constantName, tailCount, shaderName, constantInfo->registerIndex.get(), tailCount - 1); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|  | @ -1187,6 +1243,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"; |     out += "\n#else\n\n"; | ||||||
| 
 | 
 | ||||||
|     println("cbuffer {}ShaderConstants : register(b{}, space4)", isPixelShader ? "Pixel" : "Vertex", isPixelShader ? 1 : 0); |     println("cbuffer {}ShaderConstants : register(b{}, space4)", isPixelShader ? "Pixel" : "Vertex", isPixelShader ? 1 : 0); | ||||||
|  | @ -1211,7 +1336,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|             if (constantInfo->registerCount > 1) |             if (constantInfo->registerCount > 1) | ||||||
|             { |             { | ||||||
|                 uint32_t tailCount = (isPixelShader ? 224 : 256) - constantInfo->registerIndex; |                 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); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -1254,7 +1379,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|         if (constantInfo->registerSet == RegisterSet::Bool) |         if (constantInfo->registerSet == RegisterSet::Bool) | ||||||
|         { |         { | ||||||
|             const char* constantName = reinterpret_cast<const char*>(constantTableData + constantInfo->name); |             const char* constantName = reinterpret_cast<const char*>(constantTableData + constantInfo->name); | ||||||
|             println("\t#define {} (1 << {})", constantName, constantInfo->registerIndex + (isPixelShader ? 16 : 0)); |             println("#define {} (1 << {})", constantName, constantInfo->registerIndex + (isPixelShader ? 16 : 0)); | ||||||
|             boolConstants.emplace(constantInfo->registerIndex, constantName); |             boolConstants.emplace(constantInfo->registerIndex, constantName); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -1263,45 +1388,29 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
| 
 | 
 | ||||||
|     const auto shader = reinterpret_cast<const Shader*>(shaderData + shaderContainer->shaderOffset); |     const auto shader = reinterpret_cast<const Shader*>(shaderData + shaderContainer->shaderOffset); | ||||||
| 
 | 
 | ||||||
|     out += "#ifndef __spirv__\n"; |     println("struct {}", isPixelShader ? "Interpolators" : "VertexShaderInput"); | ||||||
| 
 |     out += "{\n"; | ||||||
|     if (isPixelShader) |  | ||||||
|         out += "[shader(\"pixel\")]\n"; |  | ||||||
|     else |  | ||||||
|         out += "[shader(\"vertex\")]\n"; |  | ||||||
| 
 |  | ||||||
|     out += "#endif\n"; |  | ||||||
| 
 |  | ||||||
|     out += "void main(\n"; |  | ||||||
| 
 | 
 | ||||||
|     if (isPixelShader) |     if (isPixelShader) | ||||||
|     { |     { | ||||||
|         out += "\tin float4 iPos : SV_Position,\n"; |         out += "#if __air__\n"; | ||||||
| 
 | 
 | ||||||
|         for (auto& [usage, usageIndex] : INTERPOLATORS) |         for (auto& [usage, usageIndex] : INTERPOLATORS) | ||||||
|             println("\tin float4 i{0}{1} : {2}{1},", USAGE_VARIABLES[uint32_t(usage)], usageIndex, USAGE_SEMANTICS[uint32_t(usage)]); |             println("\tfloat4 i{}{};", USAGE_VARIABLES[uint32_t(usage)], usageIndex); | ||||||
| 
 | 
 | ||||||
|         out += "#ifdef __spirv__\n"; |  | ||||||
|         out += "\tin bool iFace : SV_IsFrontFace\n"; |  | ||||||
|         out += "#else\n"; |         out += "#else\n"; | ||||||
|         out += "\tin uint iFace : SV_IsFrontFace\n"; |  | ||||||
|         out += "#endif\n"; |  | ||||||
| 
 | 
 | ||||||
|         auto pixelShader = reinterpret_cast<const PixelShader*>(shader); |         for (auto& [usage, usageIndex] : INTERPOLATORS) | ||||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR0) |             println("\tfloat4 i{0}{1} : {2}{1};", USAGE_VARIABLES[uint32_t(usage)], usageIndex, USAGE_SEMANTICS[uint32_t(usage)]); | ||||||
|             out += ",\n\tout float4 oC0 : SV_Target0"; | 
 | ||||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR1) |         out += "#endif\n"; | ||||||
|             out += ",\n\tout float4 oC1 : SV_Target1"; |  | ||||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR2) |  | ||||||
|             out += ",\n\tout float4 oC2 : SV_Target2"; |  | ||||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR3) |  | ||||||
|             out += ",\n\tout float4 oC3 : SV_Target3"; |  | ||||||
|         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_DEPTH) |  | ||||||
|             out += ",\n\tout float oDepth : SV_Depth"; |  | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         auto vertexShader = reinterpret_cast<const VertexShader*>(shader); |         auto vertexShader = reinterpret_cast<const VertexShader*>(shader); | ||||||
|  | 
 | ||||||
|  |         out += "#if __air__\n"; | ||||||
|  | 
 | ||||||
|         for (uint32_t i = 0; i < vertexShader->vertexElementCount; i++) |         for (uint32_t i = 0; i < vertexShader->vertexElementCount; i++) | ||||||
|         { |         { | ||||||
|             union |             union | ||||||
|  | @ -1314,13 +1423,52 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
| 
 | 
 | ||||||
|             const char* usageType = USAGE_TYPES[uint32_t(vertexElement.usage)]; |             const char* usageType = USAGE_TYPES[uint32_t(vertexElement.usage)]; | ||||||
| 
 | 
 | ||||||
|         #ifdef UNLEASHED_RECOMP | #ifdef UNLEASHED_RECOMP | ||||||
|             if ((vertexElement.usage == DeclUsage::TexCoord && vertexElement.usageIndex == 2 && isMetaInstancer) || |             if ((vertexElement.usage == DeclUsage::TexCoord && vertexElement.usageIndex == 2 && isMetaInstancer) || | ||||||
|                 (vertexElement.usage == DeclUsage::Position && vertexElement.usageIndex == 1)) |                 (vertexElement.usage == DeclUsage::Position && vertexElement.usageIndex == 1)) | ||||||
|             { |             { | ||||||
|                 usageType = "uint4"; |                 usageType = "uint4"; | ||||||
|             } |             } | ||||||
|         #endif | #endif | ||||||
|  | 
 | ||||||
|  |             out += '\t'; | ||||||
|  | 
 | ||||||
|  |             print("{0} i{1}{2}", usageType, USAGE_VARIABLES[uint32_t(vertexElement.usage)], | ||||||
|  |                 uint32_t(vertexElement.usageIndex)); | ||||||
|  | 
 | ||||||
|  |             for (auto& usageLocation : USAGE_LOCATIONS) | ||||||
|  |             { | ||||||
|  |                 if (usageLocation.usage == vertexElement.usage && usageLocation.usageIndex == vertexElement.usageIndex) | ||||||
|  |                 { | ||||||
|  |                     println(" [[attribute({})]];", usageLocation.location); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             vertexElements.emplace(uint32_t(vertexElement.address), vertexElement); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         out += "#else\n"; | ||||||
|  | 
 | ||||||
|  |         for (uint32_t i = 0; i < vertexShader->vertexElementCount; i++) | ||||||
|  |         { | ||||||
|  |             union | ||||||
|  |             { | ||||||
|  |                 VertexElement vertexElement; | ||||||
|  |                 uint32_t value; | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             value = vertexShader->vertexElementsAndInterpolators[vertexShader->field18 + i]; | ||||||
|  | 
 | ||||||
|  |             const char* usageType = USAGE_TYPES[uint32_t(vertexElement.usage)]; | ||||||
|  | 
 | ||||||
|  | #ifdef UNLEASHED_RECOMP | ||||||
|  |             if ((vertexElement.usage == DeclUsage::TexCoord && vertexElement.usageIndex == 2 && isMetaInstancer) || | ||||||
|  |                 (vertexElement.usage == DeclUsage::Position && vertexElement.usageIndex == 1)) | ||||||
|  |             { | ||||||
|  |                 usageType = "uint4"; | ||||||
|  |             } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|             out += '\t'; |             out += '\t'; | ||||||
| 
 | 
 | ||||||
|  | @ -1333,40 +1481,162 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             println("in {0} i{1}{2} : {3}{2},", usageType, USAGE_VARIABLES[uint32_t(vertexElement.usage)], |             println("{0} i{1}{2} : {3}{2};", usageType, USAGE_VARIABLES[uint32_t(vertexElement.usage)], | ||||||
|                 uint32_t(vertexElement.usageIndex), USAGE_SEMANTICS[uint32_t(vertexElement.usage)]); |                 uint32_t(vertexElement.usageIndex), USAGE_SEMANTICS[uint32_t(vertexElement.usage)]); | ||||||
| 
 |  | ||||||
|             vertexElements.emplace(uint32_t(vertexElement.address), vertexElement); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         out += "#endif\n"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     out += "};\n"; | ||||||
|  | 
 | ||||||
|  |     println("struct {}", isPixelShader ? "PixelShaderOutput" : "Interpolators"); | ||||||
|  |     out += "{\n"; | ||||||
|  | 
 | ||||||
|  |     if (isPixelShader) | ||||||
|  |     { | ||||||
|  |         out += "#if __air__\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 += "#else\n"; | ||||||
|  | 
 | ||||||
|  |         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR0) | ||||||
|  |             out += "\tfloat4 oC0 : SV_Target0;\n"; | ||||||
|  |         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR1) | ||||||
|  |             out += "\tfloat4 oC1 : SV_Target1;\n"; | ||||||
|  |         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR2) | ||||||
|  |             out += "\tfloat4 oC2 : SV_Target2;\n"; | ||||||
|  |         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR3) | ||||||
|  |             out += "\tfloat4 oC3 : SV_Target3;\n"; | ||||||
|  |         if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_DEPTH) | ||||||
|  |             out += "\tfloat oDepth : SV_Depth;\n"; | ||||||
|  | 
 | ||||||
|  |         out += "#endif\n"; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         out += "#if __air__\n"; | ||||||
|  | 
 | ||||||
|  |         out += "\tfloat4 oPos [[position]];\n"; | ||||||
|  | 
 | ||||||
|  |         for (auto& [usage, usageIndex] : INTERPOLATORS) | ||||||
|  |             print("\tfloat4 o{0}{1};\n", USAGE_VARIABLES[uint32_t(usage)], usageIndex); | ||||||
|  | 
 | ||||||
|  |         out += "#else\n"; | ||||||
|  | 
 | ||||||
|  |         out += "\tfloat4 oPos : SV_Position;\n"; | ||||||
|  | 
 | ||||||
|  |         for (auto& [usage, usageIndex] : INTERPOLATORS) | ||||||
|  |             print("\tfloat4 o{0}{1} : {2}{1};\n", USAGE_VARIABLES[uint32_t(usage)], usageIndex, USAGE_SEMANTICS[uint32_t(usage)]); | ||||||
|  | 
 | ||||||
|  |         out += "#endif\n"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     out += "};\n"; | ||||||
|  | 
 | ||||||
|  |     out += "#ifdef __air__\n"; | ||||||
|  | 
 | ||||||
|  |     if (isPixelShader) | ||||||
|  |         out += "[[fragment]]\n"; | ||||||
|  |     else | ||||||
|  |         out += "[[vertex]]\n"; | ||||||
|  | 
 | ||||||
|  |     out += "#elifndef __spirv__\n"; | ||||||
|  | 
 | ||||||
|  |     if (isPixelShader) | ||||||
|  |         out += "[shader(\"pixel\")]\n"; | ||||||
|  |     else | ||||||
|  |         out += "[shader(\"vertex\")]\n"; | ||||||
|  | 
 | ||||||
|  |     out += "#endif\n"; | ||||||
|  | 
 | ||||||
|  |     println("{} shaderMain(", isPixelShader ? "PixelShaderOutput" : "Interpolators"); | ||||||
|  | 
 | ||||||
|  |     if (isPixelShader) | ||||||
|  |     { | ||||||
|  |         out += "#ifdef __air__\n"; | ||||||
|  | 
 | ||||||
|  |         out += "\tInterpolators input [[stage_in]],\n"; | ||||||
|  |         out += "\tfloat4 iPos [[position]],\n"; | ||||||
|  |         out += "\tbool iFace [[front_facing]],\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(8)]]\n"; | ||||||
|  | 
 | ||||||
|  |         out += "#else\n"; | ||||||
|  | 
 | ||||||
|  |         out += "\tInterpolators input,\n"; | ||||||
|  |         out += "\tin float4 iPos : SV_Position,\n"; | ||||||
|  | 
 | ||||||
|  |         out += "#ifdef __spirv__\n"; | ||||||
|  |         out += "\tin bool iFace : SV_IsFrontFace\n"; | ||||||
|  |         out += "#else\n"; | ||||||
|  |         out += "\tin uint iFace : SV_IsFrontFace\n"; | ||||||
|  |         out += "#endif\n"; | ||||||
|  | 
 | ||||||
|  |         out += "\n#endif\n"; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         out += "#ifdef __air__\n"; | ||||||
|  |         out += "\tconstant PushConstants& g_PushConstants [[buffer(8)]],\n"; | ||||||
|  |         out += "\tVertexShaderInput input [[stage_in]]\n"; | ||||||
|  |         out += "#else\n"; | ||||||
|  |         out += "\tVertexShaderInput input\n"; | ||||||
|  |         out += "#endif\n"; | ||||||
|  | 
 | ||||||
|     #ifdef UNLEASHED_RECOMP |     #ifdef UNLEASHED_RECOMP | ||||||
|         if (hasIndexCount) |         if (hasIndexCount) | ||||||
|         { |         { | ||||||
|  |             out += "\t,\n"; | ||||||
|  |             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 iVertexId : SV_VertexID,\n"; | ||||||
|             out += "\tin uint iInstanceId : SV_InstanceID,\n"; |             out += "\tin uint iInstanceId : SV_InstanceID\n"; | ||||||
|  |             out += "#endif\n"; | ||||||
|         } |         } | ||||||
|     #endif |     #endif | ||||||
| 
 |  | ||||||
|         out += "\tout float4 oPos : SV_Position"; |  | ||||||
| 
 |  | ||||||
|         for (auto& [usage, usageIndex] : INTERPOLATORS) |  | ||||||
|             print(",\n\tout float4 o{0}{1} : {2}{1}", USAGE_VARIABLES[uint32_t(usage)], usageIndex, USAGE_SEMANTICS[uint32_t(usage)]); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     out += ")\n"; |     out += ")\n"; | ||||||
|     out += "{\n"; |     out += "{\n"; | ||||||
| 
 | 
 | ||||||
| #ifdef UNLEASHED_RECOMP | #ifdef UNLEASHED_RECOMP | ||||||
|  | 
 | ||||||
|  |     std::string outputName = isPixelShader ? "PixelShaderOutput" : "Interpolators"; | ||||||
|  | 
 | ||||||
|  |     out += "#ifdef __air__\n"; | ||||||
|  |     println("\t{0} output = {0}{{}};", outputName); | ||||||
|  |     out += "#else\n"; | ||||||
|  |     println("\t{0} output = ({0})0;", outputName); | ||||||
|  |     out += "#endif\n"; | ||||||
|  | 
 | ||||||
|     if (hasMtxProjection) |     if (hasMtxProjection) | ||||||
|     { |     { | ||||||
|         specConstantsMask |= SPEC_CONSTANT_REVERSE_Z; |         specConstantsMask |= SPEC_CONSTANT_REVERSE_Z; | ||||||
| 
 | 
 | ||||||
|         out += "\toPos = 0.0;\n"; |         out += "\toutput.oPos = 0.0;\n"; | ||||||
| 
 | 
 | ||||||
|         out += "\tfloat4x4 mtxProjection = float4x4(g_MtxProjection(0), g_MtxProjection(1), g_MtxProjection(2), g_MtxProjection(3));\n"; |         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 += "\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"; |         out += "\t{\n"; | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|  | @ -1381,8 +1651,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); |             auto value = reinterpret_cast<const be<uint32_t>*>(shaderData + shaderContainer->virtualSize + definition->physicalOffset); | ||||||
|             for (uint16_t i = 0; i < (definition->count + 3) / 4; i++) |             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}));", |                 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()); |                     definition->registerIndex + i - (isPixelShader ? 256 : 0), value[0].get(), value[1].get(), value[2].get(), value[3].get()); | ||||||
|  |                 println("#endif"); | ||||||
| 
 | 
 | ||||||
|                 value += 4; |                 value += 4; | ||||||
|             } |             } | ||||||
|  | @ -1433,14 +1708,14 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|         if (isPixelShader) |         if (isPixelShader) | ||||||
|         { |         { | ||||||
|             value = reinterpret_cast<const PixelShader*>(shader)->interpolators[i]; |             value = reinterpret_cast<const PixelShader*>(shader)->interpolators[i]; | ||||||
|             println("\tfloat4 r{} = i{}{};", uint32_t(interpolator.reg), USAGE_VARIABLES[uint32_t(interpolator.usage)], uint32_t(interpolator.usageIndex)); |             println("\tfloat4 r{} = input.i{}{};", uint32_t(interpolator.reg), USAGE_VARIABLES[uint32_t(interpolator.usage)], uint32_t(interpolator.usageIndex)); | ||||||
|             printedRegisters[interpolator.reg] = true; |             printedRegisters[interpolator.reg] = true; | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             auto vertexShader = reinterpret_cast<const VertexShader*>(shader); |             auto vertexShader = reinterpret_cast<const VertexShader*>(shader); | ||||||
|             value = vertexShader->vertexElementsAndInterpolators[vertexShader->field18 + vertexShader->vertexElementCount + i]; |             value = vertexShader->vertexElementsAndInterpolators[vertexShader->field18 + vertexShader->vertexElementCount + i]; | ||||||
|             interpolators.emplace(i, fmt::format("o{}{}", USAGE_VARIABLES[uint32_t(interpolator.usage)], uint32_t(interpolator.usageIndex))); |             interpolators.emplace(i, fmt::format("output.o{}{}", USAGE_VARIABLES[uint32_t(interpolator.usage)], uint32_t(interpolator.usageIndex))); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1448,11 +1723,11 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|     { |     { | ||||||
|     #ifdef UNLEASHED_RECOMP |     #ifdef UNLEASHED_RECOMP | ||||||
|         if (!hasMtxProjection) |         if (!hasMtxProjection) | ||||||
|             out += "\toPos = 0.0;\n"; |             out += "\toutput.oPos = 0.0;\n"; | ||||||
|     #endif |     #endif | ||||||
| 
 | 
 | ||||||
|         for (auto& [usage, usageIndex] : INTERPOLATORS) |         for (auto& [usage, usageIndex] : INTERPOLATORS) | ||||||
|             println("\to{}{} = 0.0;", USAGE_VARIABLES[uint32_t(usage)], usageIndex); |             println("\toutput.o{}{} = 0.0;", USAGE_VARIABLES[uint32_t(usage)], usageIndex); | ||||||
| 
 | 
 | ||||||
|         out += "\n"; |         out += "\n"; | ||||||
|     } |     } | ||||||
|  | @ -1488,7 +1763,11 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
| #ifdef UNLEASHED_RECOMP | #ifdef UNLEASHED_RECOMP | ||||||
|         out += "\tfloat2 pixelCoord = 0.0;\n"; |         out += "\tfloat2 pixelCoord = 0.0;\n"; | ||||||
| #endif | #endif | ||||||
|  |         out += "#ifdef __air__\n"; | ||||||
|  |         out += "\tCubeMapData cubeMapData = CubeMapData{};\n"; | ||||||
|  |         out += "#else\n"; | ||||||
|         out += "\tCubeMapData cubeMapData = (CubeMapData)0;\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); |     const be<uint32_t>* code = reinterpret_cast<const be<uint32_t>*>(shaderData + shaderContainer->virtualSize + shader->physicalOffset); | ||||||
|  | @ -1646,7 +1925,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|                 { |                 { | ||||||
|                     indent(); |                     indent(); | ||||||
|                 #ifdef UNLEASHED_RECOMP |                 #ifdef UNLEASHED_RECOMP | ||||||
|                     print("[unroll] "); |                     print("UNROLL "); | ||||||
|                 #endif |                 #endif | ||||||
|                     println("for (aL = 0; aL < i{}.x; aL++)", uint32_t(cfInstr.loopStart.loopId)); |                     println("for (aL = 0; aL < i{}.x; aL++)", uint32_t(cfInstr.loopStart.loopId)); | ||||||
|                     indent(); |                     indent(); | ||||||
|  | @ -1754,27 +2033,27 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|                             specConstantsMask |= SPEC_CONSTANT_BICUBIC_GI_FILTER; |                             specConstantsMask |= SPEC_CONSTANT_BICUBIC_GI_FILTER; | ||||||
| 
 | 
 | ||||||
|                             indent(); |                             indent(); | ||||||
|                             out += "if (g_SpecConstants() & SPEC_CONSTANT_BICUBIC_GI_FILTER)"; |                             out += "if (g_SpecConstants() & SPEC_CONSTANT_BICUBIC_GI_FILTER)\n"; | ||||||
|                             indent(); |                             indent(); | ||||||
|                             out += '{'; |                             out += "{\n"; | ||||||
| 
 | 
 | ||||||
|                             ++indentation; |                             ++indentation; | ||||||
|                             recompile(textureFetch, true); |                             recompile(textureFetch, true); | ||||||
|                             --indentation; |                             --indentation; | ||||||
| 
 | 
 | ||||||
|                             indent(); |                             indent(); | ||||||
|                             out += "}"; |                             out += "}\n"; | ||||||
|                             indent(); |                             indent(); | ||||||
|                             out += "else"; |                             out += "else\n"; | ||||||
|                             indent(); |                             indent(); | ||||||
|                             out += '{'; |                             out += "{\n"; | ||||||
| 
 | 
 | ||||||
|                             ++indentation; |                             ++indentation; | ||||||
|                             recompile(textureFetch, false); |                             recompile(textureFetch, false); | ||||||
|                             --indentation; |                             --indentation; | ||||||
| 
 | 
 | ||||||
|                             indent(); |                             indent(); | ||||||
|                             out += '}'; |                             out += "}\n"; | ||||||
|                         } |                         } | ||||||
|                         else |                         else | ||||||
|                     #endif |                     #endif | ||||||
|  | @ -1799,31 +2078,31 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|                     specConstantsMask |= SPEC_CONSTANT_ALPHA_TEST; |                     specConstantsMask |= SPEC_CONSTANT_ALPHA_TEST; | ||||||
| 
 | 
 | ||||||
|                     indent(); |                     indent(); | ||||||
|                     out += "[branch] if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TEST)"; |                     out += "BRANCH if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TEST)\n"; | ||||||
|                     indent(); |                     indent(); | ||||||
|                     out += '{'; |                     out += "{\n"; | ||||||
| 
 | 
 | ||||||
|                     indent(); |                     indent(); | ||||||
|                     out += "\tclip(oC0.w - g_AlphaThreshold);\n"; |                     out += "\tclip(output.oC0.w - g_AlphaThreshold);\n"; | ||||||
| 
 | 
 | ||||||
|                     indent(); |                     indent(); | ||||||
|                     out += "}"; |                     out += "}\n"; | ||||||
| 
 | 
 | ||||||
|                 #ifdef UNLEASHED_RECOMP |                 #ifdef UNLEASHED_RECOMP | ||||||
|                     specConstantsMask |= SPEC_CONSTANT_ALPHA_TO_COVERAGE; |                     specConstantsMask |= SPEC_CONSTANT_ALPHA_TO_COVERAGE; | ||||||
| 
 | 
 | ||||||
|                     indent(); |                     indent(); | ||||||
|                     out += "else if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TO_COVERAGE)"; |                     out += "else if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TO_COVERAGE)\n"; | ||||||
|                     indent(); |                     indent(); | ||||||
|                     out += '{'; |                     out += "{\n"; | ||||||
| 
 | 
 | ||||||
|                     indent(); |                     indent(); | ||||||
|                     out += "\toC0.w *= 1.0 + computeMipLevel(pixelCoord) * 0.25;\n"; |                     out += "\toutput.oC0.w *= 1.0 + computeMipLevel(pixelCoord) * 0.25;\n"; | ||||||
|                     indent(); |                     indent(); | ||||||
|                     out += "\toC0.w = 0.5 + (oC0.w - g_AlphaThreshold) / max(fwidth(oC0.w), 1e-6);\n"; |                     out += "\toutput.oC0.w = 0.5 + (output.oC0.w - g_AlphaThreshold) / max(fwidth(output.oC0.w), 1e-6);\n"; | ||||||
| 
 | 
 | ||||||
|                     indent(); |                     indent(); | ||||||
|                     out += '}'; |                     out += "}\n"; | ||||||
|                 #endif |                 #endif | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | @ -1838,7 +2117,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|                     else |                     else | ||||||
|                 #endif |                 #endif | ||||||
|                     { |                     { | ||||||
|                         out += "return;\n"; |                         out += "return output;\n"; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|  | @ -1872,5 +2151,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi | ||||||
|         out += "\t}\n"; |         out += "\t}\n"; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  |     out += "\treturn output;\n"; | ||||||
|  | 
 | ||||||
|     out += "}"; |     out += "}"; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ struct ShaderRecompiler : StringBuffer | ||||||
|             out += '\t'; |             out += '\t'; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void printDstSwizzle(uint32_t dstSwizzle, bool operand); |     uint32_t printDstSwizzle(uint32_t dstSwizzle, bool operand); | ||||||
|     void printDstSwizzle01(uint32_t dstRegister, uint32_t dstSwizzle); |     void printDstSwizzle01(uint32_t dstRegister, uint32_t dstSwizzle); | ||||||
| 
 | 
 | ||||||
|     void recompile(const VertexFetchInstruction& instr, uint32_t address); |     void recompile(const VertexFetchInstruction& instr, uint32_t address); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Isaac Marovitz
						Isaac Marovitz