Skip to content

Commit a0e2d16

Browse files
committed
MSL Shader Generation
Signed-off-by: Isaac Marovitz <[email protected]>
1 parent b15b5e4 commit a0e2d16

File tree

5 files changed

+607
-95
lines changed

5 files changed

+607
-95
lines changed

XenosRecomp/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ if (WIN32)
44
option(XENOS_RECOMP_DXIL "Generate DXIL shader cache" ON)
55
endif()
66

7+
if (APPLE)
8+
option(XENOS_RECOMP_AIR "Generate Metal AIR shader cache" ON)
9+
endif()
10+
711
set(SMOLV_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/smol-v/source")
812

913
add_executable(XenosRecomp
@@ -51,3 +55,7 @@ if (XENOS_RECOMP_DXIL)
5155
target_compile_definitions(XenosRecomp PRIVATE XENOS_RECOMP_DXIL)
5256
target_link_libraries(XenosRecomp PRIVATE Microsoft::DXIL)
5357
endif()
58+
59+
if (XENOS_RECOMP_AIR)
60+
target_compile_definitions(XenosRecomp PRIVATE XENOS_RECOMP_AIR)
61+
endif()

XenosRecomp/dxc_compiler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ IDxcBlob* DxcCompiler::compile(const std::string& shaderSource, bool compilePixe
3434
target = L"-T vs_6_0";
3535
}
3636

37+
if (!compileLibrary)
38+
{
39+
args[argCount++] = L"-E shaderMain";
40+
}
41+
3742
args[argCount++] = target;
3843
args[argCount++] = L"-HV 2021";
3944
args[argCount++] = L"-all-resources-bound";

XenosRecomp/shader_common.h

Lines changed: 225 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
#define SPEC_CONSTANT_REVERSE_Z (1 << 4)
1111
#endif
1212

13-
#if !defined(__cplusplus) || defined(__INTELLISENSE__)
13+
#if defined(__air__) || !defined(__cplusplus) || defined(__INTELLISENSE__)
1414

15+
#ifndef __air__
1516
#define FLT_MIN asfloat(0xff7fffff)
1617
#define FLT_MAX asfloat(0x7f7fffff)
18+
#endif
1719

1820
#ifdef __spirv__
1921

@@ -34,6 +36,30 @@ struct PushConstants
3436

3537
#define g_SpecConstants() g_SpecConstants
3638

39+
#elif __air__
40+
41+
#include <metal_stdlib>
42+
43+
using namespace metal;
44+
45+
constant uint G_SPEC_CONSTANT [[function_constant(0)]];
46+
47+
uint g_SpecConstants()
48+
{
49+
return G_SPEC_CONSTANT;
50+
}
51+
52+
struct PushConstants
53+
{
54+
ulong VertexShaderConstants;
55+
ulong PixelShaderConstants;
56+
ulong SharedConstants;
57+
};
58+
59+
#define g_Booleans (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 256)))
60+
#define g_SwappedTexcoords (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 260)))
61+
#define g_AlphaThreshold (*(reinterpret_cast<device float*>(g_PushConstants.SharedConstants + 264)))
62+
3763
#else
3864

3965
#define DEFINE_SHARED_CONSTANTS() \
@@ -45,6 +71,56 @@ uint g_SpecConstants();
4571

4672
#endif
4773

74+
#ifdef __air__
75+
76+
struct Texture2DDescriptorHeap
77+
{
78+
array<texture2d<float>, 1> g [[id(0)]];
79+
};
80+
81+
struct Texture3DDescriptorHeap
82+
{
83+
array<texture3d<float>, 1> g [[id(0)]];
84+
};
85+
86+
struct TextureCubeDescriptorHeap
87+
{
88+
array<texturecube<float>, 1> g [[id(0)]];
89+
};
90+
91+
struct SamplerDescriptorHeap
92+
{
93+
array<sampler, 1> g [[id(0)]];
94+
};
95+
96+
uint2 getTexture2DDimensions(texture2d<float> texture)
97+
{
98+
return uint2(texture.get_width(), texture.get_height());
99+
}
100+
101+
float4 tfetch2D(constant Texture2DDescriptorHeap& textureHeap,
102+
constant SamplerDescriptorHeap& samplerHeap,
103+
uint resourceDescriptorIndex,
104+
uint samplerDescriptorIndex,
105+
float2 texCoord, float2 offset)
106+
{
107+
texture2d<float> texture = textureHeap.g[resourceDescriptorIndex];
108+
sampler sampler = samplerHeap.g[samplerDescriptorIndex];
109+
return texture.sample(sampler, texCoord + offset / (float2)getTexture2DDimensions(texture));
110+
}
111+
112+
float2 getWeights2D(constant Texture2DDescriptorHeap& textureHeap,
113+
constant SamplerDescriptorHeap& samplerHeap,
114+
uint resourceDescriptorIndex,
115+
uint samplerDescriptorIndex,
116+
float2 texCoord, float2 offset)
117+
{
118+
texture2d<float> texture = textureHeap.g[resourceDescriptorIndex];
119+
return select(fract(texCoord * (float2)getTexture2DDimensions(texture) + offset - 0.5), 0.0, isnan(texCoord));
120+
}
121+
122+
#else
123+
48124
Texture2D<float4> g_Texture2DDescriptorHeap[] : register(t0, space0);
49125
Texture3D<float4> g_Texture3DDescriptorHeap[] : register(t0, space1);
50126
TextureCube<float4> g_TextureCubeDescriptorHeap[] : register(t0, space2);
@@ -69,6 +145,46 @@ float2 getWeights2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, f
69145
return select(isnan(texCoord), 0.0, frac(texCoord * getTexture2DDimensions(texture) + offset - 0.5));
70146
}
71147

148+
#endif
149+
150+
#ifdef __air__
151+
#define selectWrapper(a, b, c) select(c, b, a)
152+
#else
153+
#define selectWrapper(a, b, c) select(a, b, c)
154+
#endif
155+
156+
#ifdef __air__
157+
#define frac(X) fract(X)
158+
159+
template<typename T>
160+
void clip(T a)
161+
{
162+
if (a < 0.0) {
163+
discard_fragment();
164+
}
165+
}
166+
167+
template<typename T>
168+
float rcp(T a)
169+
{
170+
return 1.0 / a;
171+
}
172+
173+
template<typename T>
174+
float4x4 mul(T a, T b)
175+
{
176+
return a * b;
177+
}
178+
#endif
179+
180+
#ifdef __air__
181+
#define UNROLL
182+
#define BRANCH
183+
#else
184+
#define UNROLL [unroll]
185+
#define BRANCH [branch]
186+
#endif
187+
72188
float w0(float a)
73189
{
74190
return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f);
@@ -109,6 +225,74 @@ float h1(float a)
109225
return 1.0f + w3(a) / (w2(a) + w3(a)) + 0.5f;
110226
}
111227

