diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index acc9dbab0c..fcf1f2d2b7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,6 +38,7 @@ jobs: compiler: gcc compiler_version: "14" python: 3.13 + test_slang: ON extended_build_perfetto: ON extended_cmake_config: -DMATERIALX_BUILD_PERFETTO_TRACING=ON @@ -298,6 +299,20 @@ jobs: python python/Scripts/generateshader.py resources/Materials/Examples --target msl --validator "xcrun metal --language=metal" --validatorArgs="-w" python python/Scripts/generateshader.py resources/Materials/TestSuite/stdlib --target msl --validator "xcrun metal --language=metal" --validatorArgs="-w" + - name: Shader Validation Tests (Slang) + if: matrix.test_slang == 'ON' && runner.os == 'Linux' + run: | + SLANG_VERSION=2026.10.2 + curl -fsSL -o slang.tar.gz "https://github.com/shader-slang/slang/releases/download/v${SLANG_VERSION}/slang-${SLANG_VERSION}-linux-x86_64.tar.gz" + mkdir -p slang-release + tar -xzf slang.tar.gz -C slang-release + export LD_LIBRARY_PATH="$PWD/slang-release/lib:$PWD/slang-release/bin:$LD_LIBRARY_PATH" + SLANGC="$PWD/slang-release/bin/slangc" + chmod +x "$SLANGC" + "$SLANGC" -v + python python/Scripts/generateshader.py resources/Materials/Examples/StandardSurface --target slang --validator "$SLANGC" + python python/Scripts/generateshader.py resources/Materials/TestSuite/stdlib --target slang --validator "$SLANGC" + - name: Coverage Analysis Tests if: matrix.coverage_analysis == 'ON' run: | diff --git a/libraries/stdlib/genslang/lib/mx_texture.slang b/libraries/stdlib/genslang/lib/mx_texture.slang index 80e3a4ce1f..2f4420d019 100644 --- a/libraries/stdlib/genslang/lib/mx_texture.slang +++ b/libraries/stdlib/genslang/lib/mx_texture.slang @@ -24,7 +24,7 @@ struct SamplerTexture2D tex.GetDimensions(0, width, height, numberOfLevels); return numberOfLevels; } -} +}; float4 textureLod(SamplerTexture2D tex, float2 uv, float lod) { diff --git a/python/Scripts/generateshader.py b/python/Scripts/generateshader.py index 46ff359043..b574563224 100644 --- a/python/Scripts/generateshader.py +++ b/python/Scripts/generateshader.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ''' Generate shader code for each renderable element in a MaterialX document or folder. -The currently supported target languages are GLSL, ESSL, MSL, OSL, and MDL. +The currently supported target languages are GLSL, ESSL, Vulkan, WGSL, MSL, Slang, OSL, and MDL. ''' import sys, os, argparse, subprocess @@ -47,7 +47,7 @@ def main(): parser = argparse.ArgumentParser(description='Generate shader code for each renderable element in a MaterialX document or folder.') parser.add_argument('--path', dest='paths', action='append', nargs='+', help='An additional absolute search path location (e.g. "/projects/MaterialX")') parser.add_argument('--library', dest='libraries', action='append', nargs='+', help='An additional relative path to a custom data library folder (e.g. "libraries/custom")') - parser.add_argument('--target', dest='target', default='glsl', help='Target shader generator to use (e.g. "glsl, osl, mdl, essl, vulkan, wgsl"). Default is glsl.') + parser.add_argument('--target', dest='target', default='glsl', help='Target shader generator to use (e.g. "glsl, essl, vulkan, wgsl, msl, slang, osl, mdl"). Default is glsl.') parser.add_argument('--outputPath', dest='outputPath', help='File path to output shaders to. If not specified, is the location of the input document is used.') parser.add_argument('--validator', dest='validator', nargs='?', const=' ', type=str, help='Name of executable to perform source code validation.') parser.add_argument('--validatorArgs', dest='validatorArgs', nargs='?', const=' ', type=str, help='Optional arguments for code validator.') @@ -158,7 +158,7 @@ def main(): if shader: # Use extension of .vert and .frag as it's type is # recognized by glslangValidator - if gentarget in ['glsl', 'essl', 'vulkan', 'msl', 'wgsl']: + if gentarget in ['glsl', 'essl', 'vulkan', 'msl', 'wgsl', 'slang']: pixelSource = shader.getSourceCode(mx_gen_shader.PIXEL_STAGE) filename = pathPrefix + "/" + shader.getName() + "." + gentarget + ".frag" print('--- Wrote pixel shader to: ' + filename) diff --git a/source/MaterialXGenSlang/SlangShaderGenerator.cpp b/source/MaterialXGenSlang/SlangShaderGenerator.cpp index 2e093b32d8..9a088cae9b 100644 --- a/source/MaterialXGenSlang/SlangShaderGenerator.cpp +++ b/source/MaterialXGenSlang/SlangShaderGenerator.cpp @@ -372,7 +372,7 @@ void SlangShaderGenerator::emitInputs(GenContext& context, ShaderStage& stage) c emitLine("struct " + vertexInputs.getName(), stage, false); emitScopeBegin(stage); emitVariableDeclarations(vertexInputs, _syntax->getInputQualifier(), Syntax::SEMICOLON, context, stage, false); - emitScopeEnd(stage); + emitScopeEnd(stage, true); emitLineBreak(stage); for (size_t i = 0; i < vertexInputs.size(); ++i) @@ -398,7 +398,7 @@ void SlangShaderGenerator::emitInputs(GenContext& context, ShaderStage& stage) c { emitVariableDeclarations(vertexData, EMPTY_STRING, Syntax::SEMICOLON, context, stage, false); } - emitScopeEnd(stage, false, false); + emitScopeEnd(stage, true); emitLineBreak(stage); emitLine("static " + vertexData.getName() + " vd", stage); } @@ -416,7 +416,7 @@ void SlangShaderGenerator::emitOutputs(GenContext& context, ShaderStage& stage) { emitVariableDeclarations(vertexData, EMPTY_STRING, Syntax::SEMICOLON, context, stage, false); } - emitScopeEnd(stage); + emitScopeEnd(stage, true); emitLineBreak(stage); emitLineBreak(stage); }