diff options
| author | Anders Leino <aleino@nvidia.com> | 2025-03-12 13:44:57 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-12 13:44:57 +0200 |
| commit | f4d5372d3354e62770b076b47892b5172223e98a (patch) | |
| tree | 48220e9716dd585ffa64635e977df2878fc63bdc | |
| parent | 7a942cfdc338d199b8e775d16b0b9b49699363d7 (diff) | |
Migrate render-test away from deprecated compile request API (#6514)
* Add a simple interface parameter test
Since there's no documentation, it's nice to have a simple test case in order to
experiment with this feature of the testing framework.
* Add shader entry point attributes to tests
* Fix specialization arguments for tests
- Add some missing arguments
- Rremove one extraneous argument.
* Stop using deprecated compile request in render-test
Use a session object instead of the deprecated compile request object.
This closes issue #4760.
30 files changed, 421 insertions, 153 deletions
diff --git a/tests/bugs/texture2d-gather.hlsl b/tests/bugs/texture2d-gather.hlsl index 7344d863d..46f921b26 100644 --- a/tests/bugs/texture2d-gather.hlsl +++ b/tests/bugs/texture2d-gather.hlsl @@ -31,6 +31,7 @@ struct VertexStageOutput float4 position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -41,7 +42,7 @@ VertexStageOutput vertexMain(VertexStageInput input) return output; } -// Fragment Shader +[shader("fragment")] float4 fragmentMain(VertexStageOutput input) : SV_Target { return g_texture.GatherRed(g_sampler, input.color.xy); diff --git a/tests/compute/compile-time-loop.slang b/tests/compute/compile-time-loop.slang index 9035bde2a..c70cfb1b9 100644 --- a/tests/compute/compile-time-loop.slang +++ b/tests/compute/compile-time-loop.slang @@ -45,6 +45,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -70,6 +71,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { FragmentStageOutput output; diff --git a/tests/compute/constexpr.slang b/tests/compute/constexpr.slang index f1cd76841..5370de733 100644 --- a/tests/compute/constexpr.slang +++ b/tests/compute/constexpr.slang @@ -52,6 +52,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -77,6 +78,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { // The texel offset argument to `Texture2D.Sample` is diff --git a/tests/compute/discard-stmt.slang b/tests/compute/discard-stmt.slang index fa00c9ec3..6988d611b 100644 --- a/tests/compute/discard-stmt.slang +++ b/tests/compute/discard-stmt.slang @@ -46,6 +46,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -71,6 +72,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { FragmentStageOutput output; diff --git a/tests/compute/dynamic-dispatch-bindless-texture.slang b/tests/compute/dynamic-dispatch-bindless-texture.slang index 34ef67d1e..b02ca9686 100644 --- a/tests/compute/dynamic-dispatch-bindless-texture.slang +++ b/tests/compute/dynamic-dispatch-bindless-texture.slang @@ -25,7 +25,6 @@ void computeMain(int3 dispatchThreadID : SV_DispatchThreadID) gOutputBuffer[tid] = uint(trunc(outputVal)); } -//TEST_INPUT: globalExistentialType __Dynamic // Type must be marked `public` to ensure it is visible in the generated DLL. export struct MyImpl : IInterface diff --git a/tests/compute/interface-shader-param.slang b/tests/compute/interface-shader-param.slang index 7965253b2..58e477fcb 100644 --- a/tests/compute/interface-shader-param.slang +++ b/tests/compute/interface-shader-param.slang @@ -84,6 +84,7 @@ RWStructuredBuffer<int> gOutputBuffer; // Now we'll define a global shader parameter for the // random number generation strategy. // +//TEST_INPUT: globalSpecializationArg MyStrategy //TEST_INPUT:set gStrategy = new MyStrategy{} uniform IRandomNumberGenerationStrategy gStrategy; @@ -93,6 +94,7 @@ uniform IRandomNumberGenerationStrategy gStrategy; // [numthreads(4, 1, 1)] void computeMain( +//TEST_INPUT: entryPointSpecializationArg MyModifier //TEST_INPUT:set modifier = new MyModifier{} uniform IModifier modifier, int3 dispatchThreadID : SV_DispatchThreadID) diff --git a/tests/compute/simple-interface-parameter.slang b/tests/compute/simple-interface-parameter.slang new file mode 100644 index 000000000..067fb621f --- /dev/null +++ b/tests/compute/simple-interface-parameter.slang @@ -0,0 +1,27 @@ +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute + +interface IGetter +{ + int get(int x); +} + +//TEST_INPUT:set gOutputBuffer = out ubuffer(data=[0 0 0 0], stride=4) +RWStructuredBuffer<int> gOutputBuffer; + +//TEST_INPUT: globalSpecializationArg MyGetter +//TEST_INPUT: set gGetter = new MyGetter{} +uniform IGetter gGetter; + +[numthreads(4, 1, 1)] +void computeMain(int3 dispatchThreadID : SV_DispatchThreadID) +{ + gOutputBuffer[dispatchThreadID.x] = gGetter.get(dispatchThreadID.x); +} + +struct MyGetter : IGetter +{ + int get(int x) + { + return x + 1; + } +} diff --git a/tests/compute/simple-interface-parameter.slang.expected.txt b/tests/compute/simple-interface-parameter.slang.expected.txt new file mode 100644 index 000000000..94ebaf900 --- /dev/null +++ b/tests/compute/simple-interface-parameter.slang.expected.txt @@ -0,0 +1,4 @@ +1 +2 +3 +4 diff --git a/tests/compute/texture-sampling-no-1d-arrays.slang b/tests/compute/texture-sampling-no-1d-arrays.slang index f95050fca..0985374cc 100644 --- a/tests/compute/texture-sampling-no-1d-arrays.slang +++ b/tests/compute/texture-sampling-no-1d-arrays.slang @@ -60,6 +60,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -85,6 +86,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { FragmentStageOutput output; diff --git a/tests/glsl-intrinsic/shader-invocation-group/shader-invocation-group.slang b/tests/glsl-intrinsic/shader-invocation-group/shader-invocation-group.slang index 201f33ea2..d68979675 100644 --- a/tests/glsl-intrinsic/shader-invocation-group/shader-invocation-group.slang +++ b/tests/glsl-intrinsic/shader-invocation-group/shader-invocation-group.slang @@ -34,6 +34,8 @@ bool testAllInvocationsEqual() && allInvocationsEqual(gl_GlobalInvocationID.x == 0) == false ; } + +[shader("compute")] void computeMain() { outputBuffer.data[0] = true diff --git a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_Exclusive.slang b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_Exclusive.slang index 0a0fcade5..c77fa5929 100644 --- a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_Exclusive.slang +++ b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_Exclusive.slang @@ -183,6 +183,7 @@ bool testArithmetic() { ; } +[shader("compute")] void computeMain() { diff --git a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_Inclusive.slang b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_Inclusive.slang index 58c7d5aaa..40f77ee61 100644 --- a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_Inclusive.slang +++ b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_Inclusive.slang @@ -183,6 +183,7 @@ bool testArithmetic() { ; } +[shader("compute")] void computeMain() { diff --git a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_None.slang b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_None.slang index bb6316a59..4bea35b6e 100644 --- a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_None.slang +++ b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-arithmetic_None.slang @@ -182,6 +182,7 @@ bool testArithmetic() { ; } +[shader("compute")] void computeMain() { diff --git a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-ballot.slang b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-ballot.slang index 04f1b935a..82fb38f5e 100644 --- a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-ballot.slang +++ b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-ballot.slang @@ -139,6 +139,7 @@ bool testBallot() { ; } +[shader("compute")] void computeMain() { outputBuffer.data[0] = true diff --git a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-builtin-variables-2.slang b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-builtin-variables-2.slang index 2e3896cc5..aceff939b 100644 --- a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-builtin-variables-2.slang +++ b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-builtin-variables-2.slang @@ -16,6 +16,7 @@ buffer MyBlockName2 layout(local_size_x = 4) in; +[shader("compute")] void computeMain(int3 dispatchThreadID : SV_DispatchThreadID) { // There may be some issues with structure padding for global context containing diff --git a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-builtin-variables.slang b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-builtin-variables.slang index 2d11ca5fb..bfef48374 100644 --- a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-builtin-variables.slang +++ b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-builtin-variables.slang @@ -25,6 +25,7 @@ buffer MyBlockName2 layout(local_size_x = 32) in; +[shader("compute")] void computeMain() { if (gl_GlobalInvocationID.x == 3) { diff --git a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-vote.slang b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-vote.slang index c0b6e3788..23466b742 100644 --- a/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-vote.slang +++ b/tests/glsl-intrinsic/shader-subgroup/shader-subgroup-vote.slang @@ -126,6 +126,7 @@ void _barrier() #endif } +[shader("compute")] void computeMain() { //seperate tests since testing concurrency diff --git a/tests/glsl/ssbo.slang b/tests/glsl/ssbo.slang index 4f4db07cd..1eb2722ff 100644 --- a/tests/glsl/ssbo.slang +++ b/tests/glsl/ssbo.slang @@ -17,6 +17,7 @@ buffer MyBlockName2 } outputBuffer; layout(local_size_x = 4) in; +[shader("compute")] void computeMain() { outputBuffer.data[gl_GlobalInvocationID.x] = inputBuffer.data[gl_GlobalInvocationID.x]; diff --git a/tests/language-feature/shader-params/interface-shader-param-ordinary.slang b/tests/language-feature/shader-params/interface-shader-param-ordinary.slang index 7196f9b04..fa4657d76 100644 --- a/tests/language-feature/shader-params/interface-shader-param-ordinary.slang +++ b/tests/language-feature/shader-params/interface-shader-param-ordinary.slang @@ -23,6 +23,7 @@ RWStructuredBuffer<int> gOutputBuffer; //TEST_INPUT:set delta = 65536 uniform int delta; +//TEST_INPUT: globalSpecializationArg MyModifier //TEST_INPUT:set gModifier = new MyModifier{ ubuffer(data=[4 3 2 1], stride=4), 3 } } uniform IModifier gModifier; diff --git a/tests/pipeline/rasterization/mesh/task-groupshared.slang b/tests/pipeline/rasterization/mesh/task-groupshared.slang index 46334bf3e..4d88de780 100644 --- a/tests/pipeline/rasterization/mesh/task-groupshared.slang +++ b/tests/pipeline/rasterization/mesh/task-groupshared.slang @@ -32,6 +32,7 @@ struct MeshPayload groupshared MeshPayload p; [numthreads(1, 1, 1)] +[shader("amplification")] void taskMain(in uint tig : SV_GroupIndex) { p.exponent = 3; diff --git a/tests/pipeline/rasterization/mesh/task-simple.slang b/tests/pipeline/rasterization/mesh/task-simple.slang index 053b24045..61cc6da3d 100644 --- a/tests/pipeline/rasterization/mesh/task-simple.slang +++ b/tests/pipeline/rasterization/mesh/task-simple.slang @@ -35,6 +35,7 @@ struct MeshPayload }; [numthreads(1, 1, 1)] +[shader("amplification")] void taskMain(in uint tig : SV_GroupIndex) { MeshPayload p; diff --git a/tests/render/cross-compile-entry-point.slang b/tests/render/cross-compile-entry-point.slang index d8cb687c5..3b5faa111 100644 --- a/tests/render/cross-compile-entry-point.slang +++ b/tests/render/cross-compile-entry-point.slang @@ -50,6 +50,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -76,6 +77,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { FragmentStageOutput output; diff --git a/tests/render/cross-compile0.hlsl b/tests/render/cross-compile0.hlsl index 1d33b68bf..1820a17f0 100644 --- a/tests/render/cross-compile0.hlsl +++ b/tests/render/cross-compile0.hlsl @@ -45,6 +45,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -71,6 +72,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { FragmentStageOutput output; diff --git a/tests/render/imported-parameters.hlsl b/tests/render/imported-parameters.hlsl index 495ff8da2..1ed27bfa0 100644 --- a/tests/render/imported-parameters.hlsl +++ b/tests/render/imported-parameters.hlsl @@ -38,6 +38,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -64,6 +65,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { FragmentStageOutput output; diff --git a/tests/render/multiple-stage-io-locations-without-user-semantics.slang b/tests/render/multiple-stage-io-locations-without-user-semantics.slang index af0e3e39f..585b8e34e 100644 --- a/tests/render/multiple-stage-io-locations-without-user-semantics.slang +++ b/tests/render/multiple-stage-io-locations-without-user-semantics.slang @@ -31,6 +31,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -58,6 +59,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { FragmentStageOutput output; diff --git a/tests/render/multiple-stage-io-locations.slang b/tests/render/multiple-stage-io-locations.slang index 9f74d1398..5e27a9cf1 100644 --- a/tests/render/multiple-stage-io-locations.slang +++ b/tests/render/multiple-stage-io-locations.slang @@ -32,6 +32,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -59,6 +60,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { FragmentStageOutput output; diff --git a/tests/render/nointerpolation.hlsl b/tests/render/nointerpolation.hlsl index d514379d0..145bd3bed 100644 --- a/tests/render/nointerpolation.hlsl +++ b/tests/render/nointerpolation.hlsl @@ -41,6 +41,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -66,6 +67,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { FragmentStageOutput output; diff --git a/tests/render/render0.hlsl b/tests/render/render0.hlsl index 90ca42430..9fd169b06 100644 --- a/tests/render/render0.hlsl +++ b/tests/render/render0.hlsl @@ -38,6 +38,7 @@ struct VertexStageOutput float4 sv_position : SV_Position; }; +[shader("vertex")] VertexStageOutput vertexMain(VertexStageInput input) { VertexStageOutput output; @@ -63,6 +64,7 @@ struct FragmentStageOutput Fragment fragment : SV_Target; }; +[shader("fragment")] FragmentStageOutput fragmentMain(FragmentStageInput input) { FragmentStageOutput output; diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp index 5f9ae5a7f..dfde5f386 100644 --- a/tools/render-test/slang-support.cpp +++ b/tools/render-test/slang-support.cpp @@ -4,6 +4,8 @@ #include "slang-support.h" +#include "../../source/compiler-core/slang-artifact-desc-util.h" +#include "../../source/core/slang-file-system.h" #include "../../source/core/slang-string-util.h" #include "../../source/core/slang-test-tool-util.h" #include "options.h" @@ -36,7 +38,7 @@ void ShaderCompilerUtil::Output::reset() } globalSession = nullptr; - m_requestDEPRECATED = nullptr; + m_session = nullptr; } static SlangResult _compileProgramImpl( @@ -48,58 +50,84 @@ static SlangResult _compileProgramImpl( { out.reset(); - slang::SessionDesc sessionDesc = {}; - List<slang::PreprocessorMacroDesc> macros; - sessionDesc.preprocessorMacroCount = (SlangInt)macros.getCount(); - sessionDesc.preprocessorMacros = macros.getBuffer(); - - ComPtr<SlangCompileRequest> slangRequest = nullptr; - SLANG_ALLOW_DEPRECATED_BEGIN - globalSession->createCompileRequest(slangRequest.writeRef()); - SLANG_ALLOW_DEPRECATED_END - out.m_requestDEPRECATED = slangRequest; - out.globalSession = globalSession; + List<const char*> args; + for (const auto& arg : options.downstreamArgs.getArgsByName("slang")) + { + args.add(arg.value.getBuffer()); + // The -load-repro feature is not maintained, and not supported by the new compile API. + // TODO: Remove this when the feature has been deprecated. + SLANG_ASSERT(arg.value != "-load-repro"); + } - // Parse all the extra args + slang::TargetDesc sessionTargetDesc = {}; + slang::SessionDesc sessionDesc = {}; + ComPtr<ISlangUnknown> sessionDescMemory; + // If there are additional args parse them + if (args.getCount()) { - List<const char*> args; - for (const auto& arg : options.downstreamArgs.getArgsByName("slang")) + const auto res = globalSession->parseCommandLineArguments( + int(args.getCount()), + args.getBuffer(), + &sessionDesc, + sessionDescMemory.writeRef()); + // If there is a parse failure and diagnostic, output it + if (SLANG_FAILED(res)) + { + fprintf(stderr, "error: Failed to parse command line arguments: %d\n", int(res)); + return res; + } + // We're setting the targets ourselves, below. + // To simplify that, we're currently not expecting targets to be added by the command line + // arguments. + if (sessionDesc.targetCount > 0) { - args.add(arg.value.getBuffer()); - // The -load-repro feature is not maintained, and not supported by the new compile API. - // TODO: Remove this when the feature has been deprecated. - SLANG_ASSERT(arg.value != "-load-repro"); + fprintf(stderr, "error: Command line arguments added targets.\n"); + return SLANG_FAIL; } + } - // If there are additional args parse them - if (args.getCount()) + // Argument parsing may have already added options, so add those first. + // For module reference options there are two cases: + // 1. If it's a slang module, then record the path and later create an IModule from that. + // 2. If not, then propagate the option. + // The reason to propagate the option in case 2 is that there is not currently a way of + // representing a module for a downstream compiler in the compilation API. + List<slang::CompilerOptionEntry> sessionOptionEntries; + List<Slang::String> referencedSlangModulePaths; + for (int optionIndex = 0; optionIndex < sessionDesc.compilerOptionEntryCount; optionIndex++) + { + slang::CompilerOptionEntry& option = sessionDesc.compilerOptionEntries[optionIndex]; + if (option.name == slang::CompilerOptionName::ReferenceModule) { - const auto res = - slangRequest->processCommandLineArguments(args.getBuffer(), int(args.getCount())); - // If there is a parse failure and diagnostic, output it - if (SLANG_FAILED(res)) + SLANG_ASSERT(option.value.kind == slang::CompilerOptionValueKind::String); + const char* path = option.value.stringValue0; + auto desc = Slang::ArtifactDescUtil::getDescFromPath(Slang::UnownedStringSlice(path)); + switch (desc.payload) { - if (auto diagnostics = slangRequest->getDiagnosticOutput()) + case Slang::ArtifactDesc::Payload::SlangIR: + case Slang::ArtifactDesc::Payload::Slang: + referencedSlangModulePaths.add(option.value.stringValue0); + break; + case Slang::ArtifactDesc::Payload::DXIL: + sessionOptionEntries.add(option); + break; + default: { - fprintf(stderr, "%s", diagnostics); + fprintf( + stderr, + "error: Unexpected artifact payload type: %d\n", + (int)desc.payload); + return SLANG_FAIL; } - return res; } } + else + { + sessionOptionEntries.add(option); + } } - spSetCodeGenTarget(slangRequest, input.target); - if (input.profile.getLength()) // do not set profile unless requested - spSetTargetProfile( - slangRequest, - 0, - spFindProfile(out.globalSession, input.profile.getBuffer())); - if (options.generateSPIRVDirectly) - spSetTargetFlags(slangRequest, 0, SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY); - else - spSetTargetFlags(slangRequest, 0, 0); - - slangRequest->setAllowGLSLInput(options.allowGLSL); + List<slang::PreprocessorMacroDesc> macros; // Define a macro so that shader code in a test can detect what language we // are nominally working with. @@ -107,26 +135,26 @@ static SlangResult _compileProgramImpl( switch (input.sourceLanguage) { case SLANG_SOURCE_LANGUAGE_GLSL: - spAddPreprocessorDefine(slangRequest, "__GLSL__", "1"); + macros.add({"__GLSL__", "1"}); break; case SLANG_SOURCE_LANGUAGE_SLANG: - spAddPreprocessorDefine(slangRequest, "__SLANG__", "1"); + macros.add({"__SLANG__", "1"}); // fall through case SLANG_SOURCE_LANGUAGE_HLSL: - spAddPreprocessorDefine(slangRequest, "__HLSL__", "1"); + macros.add({"__HLSL__", "1"}); break; case SLANG_SOURCE_LANGUAGE_C: - spAddPreprocessorDefine(slangRequest, "__C__", "1"); + macros.add({"__C__", "1"}); break; case SLANG_SOURCE_LANGUAGE_CPP: - spAddPreprocessorDefine(slangRequest, "__CPP__", "1"); + macros.add({"__CPP__", "1"}); break; case SLANG_SOURCE_LANGUAGE_CUDA: - spAddPreprocessorDefine(slangRequest, "__CUDA__", "1"); + macros.add({"__CUDA__", "1"}); break; case SLANG_SOURCE_LANGUAGE_WGSL: - spAddPreprocessorDefine(slangRequest, "__WGSL__", "1"); + macros.add({"__WGSL__", "1"}); break; default: @@ -134,50 +162,195 @@ static SlangResult _compileProgramImpl( break; } - if (input.passThrough != SLANG_PASS_THROUGH_NONE) { - spSetPassThrough(slangRequest, input.passThrough); + slang::CompilerOptionEntry entry; + entry.name = slang::CompilerOptionName::AllowGLSL; + entry.value.kind = slang::CompilerOptionValueKind::Int; + entry.value.intValue0 = int(options.allowGLSL); + sessionOptionEntries.add(entry); } + + { + slang::CompilerOptionEntry entry; + entry.name = slang::CompilerOptionName::PassThrough; + entry.value.kind = slang::CompilerOptionValueKind::Int; + entry.value.intValue0 = int(input.passThrough); + sessionOptionEntries.add(entry); + } + + { + slang::CompilerOptionEntry entry; + entry.name = slang::CompilerOptionName::LineDirectiveMode; + entry.value.kind = slang::CompilerOptionValueKind::Int; + entry.value.intValue0 = int(SlangLineDirectiveMode::SLANG_LINE_DIRECTIVE_MODE_NONE); + sessionOptionEntries.add(entry); + } + + sessionTargetDesc.format = input.target; + if (input.profile.getLength()) // do not set profile unless requested + sessionTargetDesc.profile = globalSession->findProfile(input.profile.getBuffer()); + if (options.generateSPIRVDirectly) + sessionTargetDesc.flags |= SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY; else + sessionTargetDesc.flags = 0; + + // Not expecting argument parsing to have added any targets + SLANG_ASSERT(sessionDesc.targetCount == 0); + sessionDesc.targetCount = 1; + sessionDesc.targets = &sessionTargetDesc; + + if (options.generateSPIRVDirectly) { - spSetCompileFlags(slangRequest, SLANG_COMPILE_FLAG_NO_CODEGEN); + slang::CompilerOptionEntry entry; + entry.name = slang::CompilerOptionName::DebugInformation; + entry.value.kind = slang::CompilerOptionValueKind::Int; + entry.value.intValue0 = + int(options.disableDebugInfo ? SlangDebugInfoLevel::SLANG_DEBUG_INFO_LEVEL_NONE + : SlangDebugInfoLevel::SLANG_DEBUG_INFO_LEVEL_STANDARD); + sessionOptionEntries.add(entry); } + sessionDesc.compilerOptionEntryCount = sessionOptionEntries.getCount(); + sessionDesc.compilerOptionEntries = sessionOptionEntries.getBuffer(); - const auto sourceLanguage = input.sourceLanguage; + // Argument parsing should not have added macros. + SLANG_ASSERT(sessionDesc.preprocessorMacroCount == 0); + sessionDesc.preprocessorMacroCount = (SlangInt)macros.getCount(); + sessionDesc.preprocessorMacros = macros.getBuffer(); + + ComPtr<slang::ISession> slangSession = nullptr; + SLANG_RETURN_ON_FAIL(globalSession->createSession(sessionDesc, slangSession.writeRef())); + out.m_session = slangSession; + out.globalSession = globalSession; - int translationUnitIndex = 0; + String source(request.source.dataBegin, request.source.dataEnd); + ComPtr<slang::IBlob> diagnostics; + ComPtr<slang::IModule> module(slangSession->loadModuleFromSourceString( + "main", + request.source.path, + source.getBuffer(), + diagnostics.writeRef())); + if (!module) { - translationUnitIndex = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr); - spAddTranslationUnitSourceString( - slangRequest, - translationUnitIndex, - request.source.path, - request.source.dataBegin); + fprintf( + stderr, + "error: Failed to load module: %s\n", + diagnostics ? (char*)diagnostics->getBufferPointer() : "(no diagnostic output)"); + return SLANG_FAIL; } - const int globalSpecializationArgCount = int(request.globalSpecializationArgs.getCount()); + // Some tests are verifying that various warnings are printed, so print any diagnostics! + if (diagnostics && (diagnostics->getBufferSize() > 0U)) + StdWriters::getError().print("%s", (char*)diagnostics->getBufferPointer()); + + ComPtr<slang::IModule> specializedModule; + List<ComPtr<slang::IEntryPoint>> specializedEntryPoints; + List<slang::IComponentType*> componentsRawPtr; + + ComPtr<ISlangFileSystem> osFileSystem = + ComPtr<ISlangFileSystem>(Slang::OSFileSystem::getExtSingleton()); + + // This list is just kept so that the modules will be freed at scope exit + List<ComPtr<slang::IModule>> referencedModules; + for (auto& path : referencedSlangModulePaths) + { + auto desc = + Slang::ArtifactDescUtil::getDescFromPath(Slang::UnownedStringSlice(path.getBuffer())); + // If it's a GPU binary, then we'll assume it's a library + if (ArtifactDescUtil::isGpuUsable(desc)) + { + desc.kind = ArtifactKind::Library; + } + const String name = ArtifactDescUtil::getBaseNameFromPath(desc, path.getUnownedSlice()); + + ComPtr<slang::IBlob> codeBlob; + SlangResult result = osFileSystem->loadFile(path.getBuffer(), codeBlob.writeRef()); + if (SLANG_FAILED(result)) + { + fprintf(stderr, "error: Failed to read referenced module file: %s\n", path.getBuffer()); + return SLANG_FAIL; + } + + ComPtr<slang::IModule> module; + switch (desc.payload) + { + case Slang::ArtifactDesc::Payload::Slang: + { + String sourceString( + (const char*)codeBlob->getBufferPointer(), + (const char*)codeBlob->getBufferPointer() + codeBlob->getBufferSize()); + module = ComPtr<slang::IModule>(slangSession->loadModuleFromSourceString( + name.getBuffer(), + path.getBuffer(), + sourceString.getBuffer(), + diagnostics.writeRef())); + break; + } + case Slang::ArtifactDesc::Payload::SlangIR: + { + module = ComPtr<slang::IModule>(slangSession->loadModuleFromIRBlob( + name.getBuffer(), + path.getBuffer(), + codeBlob, + diagnostics.writeRef())); + break; + } + default: + { + SLANG_UNREACHABLE("Unexpected artifact payload type"); + } + } + + if (!module) + { + fprintf( + stderr, + "error: Failed to load referenced module: %s: %s\n", + path.getBuffer(), + diagnostics ? (char*)diagnostics->getBufferPointer() : "(no diagnostic output)"); + return SLANG_FAIL; + } + referencedModules.add(module); + componentsRawPtr.add(module.get()); + } + + int globalSpecializationArgCount = int(request.globalSpecializationArgs.getCount()); + int moduleSpecializationArgCount = module->getSpecializationParamCount(); + if (globalSpecializationArgCount != moduleSpecializationArgCount) + { + fprintf( + stderr, + "error: The specialization argument count of the request (%d) does not match that of " + "the module (%d)!\n", + globalSpecializationArgCount, + moduleSpecializationArgCount); + return SLANG_FAIL; + } + List<slang::SpecializationArg> moduleSpecializationArgs; for (int ii = 0; ii < globalSpecializationArgCount; ++ii) { - spSetTypeNameForGlobalExistentialTypeParam( - slangRequest, - ii, - request.globalSpecializationArgs[ii].getBuffer()); + String specializedTypeName = request.globalSpecializationArgs[ii].getBuffer(); + slang::TypeReflection* typeReflection = + module->getLayout()->findTypeByName(specializedTypeName.getBuffer()); + moduleSpecializationArgs.add(slang::SpecializationArg::fromType(typeReflection)); } - const int entryPointSpecializationArgCount = - int(request.entryPointSpecializationArgs.getCount()); - auto setEntryPointSpecializationArgs = [&](int entryPoint) { - for (int ii = 0; ii < entryPointSpecializationArgCount; ++ii) + ComPtr<slang::IBlob> diagnostics; + auto res = module->specialize( + moduleSpecializationArgs.getBuffer(), + moduleSpecializationArgs.getCount(), + (slang::IComponentType**)specializedModule.writeRef(), + diagnostics.writeRef()); + if (SLANG_FAILED(res)) { - spSetTypeNameForEntryPointExistentialTypeParam( - slangRequest, - entryPoint, - ii, - request.entryPointSpecializationArgs[ii].getBuffer()); + fprintf( + stderr, + "error: Failed to specialize module: %s\n", + diagnostics ? (char*)diagnostics->getBufferPointer() : "(no diagnostic output)"); + return res; } - }; + } Index explicitEntryPointCount = request.entryPoints.getCount(); for (Index ee = 0; ee < explicitEntryPointCount; ++ee) @@ -192,107 +365,134 @@ static SlangResult _compileProgramImpl( } auto& entryPointInfo = request.entryPoints[ee]; - int entryPointIndex = spAddEntryPoint( - slangRequest, - translationUnitIndex, - entryPointInfo.name, - entryPointInfo.slangStage); - SLANG_ASSERT(entryPointIndex == ee); - - setEntryPointSpecializationArgs(entryPointIndex); - } - - spSetLineDirectiveMode(slangRequest, SLANG_LINE_DIRECTIVE_MODE_NONE); - - if (options.generateSPIRVDirectly) - { - if (options.disableDebugInfo) - spSetDebugInfoLevel(slangRequest, SLANG_DEBUG_INFO_LEVEL_NONE); - else - spSetDebugInfoLevel(slangRequest, SLANG_DEBUG_INFO_LEVEL_STANDARD); - } - - const SlangResult res = spCompile(slangRequest); - - if (auto diagnostics = spGetDiagnosticOutput(slangRequest)) - { - StdWriters::getError().print("%s", diagnostics); - } - - SLANG_RETURN_ON_FAIL(res); - - ComPtr<slang::IComponentType> linkedSlangProgram; - - List<ShaderCompileRequest::EntryPoint> actualEntryPoints; - if (input.passThrough == SLANG_PASS_THROUGH_NONE) - { - // In the case where pass-through compilation is not being used, - // we can use the Slang reflection information to discover what - // the entry points were, and then use those to drive the - // loading of code. - // - auto reflection = slang::ProgramLayout::get(slangRequest); - SLANG_RETURN_ON_FAIL(spCompileRequest_getProgramWithEntryPoints( - slangRequest, - linkedSlangProgram.writeRef())); - - // Get the amount of entry points in reflection - Index entryPointCount = Index(reflection->getEntryPointCount()); - - // We must have at least one entry point (whether explicit or implicit) - SLANG_ASSERT(entryPointCount); - for (Index ee = 0; ee < entryPointCount; ++ee) + ComPtr<slang::IEntryPoint> entryPoint; + ComPtr<slang::IBlob> diagnostics; + auto res = module->findAndCheckEntryPoint( + entryPointInfo.name, + entryPointInfo.slangStage, + entryPoint.writeRef(), + diagnostics.writeRef()); + if (SLANG_FAILED(res)) { - auto entryPoint = reflection->getEntryPointByIndex(ee); - const char* entryPointName = entryPoint->getName(); - SLANG_ASSERT(entryPointName); + fprintf( + stderr, + "error: Failed to find entry point '%s': %s\n", + entryPointInfo.name, + diagnostics ? (char*)diagnostics->getBufferPointer() : "(no diagnostic output)"); + return res; + } - auto slangStage = entryPoint->getStage(); + const int entryPointSpecializationArgCount = + int(request.entryPointSpecializationArgs.getCount()); + if (entryPointSpecializationArgCount != entryPoint->getSpecializationParamCount()) + { + fprintf( + stderr, + "error: %s\n", + "The specialization argument count of the requested entry point does not match " + "that of the entry point!"); + return SLANG_FAIL; + } - ShaderCompileRequest::EntryPoint entryPointInfo; - entryPointInfo.name = entryPointName; - entryPointInfo.slangStage = slangStage; + List<slang::SpecializationArg> entryPointSpecializationArgs; + for (int ii = 0; ii < entryPointSpecializationArgCount; ++ii) + { + String specializedTypeName = request.entryPointSpecializationArgs[ii].getBuffer(); + slang::TypeReflection* typeReflection = + module->getLayout()->findTypeByName(specializedTypeName.getBuffer()); + entryPointSpecializationArgs.add(slang::SpecializationArg::fromType(typeReflection)); + } - actualEntryPoints.add(entryPointInfo); + ComPtr<slang::IEntryPoint> specializedEntryPoint; + { + ComPtr<slang::IBlob> diagnostics; + auto res = entryPoint->specialize( + entryPointSpecializationArgs.getBuffer(), + entryPointSpecializationArgs.getCount(), + (slang::IComponentType**)specializedEntryPoint.writeRef(), + diagnostics.writeRef()); + if (SLANG_FAILED(res)) + { + fprintf( + stderr, + "error: Failed to specialize entry point: %s\n", + diagnostics ? (char*)diagnostics->getBufferPointer() + : "(no diagnostic output)"); + return res; + } } + specializedEntryPoints.add(specializedEntryPoint); } - else + + if (input.passThrough == SLANG_PASS_THROUGH_NONE) { - actualEntryPoints = request.entryPoints; + componentsRawPtr.add(specializedModule); + for (auto& specializedEntryPoint : specializedEntryPoints) + componentsRawPtr.add(specializedEntryPoint); } + // This list just makes sure that the components get released + List<ComPtr<slang::ITypeConformance>> typeConformanceComponents; if (request.typeConformances.getCount()) { - ComPtr<slang::ISession> session; - slangRequest->getSession(session.writeRef()); - List<ComPtr<slang::ITypeConformance>> typeConformanceComponents; - List<slang::IComponentType*> componentsRawPtr; - componentsRawPtr.add(linkedSlangProgram.get()); - auto reflection = slang::ProgramLayout::get(slangRequest); - ComPtr<ISlangBlob> outDiagnostic; + auto reflection = module->getLayout(); for (auto& conformance : request.typeConformances) { + ComPtr<ISlangBlob> outDiagnostic; auto derivedType = reflection->findTypeByName(conformance.derivedTypeName.getBuffer()); auto baseType = reflection->findTypeByName(conformance.baseTypeName.getBuffer()); ComPtr<slang::ITypeConformance> conformanceComponentType; - session->createTypeConformanceComponentType( + SlangResult res = slangSession->createTypeConformanceComponentType( derivedType, baseType, conformanceComponentType.writeRef(), conformance.idOverride, outDiagnostic.writeRef()); + if (SLANG_FAILED(res)) + { + fprintf( + stderr, + "error: Failed to handle type conformances: %s\n", + outDiagnostic ? (char*)outDiagnostic->getBufferPointer() + : "(no diagnostic output)"); + return res; + } typeConformanceComponents.add(conformanceComponentType); componentsRawPtr.add(conformanceComponentType); } - ComPtr<slang::IComponentType> newProgram; - session->createCompositeComponentType( + } + + ComPtr<slang::IComponentType> linkedSlangProgram; + if (componentsRawPtr.getCount() > 0) + { + ComPtr<slang::IComponentType> composite; + ComPtr<ISlangBlob> outDiagnostic; + SlangResult res = slangSession->createCompositeComponentType( componentsRawPtr.getBuffer(), componentsRawPtr.getCount(), - newProgram.writeRef(), + composite.writeRef(), outDiagnostic.writeRef()); - linkedSlangProgram = newProgram; + if (SLANG_FAILED(res)) + { + fprintf( + stderr, + "error: Failed to create composite: %s\n", + outDiagnostic ? (char*)outDiagnostic->getBufferPointer() + : "(no diagnostic output)"); + return res; + } + res = composite->link(linkedSlangProgram.writeRef(), outDiagnostic.writeRef()); + if (SLANG_FAILED(res)) + { + fprintf( + stderr, + "error: Failed to link program: %s\n", + outDiagnostic ? (char*)outDiagnostic->getBufferPointer() + : "(no diagnostic output)"); + } } + out.set(linkedSlangProgram); return SLANG_OK; } @@ -348,13 +548,13 @@ static SlangResult compileProgram( // SLANG_RETURN_ON_FAIL(_compileProgramImpl(globalSession, options, input, request, out)); - out.m_requestDEPRECATED = slangOutput.m_requestDEPRECATED; - // slangOutput.desc.slangGlobalScope and slangOutput.slangProgram are the same object, but - // the latter is a ComPtr while the former isn't. Therefore we need to detach so that the - // object doesn't get destroyed. + out.m_session = slangOutput.m_session; + // slangOutput.desc.slangGlobalScope and slangOutput.slangProgram are the same object, + // but the latter is a ComPtr while the former isn't. Therefore we need to detach so + // that the object doesn't get destroyed. SLANG_ASSERT(slangOutput.desc.slangGlobalScope == slangOutput.slangProgram.get()); out.desc.slangGlobalScope = slangOutput.slangProgram.detach(); - slangOutput.m_requestDEPRECATED = nullptr; + slangOutput.m_session = nullptr; return SLANG_OK; } } diff --git a/tools/render-test/slang-support.h b/tools/render-test/slang-support.h index 60e63b57f..916166c3a 100644 --- a/tools/render-test/slang-support.h +++ b/tools/render-test/slang-support.h @@ -67,7 +67,7 @@ struct ShaderCompilerUtil ComPtr<slang::IComponentType> slangProgram; ShaderProgramDesc desc = {}; - ComPtr<SlangCompileRequest> m_requestDEPRECATED = nullptr; + ComPtr<slang::ISession> m_session = nullptr; slang::IGlobalSession* globalSession = nullptr; }; |