228+
struct CubeMapData
229+
{
230+
float3 cubeMapDirections[2];
231+
uint cubeMapIndex;
232+
};
233+
234+
#ifdef __air__
235+
236+
float4 tfetch2DBicubic(constant Texture2DDescriptorHeap& textureHeap,
237+
constant SamplerDescriptorHeap& samplerHeap,
238+
uint resourceDescriptorIndex,
239+
uint samplerDescriptorIndex,
240+
float2 texCoord, float2 offset)
241+
{
242+
texture2d<float> texture = textureHeap.g[resourceDescriptorIndex];
243+
sampler sampler = samplerHeap.g[samplerDescriptorIndex];
244+
uint2 dimensions = getTexture2DDimensions(texture);
245+
246+
float x = texCoord.x * dimensions.x + offset.x;
247+
float y = texCoord.y * dimensions.y + offset.y;
248+
249+
x -= 0.5f;
250+
y -= 0.5f;
251+
float px = floor(x);
252+
float py = floor(y);
253+
float fx = x - px;
254+
float fy = y - py;
255+
256+
float g0x = g0(fx);
257+
float g1x = g1(fx);
258+
float h0x = h0(fx);
259+
float h1x = h1(fx);
260+
float h0y = h0(fy);
261+
float h1y = h1(fy);
262+
263+
float4 r =
264+
g0(fy) * (g0x * texture.sample(sampler, float2(px + h0x, py + h0y) / float2(dimensions)) +
265+
g1x * texture.sample(sampler, float2(px + h1x, py + h0y) / float2(dimensions))) +
266+
g1(fy) * (g0x * texture.sample(sampler, float2(px + h0x, py + h1y) / float2(dimensions)) +
267+
g1x * texture.sample(sampler, float2(px + h1x, py + h1y) / float2(dimensions)));
268+
269+
return r;
270+
}
271+
272+
float4 tfetch3D(constant Texture3DDescriptorHeap& textureHeap,
273+
constant SamplerDescriptorHeap& samplerHeap,
274+
uint resourceDescriptorIndex,
275+
uint samplerDescriptorIndex,
276+
float3 texCoord)
277+
{
278+
texture3d<float> texture = textureHeap.g[resourceDescriptorIndex];
279+
sampler sampler = samplerHeap.g[samplerDescriptorIndex];
280+
return texture.sample(sampler, texCoord);
281+
}
282+
283+
float4 tfetchCube(constant TextureCubeDescriptorHeap& textureHeap,
284+
constant SamplerDescriptorHeap& samplerHeap,
285+
uint resourceDescriptorIndex,
286+
uint samplerDescriptorIndex,
287+
float3 texCoord, thread CubeMapData* cubeMapData)
288+
{
289+
texturecube<float> texture = textureHeap.g[resourceDescriptorIndex];
290+
sampler sampler = samplerHeap.g[samplerDescriptorIndex];
291+
return texture.sample(sampler, cubeMapData->cubeMapDirections[(uint)texCoord.z]);
292+
}
293+
294+
#else
295+
112296
float4 tfetch2DBicubic(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset)
113297
{
114298
Texture2D<float4> texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex];
@@ -146,17 +330,13 @@ float4 tfetch3D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float
146330
return g_Texture3DDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord);
147331
}
148332

