Compare commits

...

22 commits

Author SHA1 Message Date
Isaac Marovitz
5a81a69f9c
Merge 6c7c8fa87d into b15b5e4728 2025-03-21 18:39:45 +00:00
Isaac Marovitz
6c7c8fa87d
Initial vertex IO fixes
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-21 14:39:39 -04:00
Isaac Marovitz
790c8be91b
Fix UNROLL macro
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-21 14:33:22 -04:00
Isaac Marovitz
2d9e24c52f
Nvm fix mul properly
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-21 13:34:14 -04:00
Isaac Marovitz
9112665766
Fix MSL matrix mul
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-21 13:31:37 -04:00
Isaac Marovitz
995d2889d4
Fix missing newline
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-20 22:30:05 -04:00
Isaac Marovitz
f87e28fbcc
Main func signature
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-20 22:28:19 -04:00
Isaac Marovitz
347fee997c
tfetch and getPixelCoord signatures
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-20 22:24:42 -04:00
Isaac Marovitz
4c93ec4e43
Explicit cast vector register writes
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-20 21:43:32 -04:00
Isaac Marovitz
67467f459a
Changes
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-20 21:34:15 -04:00
Isaac Marovitz
4149b8458a
shader_common fixes
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-20 21:19:04 -04:00
Isaac Marovitz
6c88f0b31e
Defines cleanup
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 15:53:16 -04:00
Isaac Marovitz
c3b320e314
Fix cast
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 15:46:58 -04:00
Isaac Marovitz
58e4631dce
Cleanup
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 15:43:33 -04:00
Isaac Marovitz
6153094d1f
Cleanup
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 15:38:37 -04:00
Isaac Marovitz
f328cbbec8
Move around common MSL
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 15:20:25 -04:00
Isaac Marovitz
8a0c898a7d
EOF newline
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 14:47:22 -04:00
Isaac Marovitz
a223077258
More generator changes
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 14:46:39 -04:00
Isaac Marovitz
2efa88dbd4
Generator changes
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 14:37:39 -04:00
Isaac Marovitz
342a7224ee
MSL -> AIR
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 14:19:46 -04:00
Isaac Marovitz
ae64bcf8ea
XENOS_RECOMP_MSL option
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 14:12:53 -04:00
Isaac Marovitz
0de70f7458
MSL Shader Common
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
2025-03-16 14:08:36 -04:00
3 changed files with 415 additions and 33 deletions

View file

@ -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()

View file

@ -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));
}

View file

@ -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
}