Skip to content

Commit e500729

Browse files
authored
Add GenSlang, SlangRenderer, and RenderSlang (AcademySoftwareFoundation#2548)
- Adds MaterialXGenSlang, matching GenGlsl as closely as possible. - The genslang `.mtlx` files were created by copying the genglsl files. - Various `mx_function.slang` files were created by copying `mx_function.glsl` files and doing the minimal required changes. - SlangShaderGenerator generates vertex and pixel shader, again to mimic the GenGlsl (and reuse as much of the existing Hw code). - Uniform defaults in the code are not supported by Slang, so SlangShaderGenerator generates custom user attributes, that the application needs to read and set. - This is the major compatibility issue that needs to be resolved. Another way would be a separate kernel call to move all uniforms into a struct, and have a separate kernel call to set the defaults. It would deviate from the existing Glsl code, and still wouldn't be completely self-contained shader. - Code is not using Strings, despite Slang supporting them. Can be added in the future, replacing the string-to-enum code. - It is configured as off by default. - Adds MaterialXRenderSlang, matching the `ShaderRenderer` interface. - Used exclusively for testing. - Uses `slang-rhi` library to abstract the specific graphics API, allowing to run identical code on D3D12 and Vulkan. - Mac and WebGPU are also supported by both Slang and slang-rhi, but haven't been tested on this codebase yet. - Like the MaterialXRenderMsl, the immediate (OpenGL) interface of `ShaderRenderer` doesn't really fit the modern graphics API, so not all interfaces are implemented. - `SlangRederer::initialize` takes `const char*` of the required device type. If none is provided, default one for the given architecture is chosen instead. - `MaterialXRenderSlang` is explicitly taken out of `install` targets, because `slang-rhi` is currently not ready for that workflow. - Adds `RenderSlang` that uses `MaterialXRenderSlang` to run tests. - Only uses the `Default` device type for now, i.e., `D3D12` on Windows and `Vulkan` on Linux.
1 parent facd77a commit e500729

52 files changed

Lines changed: 7278 additions & 8 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ option(MATERIALX_BUILD_GEN_GLSL "Build the GLSL shader generator back-end." ON)
4242
option(MATERIALX_BUILD_GEN_OSL "Build the OSL shader generator back-ends." ON)
4343
option(MATERIALX_BUILD_GEN_MDL "Build the MDL shader generator back-end." ON)
4444
option(MATERIALX_BUILD_GEN_MSL "Build the MSL shader generator back-end." ON)
45+
option(MATERIALX_BUILD_GEN_SLANG "Build the Slang shader generator back-end." ON)
4546
option(MATERIALX_BUILD_RENDER "Build the MaterialX Render modules." ON)
4647
option(MATERIALX_BUILD_RENDER_PLATFORMS "Build platform-specific render modules for each shader generator." ON)
4748
option(MATERIALX_BUILD_OIIO "Build OpenImageIO support for MaterialXRender." OFF)
@@ -86,6 +87,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "iOS" OR CMAKE_SYSTEM_NAME MATCHES "tvOS" OR CMAKE
8687
set(MATERIALX_BUILD_GEN_GLSL OFF)
8788
set(MATERIALX_BUILD_GEN_OSL OFF)
8889
set(MATERIALX_BUILD_GEN_MDL OFF)
90+
set(MATERIALX_BUILD_GEN_SLANG OFF)
8991
set(MATERIALX_BUILD_OSOS OFF)
9092
set(MATERIALX_BUILD_TESTS OFF)
9193
endif()
@@ -133,6 +135,9 @@ set(MATERIALX_OSL_BINARY_OSLC "" CACHE FILEPATH "Full path to the OSL compiler b
133135
set(MATERIALX_OSL_BINARY_TESTRENDER "" CACHE FILEPATH "Full path to the OSL test render binary.")
134136
set(MATERIALX_OSL_INCLUDE_PATH "" CACHE PATH "Full path to OSL shader includes (e.g. 'stdosl.h').")
135137

138+
# Helpers for Slang validation
139+
set(MATERIALX_SLANG_RHI_SOURCE_DIR "" CACHE PATH "Full path to the Slang RHI build directory.")
140+
136141
set(MATERIALX_PYTHON_FOLDER_NAME "python/MaterialX" CACHE INTERNAL "Folder name to user for installing the Python library.")
137142

138143
if(SKBUILD)
@@ -166,6 +171,7 @@ set(MATERIALX_LIBNAME_SUFFIX "" CACHE STRING "Specify a suffix to all libraries
166171

167172
mark_as_advanced(MATERIALX_BUILD_DOCS)
168173
mark_as_advanced(MATERIALX_BUILD_GEN_GLSL)
174+
mark_as_advanced(MATERIALX_BUILD_GEN_SLANG)
169175
mark_as_advanced(MATERIALX_BUILD_GEN_OSL)
170176
mark_as_advanced(MATERIALX_BUILD_GEN_MDL)
171177
mark_as_advanced(MATERIALX_BUILD_GEN_MSL)
@@ -205,6 +211,7 @@ mark_as_advanced(MATERIALX_BUILD_APPLE_FRAMEWORK)
205211
mark_as_advanced(MATERIALX_MDL_BINARY_MDLC)
206212
mark_as_advanced(MATERIALX_MDL_MODULE_PATHS)
207213
mark_as_advanced(MATERIALX_MDL_SDK_DIR)
214+
mark_as_advanced(MATERIALX_SLANG_RHI_SOURCE_DIR)
208215

209216
if (MATERIALX_BUILD_USE_CCACHE)
210217
# Setup CCache for C/C++ compilation
@@ -330,7 +337,7 @@ function(assign_source_group prefix)
330337
endfunction(assign_source_group)
331338

332339
function(mx_add_library MATERIALX_MODULE_NAME)
333-
set(options ADD_OBJECTIVE_C_CODE)
340+
set(options ADD_OBJECTIVE_C_CODE SKIP_INSTALL)
334341
set(oneValueArgs EXPORT_DEFINE)
335342
set(multiValueArgs
336343
SOURCE_FILES
@@ -415,7 +422,7 @@ function(mx_add_library MATERIALX_MODULE_NAME)
415422

416423
target_compile_definitions(${TARGET_NAME} PRIVATE "-D${args_EXPORT_DEFINE}")
417424

418-
if(NOT SKBUILD)
425+
if(NOT SKBUILD AND NOT args_SKIP_INSTALL)
419426
if(NOT MATERIALX_BUILD_MONOLITHIC)
420427
install(TARGETS ${MATERIALX_MODULE_NAME}
421428
EXPORT MaterialX
@@ -459,15 +466,18 @@ add_subdirectory(source/MaterialXFormat)
459466

460467
# Add shader generation subdirectories
461468
add_subdirectory(source/MaterialXGenShader)
462-
if(MATERIALX_BUILD_GEN_GLSL OR MATERIALX_BUILD_GEN_OSL OR MATERIALX_BUILD_GEN_MDL OR MATERIALX_BUILD_GEN_MSL)
463-
if(MATERIALX_BUILD_GEN_GLSL OR MATERIALX_BUILD_GEN_MSL)
469+
if(MATERIALX_BUILD_GEN_GLSL OR MATERIALX_BUILD_GEN_OSL OR MATERIALX_BUILD_GEN_MDL OR MATERIALX_BUILD_GEN_MSL OR MATERIALX_BUILD_GEN_SLANG)
470+
if(MATERIALX_BUILD_GEN_GLSL OR MATERIALX_BUILD_GEN_MSL OR MATERIALX_BUILD_GEN_SLANG)
464471
add_subdirectory(source/MaterialXGenHw)
465472
endif()
466-
467473
if (MATERIALX_BUILD_GEN_GLSL)
468474
add_definitions(-DMATERIALX_BUILD_GEN_GLSL)
469475
add_subdirectory(source/MaterialXGenGlsl)
470476
endif()
477+
if (MATERIALX_BUILD_GEN_SLANG)
478+
add_definitions(-DMATERIALX_BUILD_GEN_SLANG)
479+
add_subdirectory(source/MaterialXGenSlang)
480+
endif()
471481
if (MATERIALX_BUILD_GEN_OSL)
472482
add_definitions(-DMATERIALX_BUILD_GEN_OSL)
473483
add_subdirectory(source/MaterialXGenOsl)
@@ -505,6 +515,9 @@ if(MATERIALX_BUILD_RENDER)
505515
if(MATERIALX_BUILD_GEN_OSL)
506516
add_subdirectory(source/MaterialXRenderOsl)
507517
endif()
518+
if(MATERIALX_BUILD_GEN_SLANG AND MATERIALX_SLANG_RHI_SOURCE_DIR)
519+
add_subdirectory(source/MaterialXRenderSlang)
520+
endif()
508521
endif()
509522
if(MATERIALX_BUILD_VIEWER)
510523
add_subdirectory(source/MaterialXView)

documents/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ set(MATERIALX_DOXYGEN_SOURCE_FOLDERS
99
${PROJECT_SOURCE_DIR}/source/MaterialXGenShader/Nodes
1010
${PROJECT_SOURCE_DIR}/source/MaterialXGenGlsl
1111
${PROJECT_SOURCE_DIR}/source/MaterialXGenGlsl/Nodes
12+
${PROJECT_SOURCE_DIR}/source/MaterialXGenSlang
1213
${PROJECT_SOURCE_DIR}/source/MaterialXGenOsl
1314
${PROJECT_SOURCE_DIR}/source/MaterialXGenMdl
1415
${PROJECT_SOURCE_DIR}/source/MaterialXRender
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0"?>
2+
<materialx version="1.39">
3+
4+
<!-- <point_light> -->
5+
<implementation name="IM_point_light_genslang" nodedef="ND_point_light" file="mx_point_light.slang" function="mx_point_light" target="genslang" />
6+
7+
<!-- <directional_light> -->
8+
<implementation name="IM_directional_light_genslang" nodedef="ND_directional_light" file="mx_directional_light.slang" function="mx_directional_light" target="genslang" />
9+
10+
<!-- <spot_light> -->
11+
<implementation name="IM_spot_light_genslang" nodedef="ND_spot_light" file="mx_spot_light.slang" function="mx_spot_light" target="genslang" />
12+
13+
</materialx>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
void mx_directional_light(LightData light, float3 position, out lightshader result)
2+
{
3+
result.direction = -light.direction;
4+
result.intensity = light.color * light.intensity;
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
void mx_point_light(LightData light, float3 position, out lightshader result)
2+
{
3+
result.direction = light.position - position;
4+
float distance = length(result.direction) + M_FLOAT_EPS;
5+
float attenuation = pow(distance + 1.0, light.decay_rate + M_FLOAT_EPS);
6+
result.intensity = light.color * light.intensity / attenuation;
7+
result.direction /= distance;
8+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
void mx_spot_light(LightData light, float3 position, out lightshader result)
2+
{
3+
result.direction = light.position - position;
4+
float distance = length(result.direction) + M_FLOAT_EPS;
5+
float attenuation = pow(distance + 1.0, light.decay_rate + M_FLOAT_EPS);
6+
result.intensity = light.color * light.intensity / attenuation;
7+
result.direction /= distance;
8+
float low = min(light.inner_angle, light.outer_angle);
9+
float high = light.inner_angle;
10+
float cosDir = dot(result.direction, -light.direction);
11+
float spotAttenuation = smoothstep(low, high, cosDir);
12+
result.intensity *= spotAttenuation;
13+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0"?>
2+
<materialx version="1.39">
3+
<!--
4+
Copyright Contributors to the MaterialX Project
5+
SPDX-License-Identifier: Apache-2.0
6+
7+
Declarations for GLSL implementations of standard nodes included in the MaterialX specification.
8+
-->
9+
10+
<!-- ======================================================================== -->
11+
<!-- View-dependent nodes -->
12+
<!-- ======================================================================== -->
13+
14+
<!-- <viewdirection> -->
15+
<implementation name="IM_viewdirection_vector3_genslang" nodedef="ND_viewdirection_vector3" target="genslang" />
16+
17+
</materialx>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0"?>
2+
<materialx version="1.39">
3+
4+
<!-- <surface> -->
5+
<implementation name="IM_surface_genslang" nodedef="ND_surface" target="genslang" />
6+
7+
<!-- <light> -->
8+
<implementation name="IM_light_genslang" nodedef="ND_light" target="genslang" />
9+
10+
</materialx>
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#define M_FLOAT_EPS 1e-8
2+
3+
#define mx_inversesqrt rsqrt
4+
#define mx_sin sin
5+
#define mx_cos cos
6+
#define mx_tan tan
7+
#define mx_asin asin
8+
#define mx_acos acos
9+
#define mx_radians radians
10+
#define mx_float_bits_to_int asint
11+
12+
/// The GLSL we are piggybacking on has all its matrices transposed compared to Slang and the MaterialX spec.
13+
/// (The matrices are defined like mat3(1, 2, 3, 4, 5, 6, 7, 8, 9) where the spec says it should be row-major order, but GLSL creates it as col-major)
14+
/// So when GLSL code says "mul(M, v)" it means "v * transpose(M)", and since in Slang the matrices are stored
15+
/// in row-major order, we need to reverse the order of multiplication to get the same result.
16+
float2 mx_matrix_mul(float2 v, float2x2 m) { return mul(m, v); }
17+
float3 mx_matrix_mul(float3 v, float3x3 m) { return mul(m, v); }
18+
float4 mx_matrix_mul(float4 v, float4x4 m) { return mul(m, v); }
19+
float2 mx_matrix_mul(float2x2 m, float2 v) { return mul(v, m); }
20+
float3 mx_matrix_mul(float3x3 m, float3 v) { return mul(v, m); }
21+
float4 mx_matrix_mul(float4x4 m, float4 v) { return mul(v, m); }
22+
float2x2 mx_matrix_mul(float2x2 m1, float2x2 m2) { return mul(m2, m1); }
23+
float3x3 mx_matrix_mul(float3x3 m1, float3x3 m2) { return mul(m2, m1); }
24+
float4x4 mx_matrix_mul(float4x4 m1, float4x4 m2) { return mul(m2, m1); }
25+
26+
float mx_square(float x)
27+
{
28+
return x*x;
29+
}
30+
31+
float2 mx_square(float2 x)
32+
{
33+
return x*x;
34+
}
35+
36+
float3 mx_square(float3 x)
37+
{
38+
return x*x;
39+
}
40+
41+
float3 mx_srgb_encode(float3 color)
42+
{
43+
bool3 isAbove = (color > float3(0.0031308));
44+
float3 linSeg = color * 12.92;
45+
float3 powSeg = 1.055 * pow(max(color, float3(0.0)), float3(1.0 / 2.4)) - 0.055;
46+
return select(isAbove, powSeg, linSeg);
47+
}
48+
49+
/// Library assumes GLSL style mod (result has the sign of y), so cannot use fmod
50+
float mx_mod(float a, float b) { return (a - b * floor(a / b)); }
51+
float2 mx_mod(float2 a, float2 b) { return (a - b * floor(a / b)); }
52+
float3 mx_mod(float3 a, float3 b) { return (a - b * floor(a / b)); }
53+
float4 mx_mod(float4 a, float4 b) { return (a - b * floor(a / b)); }
54+
float2 mx_mod(float2 a, float b) { return (a - b * floor(a / b)); }
55+
float3 mx_mod(float3 a, float b) { return (a - b * floor(a / b)); }
56+
float4 mx_mod(float4 a, float b) { return (a - b * floor(a / b)); }
57+
58+
/// The float3x3 and float4x4 inverse are taken from the Slang's SGL library
59+
/// https://github.com/shader-slang/sgl/
60+
/// Specifically the matrix_math.h
61+
/// https://github.com/shader-slang/sgl/blob/main/src/sgl/math/matrix_math.h
62+
float3x3 mx_inverse(float3x3 m)
63+
{
64+
float one_over_det = 1.f / determinant(m);
65+
66+
float3x3 result;
67+
result[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]) * one_over_det;
68+
result[0][1] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]) * one_over_det;
69+
result[0][2] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]) * one_over_det;
70+
result[1][0] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) * one_over_det;
71+
result[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]) * one_over_det;
72+
result[1][2] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) * one_over_det;
73+
result[2][0] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]) * one_over_det;
74+
result[2][1] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) * one_over_det;
75+
result[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]) * one_over_det;
76+
return result;
77+
}
78+
79+
float4x4 mx_inverse(float4x4 m)
80+
{
81+
float c00 = m[2][2] * m[3][3] - m[2][3] * m[3][2];
82+
float c02 = m[2][1] * m[3][3] - m[2][3] * m[3][1];
83+
float c03 = m[2][1] * m[3][2] - m[2][2] * m[3][1];
84+
85+
float c04 = m[1][2] * m[3][3] - m[1][3] * m[3][2];
86+
float c06 = m[1][1] * m[3][3] - m[1][3] * m[3][1];
87+
float c07 = m[1][1] * m[3][2] - m[1][2] * m[3][1];
88+
89+
float c08 = m[1][2] * m[2][3] - m[1][3] * m[2][2];
90+
float c10 = m[1][1] * m[2][3] - m[1][3] * m[2][1];
91+
float c11 = m[1][1] * m[2][2] - m[1][2] * m[2][1];
92+
93+
float c12 = m[0][2] * m[3][3] - m[0][3] * m[3][2];
94+
float c14 = m[0][1] * m[3][3] - m[0][3] * m[3][1];
95+
float c15 = m[0][1] * m[3][2] - m[0][2] * m[3][1];
96+
97+
float c16 = m[0][2] * m[2][3] - m[0][3] * m[2][2];
98+
float c18 = m[0][1] * m[2][3] - m[0][3] * m[2][1];
99+
float c19 = m[0][1] * m[2][2] - m[0][2] * m[2][1];
100+
101+
float c20 = m[0][2] * m[1][3] - m[0][3] * m[1][2];
102+
float c22 = m[0][1] * m[1][3] - m[0][3] * m[1][1];
103+
float c23 = m[0][1] * m[1][2] - m[0][2] * m[1][1];
104+
105+
float4 fac0 = float4(c00, c00, c02, c03);
106+
float4 fac1 = float4(c04, c04, c06, c07);
107+
float4 fac2 = float4(c08, c08, c10, c11);
108+
float4 fac3 = float4(c12, c12, c14, c15);
109+
float4 fac4 = float4(c16, c16, c18, c19);
110+
float4 fac5 = float4(c20, c20, c22, c23);
111+
112+
float4 vec0 = float4(m[0][1], m[0][0], m[0][0], m[0][0]);
113+
float4 vec1 = float4(m[1][1], m[1][0], m[1][0], m[1][0]);
114+
float4 vec2 = float4(m[2][1], m[2][0], m[2][0], m[2][0]);
115+
float4 vec3 = float4(m[3][1], m[3][0], m[3][0], m[3][0]);
116+
117+
float4 inv0 = float4(vec1 * fac0 - vec2 * fac1 + vec3 * fac2);
118+
float4 inv1 = float4(vec0 * fac0 - vec2 * fac3 + vec3 * fac4);
119+
float4 inv2 = float4(vec0 * fac1 - vec1 * fac3 + vec3 * fac5);
120+
float4 inv3 = float4(vec0 * fac2 - vec1 * fac4 + vec2 * fac5);
121+
122+
float4 sign_a = float4(+1, -1, +1, -1);
123+
float4 sign_b = float4(-1, +1, -1, +1);
124+
// make matrix from columns
125+
float4x4 inverse = transpose(float4x4(inv0 * sign_a, inv1 * sign_b, inv2 * sign_a, inv3 * sign_b));
126+
127+
float4 row0 = float4(inverse[0][0], inverse[0][1], inverse[0][2], inverse[0][3]);
128+
float4 col0 = float4(inverse[0][0], inverse[1][0], inverse[2][0], inverse[3][0]);
129+
130+
float4 dot0 = float4(col0 * row0);
131+
float dot1 = (dot0.x + dot0.y) + (dot0.z + dot0.w);
132+
133+
float one_over_det = 1.f / dot1;
134+
135+
return inverse * one_over_det;
136+
}
137+
138+
float mx_atan(float y_over_x)
139+
{
140+
return atan(y_over_x);
141+
}
142+
143+
float mx_atan(float y, float x)
144+
{
145+
return atan2(y, x);
146+
}
147+
148+
float2 mx_atan(float2 y, float2 x)
149+
{
150+
return atan2(y, x);
151+
}
152+
153+
float3 mx_atan(float3 y, float3 x)
154+
{
155+
return atan2(y, x);
156+
}
157+
158+
float4 mx_atan(float4 y, float4 x)
159+
{
160+
return atan2(y, x);
161+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
struct SamplerTexture2D
2+
{
3+
Texture2D tex;
4+
SamplerState sampler;
5+
6+
// needed for Storm
7+
int get_width(int mipLevel = 0)
8+
{
9+
uint width, height, numberOfLevels;
10+
tex.GetDimensions(mipLevel, width, height, numberOfLevels);
11+
return width;
12+
}
13+
14+
int get_height(int mipLevel = 0)
15+
{
16+
uint width, height, numberOfLevels;
17+
tex.GetDimensions(mipLevel, width, height, numberOfLevels);
18+
return height;
19+
}
20+
21+
int get_num_mip_levels()
22+
{
23+
uint width, height, numberOfLevels;
24+
tex.GetDimensions(0, width, height, numberOfLevels);
25+
return numberOfLevels;
26+
}
27+
}
28+
29+
float4 textureLod(SamplerTexture2D tex, float2 uv, float lod)
30+
{
31+
return tex.tex.SampleLevel(tex.sampler, uv, lod);
32+
}
33+
34+
float4 texture(SamplerTexture2D tex, float2 uv)
35+
{
36+
return tex.tex.Sample(tex.sampler, uv);
37+
}
38+
39+
float4 textureGrad(SamplerTexture2D tex, float2 uv, float2 ddx_, float2 ddy_)
40+
{
41+
return tex.tex.SampleGrad(tex.sampler, uv, ddx_, ddy_);
42+
}
43+
44+
int2 textureSize(SamplerTexture2D tex, int mipLevel)
45+
{
46+
return int2(tex.get_width(mipLevel), tex.get_height(mipLevel));
47+
}

0 commit comments

Comments
 (0)