149-
struct CubeMapData
150-
{
151-
float3 cubeMapDirections[2];
152-
uint cubeMapIndex;
153-
};
154-
155333
float4 tfetchCube(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float3 texCoord, inout CubeMapData cubeMapData)
156334
{
157335
return g_TextureCubeDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], cubeMapData.cubeMapDirections[texCoord.z]);
158336
}
159337

338+
#endif
339+
160340
float4 tfetchR11G11B10(uint4 value)
161341
{
162342
if (g_SpecConstants() & SPEC_CONSTANT_R11G11B10_NORMAL)
@@ -169,7 +349,11 @@ float4 tfetchR11G11B10(uint4 value)
169349
}
170350
else
171351
{
352+
#ifdef __air__
353+
return as_type<float4>(value);
354+
#else
172355
return asfloat(value);
356+
#endif
173357
}
174358
}
175359

@@ -178,6 +362,19 @@ float4 tfetchTexcoord(uint swappedTexcoords, float4 value, uint semanticIndex)
178362
return (swappedTexcoords & (1ull << semanticIndex)) != 0 ? value.yxwz : value;
179363
}
180364

365+
#ifdef __air__
366+
367+
float4 cube(float4 value, thread CubeMapData* cubeMapData)
368+
{
369+
uint index = cubeMapData->cubeMapIndex;
370+
cubeMapData->cubeMapDirections[index] = value.xyz;
371+
++cubeMapData->cubeMapIndex;
372+
373+
return float4(0.0, 0.0, 0.0, index);
374+
}
375+
376+
#else
377+
181378
float4 cube(float4 value, inout CubeMapData cubeMapData)
182379
{
183380
uint index = cubeMapData.cubeMapIndex;
@@ -187,6 +384,8 @@ float4 cube(float4 value, inout CubeMapData cubeMapData)
187384
return float4(0.0, 0.0, 0.0, index);
188385
}
189386

387+
#endif
388+
190389
float4 dst(float4 src0, float4 src1)
191390
{
192391
float4 dest;
@@ -202,15 +401,34 @@ float4 max4(float4 src0)
202401
return max(max(src0.x, src0.y), max(src0.z, src0.w));
203402
}
204403

404+
#ifdef __air__
405+
406+
float2 getPixelCoord(constant Texture2DDescriptorHeap& textureHeap,
407+
uint resourceDescriptorIndex,
408+
float2 texCoord)
409+
{
410+
texture2d<float> texture = textureHeap.g[resourceDescriptorIndex];
411+
return (float2)getTexture2DDimensions(texture) * texCoord;
412+
}
413+
414+
#else
415+
205416
float2 getPixelCoord(uint resourceDescriptorIndex, float2 texCoord)
206417
{
207418
return getTexture2DDimensions(g_Texture2DDescriptorHeap[resourceDescriptorIndex]) * texCoord;
208419
}
209420

421+
#endif
422+
210423
float computeMipLevel(float2 pixelCoord)
211424
{
425+
#ifdef __air__
426+
float2 dx = dfdx(pixelCoord);
427+
float2 dy = dfdy(pixelCoord);
428+
#else
212429
float2 dx = ddx(pixelCoord);
213430
float2 dy = ddy(pixelCoord);
431+
#endif
214432
float deltaMaxSqr = max(dot(dx, dx), dot(dy, dy));
215433
return max(0.0, 0.5 * log2(deltaMaxSqr));
216434
}

0 commit comments

Comments
 (0)