Skip to content

Commit e851c0b

Browse files
committed
MSL Shader Generation
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
1 parent 421e3b3 commit e851c0b

5 files changed

Lines changed: 607 additions & 95 deletions

File tree

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

@@ -35,6 +37,30 @@ struct PushConstants
3537

3638
#define g_SpecConstants() g_SpecConstants
3739

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

4066
#define DEFINE_SHARED_CONSTANTS() \
@@ -47,6 +73,56 @@ uint g_SpecConstants();
4773

4874
#endif
4975

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

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

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

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

340+
#endif
341+
162342
float4 tfetchR11G11B10(uint4 value)
163343
{
164344
if (g_SpecConstants() & SPEC_CONSTANT_R11G11B10_NORMAL)
@@ -171,7 +351,11 @@ float4 tfetchR11G11B10(uint4 value)
171351
}
172352
else
173353
{
354+
#ifdef __air__
355+
return as_type<float4>(value);
356+
#else
174357
return asfloat(value);
358+
#endif
175359
}
176360
}
177361

@@ -180,6 +364,19 @@ float4 tfetchTexcoord(uint swappedTexcoords, float4 value, uint semanticIndex)
180364
return (swappedTexcoords & (1ull << semanticIndex)) != 0 ? value.yxwz : value;
181365
}
182366

367+
#ifdef __air__
368+
369+
float4 cube(float4 value, thread CubeMapData* cubeMapData)
370+
{
371+
uint index = cubeMapData->cubeMapIndex;
372+
cubeMapData->cubeMapDirections[index] = value.xyz;
373+
++cubeMapData->cubeMapIndex;
374+
375+
return float4(0.0, 0.0, 0.0, index);
376+
}
377+
378+
#else
379+
183380
float4 cube(float4 value, inout CubeMapData cubeMapData)
184381
{
185382
uint index = cubeMapData.cubeMapIndex;
@@ -189,6 +386,8 @@ float4 cube(float4 value, inout CubeMapData cubeMapData)
189386
return float4(0.0, 0.0, 0.0, index);
190387
}
191388

389+
#endif
390+
192391
float4 dst(float4 src0, float4 src1)
193392
{
194393
float4 dest;
@@ -204,15 +403,34 @@ float4 max4(float4 src0)
204403
return max(max(src0.x, src0.y), max(src0.z, src0.w));
205404
}
206405

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

423+
#endif
424+
212425
float computeMipLevel(float2 pixelCoord)
213426
{
427+
#ifdef __air__
428+
float2 dx = dfdx(pixelCoord);
429+
float2 dy = dfdy(pixelCoord);
430+
#else
214431
float2 dx = ddx(pixelCoord);
215432
float2 dy = ddy(pixelCoord);
433+
#endif
216434
float deltaMaxSqr = max(dot(dx, dx), dot(dy, dy));
217435
return max(0.0, 0.5 * log2(deltaMaxSqr));
218436
}

0 commit comments

Comments
 (0)