diff options
| -rw-r--r-- | build/visual-studio/slang/slang.vcxproj | 2 | ||||
| -rw-r--r-- | build/visual-studio/slang/slang.vcxproj.filters | 6 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 6 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 5 | ||||
| -rw-r--r-- | source/slang/slang-ir-check-unsupported-inst.cpp | 71 | ||||
| -rw-r--r-- | source/slang/slang-ir-check-unsupported-inst.h | 10 | ||||
| -rw-r--r-- | source/slang/slang-ir-spirv-legalize.cpp | 6 | ||||
| -rw-r--r-- | source/slang/slang-ir-util.cpp | 20 | ||||
| -rw-r--r-- | source/slang/slang-ir-util.h | 2 | ||||
| -rw-r--r-- | tests/bugs/gh-3780.slang | 58 | ||||
| -rw-r--r-- | tests/bugs/gh-3781.slang | 22 | ||||
| -rw-r--r-- | tests/bugs/gh-3783.slang | 17 | ||||
| -rw-r--r-- | tests/cross-compile/array-of-buffers.slang | 7 | ||||
| -rw-r--r-- | tests/diagnostics/recursion.slang | 15 | ||||
| -rw-r--r-- | tests/spirv/scalar-buffer-packing.slang | 2 |
16 files changed, 245 insertions, 6 deletions
diff --git a/build/visual-studio/slang/slang.vcxproj b/build/visual-studio/slang/slang.vcxproj index 947ab4b5f..c503e8f4d 100644 --- a/build/visual-studio/slang/slang.vcxproj +++ b/build/visual-studio/slang/slang.vcxproj @@ -373,6 +373,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla <ClInclude Include="..\..\..\source\slang\slang-ir-bit-field-accessors.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-byte-address-legalize.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-check-differentiability.h" />
+ <ClInclude Include="..\..\..\source\slang\slang-ir-check-unsupported-inst.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-cleanup-void.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-clone.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-collect-global-uniforms.h" />
@@ -597,6 +598,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla <ClCompile Include="..\..\..\source\slang\slang-ir-bit-field-accessors.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-byte-address-legalize.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-check-differentiability.cpp" />
+ <ClCompile Include="..\..\..\source\slang\slang-ir-check-unsupported-inst.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-cleanup-void.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-clone.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-collect-global-uniforms.cpp" />
diff --git a/build/visual-studio/slang/slang.vcxproj.filters b/build/visual-studio/slang/slang.vcxproj.filters index 85476ba7b..9c274990d 100644 --- a/build/visual-studio/slang/slang.vcxproj.filters +++ b/build/visual-studio/slang/slang.vcxproj.filters @@ -207,6 +207,9 @@ <ClInclude Include="..\..\..\source\slang\slang-ir-check-differentiability.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\slang\slang-ir-check-unsupported-inst.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\slang\slang-ir-cleanup-void.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -875,6 +878,9 @@ <ClCompile Include="..\..\..\source\slang\slang-ir-check-differentiability.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\slang\slang-ir-check-unsupported-inst.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\slang\slang-ir-cleanup-void.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index db17c92a0..ba57e63f9 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -792,6 +792,8 @@ DIAGNOSTIC(54004, Warning, unnecessaryHLSLMeshOutputModifier, "Unnecessary HLSL DIAGNOSTIC(55101, Error, invalidTorchKernelReturnType, "'$0' is not a valid return type for a pytorch kernel function.") DIAGNOSTIC(55102, Error, invalidTorchKernelParamType, "'$0' is not a valid parameter type for a pytorch kernel function.") +DIAGNOSTIC(55200, Error, unsupportedBuiltinType, "'$0' is not a supported builtin type for the target.") +DIAGNOSTIC(55201, Error, unsupportedRecursion, "recursion detected in call to '$0', but the current code generation target does not allow recursion.") DIAGNOSTIC(56001, Error, unableToAutoMapCUDATypeToHostType, "Could not automatically map '$0' to a host type. Automatic binding generation failed for '$1'") DIAGNOSTIC(57001, Warning, spirvOptFailed, "spirv-opt failed. $0") diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index afb1b3a63..6ecffecd1 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -3060,6 +3060,12 @@ struct SPIRVEmitContext case Stage::Callable: requireSPIRVCapability(SpvCapabilityRayTracingKHR); ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_ray_tracing")); + break; + case Stage::Mesh: + case Stage::Amplification: + requireSPIRVCapability(SpvCapabilityMeshShadingEXT); + ensureExtensionDeclaration(UnownedStringSlice("SPV_EXT_mesh_shader")); + break; default: break; } diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index ee38996e6..649858e51 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -8,6 +8,7 @@ #include "slang-ir-any-value-inference.h" #include "slang-ir-bind-existentials.h" #include "slang-ir-byte-address-legalize.h" +#include "slang-ir-check-unsupported-inst.h" #include "slang-ir-collect-global-uniforms.h" #include "slang-ir-cleanup-void.h" #include "slang-ir-composite-reg-to-mem.h" @@ -1061,7 +1062,9 @@ Result linkAndOptimizeIR( outLinkedIR.metadata = metadata; - return SLANG_OK; + checkUnsupportedInst(codeGenContext->getTargetReq(), irModule, sink); + + return sink->getErrorCount() == 0 ? SLANG_OK : SLANG_FAIL; } SlangResult CodeGenContext::emitEntryPointsSourceFromIR(ComPtr<IArtifact>& outArtifact) diff --git a/source/slang/slang-ir-check-unsupported-inst.cpp b/source/slang/slang-ir-check-unsupported-inst.cpp new file mode 100644 index 000000000..c89928af5 --- /dev/null +++ b/source/slang/slang-ir-check-unsupported-inst.cpp @@ -0,0 +1,71 @@ +#include "slang-ir-check-unsupported-inst.h" + +#include "slang-ir.h" +#include "slang-ir-util.h" + +namespace Slang +{ + bool isCPUTarget(TargetRequest* targetReq); + + bool checkRecursionImpl(HashSet<IRFunc*>& checkedFuncs, HashSet<IRFunc*>& callStack, IRFunc* func, DiagnosticSink* sink) + { + for (auto block : func->getBlocks()) + { + for (auto inst : block->getChildren()) + { + auto callInst = as<IRCall>(inst); + if (!callInst) + continue; + auto callee = as<IRFunc>(callInst->getCallee()); + if (!callee) + continue; + if (!callStack.add(callee)) + { + sink->diagnose(callInst, Diagnostics::unsupportedRecursion, callee); + return false; + } + if (checkedFuncs.add(callee)) + checkRecursionImpl(checkedFuncs, callStack, callee, sink); + callStack.remove(callee); + } + } + return true; + } + + void checkRecursion(HashSet<IRFunc*>& checkedFuncs, IRFunc* func, DiagnosticSink* sink) + { + HashSet<IRFunc*> callStack; + if (checkedFuncs.add(func)) + { + callStack.add(func); + checkRecursionImpl(checkedFuncs, callStack, func, sink); + } + } + + void checkUnsupportedInst(TargetRequest* target, IRModule* module, DiagnosticSink* sink) + { + HashSet<IRFunc*> checkedFuncsForRecursionDetection; + + for (auto globalInst : module->getGlobalInsts()) + { + switch (globalInst->getOp()) + { + case kIROp_VectorType: + case kIROp_MatrixType: + { + if (!as<IRBasicType>(globalInst->getOperand(0))) + { + sink->diagnose(findFirstUseLoc(globalInst), Diagnostics::unsupportedBuiltinType, globalInst); + } + break; + } + case kIROp_Func: + if (!isCPUTarget(target)) + checkRecursion(checkedFuncsForRecursionDetection, as<IRFunc>(globalInst), sink); + default: + break; + } + } + } + +} diff --git a/source/slang/slang-ir-check-unsupported-inst.h b/source/slang/slang-ir-check-unsupported-inst.h new file mode 100644 index 000000000..b52306566 --- /dev/null +++ b/source/slang/slang-ir-check-unsupported-inst.h @@ -0,0 +1,10 @@ +#pragma once + +namespace Slang +{ + struct IRModule; + class DiagnosticSink; + class TargetRequest; + + void checkUnsupportedInst(TargetRequest* target, IRModule* module, DiagnosticSink* sink); +} diff --git a/source/slang/slang-ir-spirv-legalize.cpp b/source/slang/slang-ir-spirv-legalize.cpp index a7c14242b..2b7e86f47 100644 --- a/source/slang/slang-ir-spirv-legalize.cpp +++ b/source/slang/slang-ir-spirv-legalize.cpp @@ -216,8 +216,12 @@ struct SPIRVLegalizationContext : public SourceEmitterBase auto user = use->getUser(); IRBuilder builder(user); builder.setInsertBefore(user); - if(as<IRGetElement>(user) || as<IRFieldExtract>(user)) + + if((as<IRGetElement>(user) || as<IRFieldExtract>(user)) && + use == user->getOperands()) { + // If the use is the address operand of a getElement or FieldExtract, + // replace the inst with the updated address and continue to follow the use chain. auto basePtrType = as<IRPtrTypeBase>(addr->getDataType()); IRType* ptrType = nullptr; if (basePtrType->hasAddressSpace()) diff --git a/source/slang/slang-ir-util.cpp b/source/slang/slang-ir-util.cpp index 2f059d308..e1eb86508 100644 --- a/source/slang/slang-ir-util.cpp +++ b/source/slang/slang-ir-util.cpp @@ -230,6 +230,18 @@ bool isSimpleDataType(IRType* type) } } +SourceLoc findFirstUseLoc(IRInst* inst) +{ + for (auto use = inst->firstUse; use; use = use->nextUse) + { + if (use->getUser()->sourceLoc.isValid()) + { + return use->getUser()->sourceLoc; + } + } + return inst->sourceLoc; +} + IRInst* hoistValueFromGeneric(IRBuilder& inBuilder, IRInst* value, IRInst*& outSpecializedVal, bool replaceExistingValue) { auto outerGeneric = as<IRGeneric>(findOuterGeneric(value)); @@ -582,14 +594,20 @@ void getTypeNameHint(StringBuilder& sb, IRInst* type) getTypeNameHint(sb, as<IRRateQualifiedType>(type)->getValueType()); break; case kIROp_VectorType: + sb << "vector<"; getTypeNameHint(sb, type->getOperand(0)); + sb << ","; getTypeNameHint(sb, as<IRVectorType>(type)->getElementCount()); + sb << ">"; break; case kIROp_MatrixType: + sb << "matrix<"; getTypeNameHint(sb, type->getOperand(0)); + sb << ","; getTypeNameHint(sb, as<IRMatrixType>(type)->getRowCount()); - sb << "x"; + sb << ","; getTypeNameHint(sb, as<IRMatrixType>(type)->getColumnCount()); + sb << ">"; break; case kIROp_IntLit: sb << as<IRIntLit>(type)->getValue(); diff --git a/source/slang/slang-ir-util.h b/source/slang/slang-ir-util.h index fd34d81f7..40ba783b9 100644 --- a/source/slang/slang-ir-util.h +++ b/source/slang/slang-ir-util.h @@ -89,6 +89,8 @@ bool isValueType(IRInst* type); bool isSimpleDataType(IRType* type); +SourceLoc findFirstUseLoc(IRInst* inst); + inline bool isChildInstOf(IRInst* inst, IRInst* parent) { while (inst) diff --git a/tests/bugs/gh-3780.slang b/tests/bugs/gh-3780.slang new file mode 100644 index 000000000..62a9542d7 --- /dev/null +++ b/tests/bugs/gh-3780.slang @@ -0,0 +1,58 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly + +// CHECK: OpEntryPoint + +const static float2 positions[3] = { + float2(0.0, -0.5), + float2(0.5, 0.5), + float2(-0.5, 0.5) +}; + +const static float3 colors[3] = { + float3(1.0, 1.0, 0.0), + float3(0.0, 1.0, 1.0), + float3(1.0, 0.0, 1.0) +}; + +struct Vertex +{ + float4 pos : SV_Position; + float3 color; +}; + +const static uint MAX_VERTS = 3; +const static uint MAX_PRIMS = 1; + +[outputtopology("triangle")] +[numthreads(3, 1, 1)] +[shader("mesh")] +void entry_mesh( + in uint tig : SV_GroupIndex, + out vertices Vertex verts[MAX_VERTS], + out indices uint3 triangles[MAX_PRIMS]) +{ + const uint numVertices = 3; + const uint numPrimitives = 1; + SetMeshOutputCounts(numVertices, numPrimitives); + + if(tig < numVertices) { + verts[tig] = {float4(positions[tig], 0, 1), colors[tig]}; + } + + if(tig < numPrimitives) { + triangles[tig] = uint3(0,1,2); + } +} + +struct FragmentOut +{ + [[vk::location(0)]] float3 color; +}; + +[shader("fragment")] +FragmentOut entry_fragment(in Vertex vertex) +{ + FragmentOut frag_out; + frag_out.color = float3(1,1,1); + return frag_out; +}
\ No newline at end of file diff --git a/tests/bugs/gh-3781.slang b/tests/bugs/gh-3781.slang new file mode 100644 index 000000000..89b2957b9 --- /dev/null +++ b/tests/bugs/gh-3781.slang @@ -0,0 +1,22 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly + +// CHECK: OpEntryPoint + +struct Vertex +{ + float4 pos : SV_Position; + [[vk::location(0)]] float3 color; +}; + +const static uint MAX_VERTS = 3; +const static uint MAX_PRIMS = 1; + +[outputtopology("triangle")] +[numthreads(3, 1, 1)] +[shader("mesh")] +void entry_mesh( + in uint tig : SV_GroupIndex, + out vertices Vertex verts[MAX_VERTS], + out indices uint3 triangles[MAX_PRIMS]) +{ +}
\ No newline at end of file diff --git a/tests/bugs/gh-3783.slang b/tests/bugs/gh-3783.slang new file mode 100644 index 000000000..9e343b22f --- /dev/null +++ b/tests/bugs/gh-3783.slang @@ -0,0 +1,17 @@ +//TEST:SIMPLE(filecheck=CHECK):-target spirv -emit-spirv-directly + +// CHECK: error 55200: + +RWStructuredBuffer<float> outputBuffer; + +float testFunc(vector<vector<float, 3>, 2> v1) +{ + return v1.x.x; +} + +[numthreads(1,1,1)] +void main(uint v : SV_DispatchThreadID) +{ + vector<vector<float, 3>, 2> v1 = { { 1, 2, 3 }, { 4, 5, v } }; + outputBuffer[0] = testFunc(v1); +}
\ No newline at end of file diff --git a/tests/cross-compile/array-of-buffers.slang b/tests/cross-compile/array-of-buffers.slang index 31738ccfc..bf2574f29 100644 --- a/tests/cross-compile/array-of-buffers.slang +++ b/tests/cross-compile/array-of-buffers.slang @@ -1,7 +1,10 @@ // array-of-buffers.slang -//TEST:CROSS_COMPILE:-target spirv-assembly -entry main -stage fragment -//TEST:CROSS_COMPILE:-target dxil-assembly -entry main -stage fragment -profile sm_6_0 +//TEST:SIMPLE(filecheck=SPIRV):-target spirv-assembly -entry main -stage fragment +//TEST:SIMPLE(filecheck=DXIL):-target dxil-assembly -entry main -stage fragment -profile sm_6_0 + +// SPIRV: OpEntryPoint +// DXIL: define void @main() // This test ensures that we cross-compile arrays of structured/constant // buffers into appropriate GLSL, where these are not first-class types. diff --git a/tests/diagnostics/recursion.slang b/tests/diagnostics/recursion.slang new file mode 100644 index 000000000..b5746820e --- /dev/null +++ b/tests/diagnostics/recursion.slang @@ -0,0 +1,15 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly + +// CHECK: error 55201: + +float test<let x : int>() +{ + return test<x>(); +} + +RWStructuredBuffer<float> outputBuffer; +[numthreads(1,1,1)] +void main() +{ + outputBuffer[0] = test<1>(); +}
\ No newline at end of file diff --git a/tests/spirv/scalar-buffer-packing.slang b/tests/spirv/scalar-buffer-packing.slang index bc42cfa39..1224ae664 100644 --- a/tests/spirv/scalar-buffer-packing.slang +++ b/tests/spirv/scalar-buffer-packing.slang @@ -51,6 +51,6 @@ void computeMain() // SPIRV: OpEntryPoint GLCompute -// SPIRV-DAG: %[[STRUCTNAME:[A-Za-z0-9_]+]] = OpTypeStruct %int %_Array_natural_int32 +// SPIRV-DAG: %[[STRUCTNAME:[A-Za-z0-9_]+]] = OpTypeStruct %int %_Array_natural_vector_int_3_2 // SPIRV-DAG: OpMemberDecorate %[[STRUCTNAME:[A-Za-z0-9_]+]] 1 Offset 4 |
