From d40931cc8bde13520ea45769cf94e7cc6cc9065f Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Fri, 15 Mar 2024 08:48:41 +0800 Subject: Mesh shader refactoring and bugfixes (#3702) --- source/slang/core.meta.slang | 25 ++- source/slang/slang-check-decl.cpp | 4 +- source/slang/slang-diagnostic-defs.h | 2 +- source/slang/slang-emit-c-like.cpp | 15 ++ source/slang/slang-emit-hlsl.cpp | 7 +- source/slang/slang-ir-glsl-legalize.cpp | 209 +++++++++++---------- source/slang/slang-ir-inst-defs.h | 1 + source/slang/slang-ir-insts.h | 10 +- source/slang/slang-ir-spirv-legalize.cpp | 24 ++- source/slang/slang-parameter-binding.cpp | 7 + .../rasterization/mesh/component-write.slang | 4 +- tests/pipeline/rasterization/mesh/dead-loop.slang | 82 ++++++++ tests/pipeline/rasterization/mesh/hello.slang | 4 +- .../pipeline/rasterization/mesh/hlsl-syntax.slang | 2 +- .../mesh/nested-component-write.slang | 4 +- .../rasterization/mesh/passing-outputs.slang | 16 +- .../rasterization/mesh/primitive-output.slang | 6 +- tests/pipeline/rasterization/mesh/simple.slang | 4 +- .../rasterization/mesh/swizzled-store.slang | 4 +- .../rasterization/mesh/task-groupshared.slang | 4 +- .../pipeline/rasterization/mesh/task-simple.slang | 4 +- 21 files changed, 299 insertions(+), 139 deletions(-) create mode 100644 tests/pipeline/rasterization/mesh/dead-loop.slang diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 237daac56..e55206ca9 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -1255,12 +1255,15 @@ struct ParameterBlock {} __generic __magic_type(VerticesType) __intrinsic_type($(kIROp_VerticesType)) -struct Vertices +[__NonCopyableType] +struct OutputVertices { __subscript(uint index) -> T { - // TODO: Ellie make sure these remains write only - __intrinsic_op($(kIROp_GetElementPtr)) + // TODO: Make sure this remains write only, we can't do this with just + // a 'set' operation as it's legal to only write to part of the output + // buffer, or part of the output buffer at a time. + __intrinsic_op($(kIROp_MeshOutputRef)) ref; } }; @@ -1268,24 +1271,28 @@ struct Vertices __generic __magic_type(IndicesType) __intrinsic_type($(kIROp_IndicesType)) -struct Indices +[__NonCopyableType] +struct OutputIndices { __subscript(uint index) -> T { - // TODO: Ellie: It's illegal to not write out the whole primitive at once, should we use set over ref? - __intrinsic_op($(kIROp_GetElementPtr)) - ref; + // It's illegal to not write out the entire primitive at once, so limit + // this to set + [mutating] + __intrinsic_op($(kIROp_MeshOutputSet)) + set; } }; __generic __magic_type(PrimitivesType) __intrinsic_type($(kIROp_PrimitivesType)) -struct Primitives +[__NonCopyableType] +struct OutputPrimitives { __subscript(uint index) -> T { - __intrinsic_op($(kIROp_GetElementPtr)) + __intrinsic_op($(kIROp_MeshOutputRef)) ref; } }; diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 88a707ed8..093e2599f 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -7032,7 +7032,9 @@ namespace Slang { return; } - if(!varDecl->findModifier()) + // HLSL requires an 'out' modifier here, but since we don't operate + // under such strict compatability we can just not warn here. + if(!varDecl->findModifier() && modifier) { getSink()->diagnose(varDecl, Diagnostics::meshOutputMustBeOut); } diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 5b66a0f91..47c75ab0c 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -782,7 +782,7 @@ DIAGNOSTIC(52007, Error, typeCannotBeUsedInDynamicDispatch, "failed to generate DIAGNOSTIC(52008, Error, dynamicDispatchOnSpecializeOnlyInterface, "type '$0' is marked for specialization only, but dynamic dispatch is needed for the call.") DIAGNOSTIC(53001, Error, invalidTypeMarshallingForImportedDLLSymbol, "invalid type marshalling in imported func $0.") -DIAGNOSTIC(54001, Error, meshOutputMustBeOut, "Mesh shader outputs must be declared with 'out'.") +DIAGNOSTIC(54001, Warning, meshOutputMustBeOut, "Mesh shader outputs must be declared with 'out'.") DIAGNOSTIC(54002, Error, meshOutputMustBeArray, "HLSL style mesh shader outputs must be arrays") DIAGNOSTIC(54003, Error, meshOutputArrayMustHaveSize, "HLSL style mesh shader output arrays must have a length specified") DIAGNOSTIC(54004, Warning, unnecessaryHLSLMeshOutputModifier, "Unnecessary HLSL style mesh shader output modifier") diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index 44d74f219..2019bfa8c 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -2409,6 +2409,7 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO break; } case kIROp_GetElement: + case kIROp_MeshOutputRef: case kIROp_GetElementPtr: case kIROp_ImageSubscript: // HACK: deal with translation of GLSL geometry shader input arrays. @@ -2904,6 +2905,20 @@ void CLikeSourceEmitter::_emitInst(IRInst* inst) m_writer->emit(";\n"); } break; + case kIROp_MeshOutputSet: + { + auto ii = (IRMeshOutputSet*)inst; + auto subscriptOuter = getInfo(EmitOp::General); + auto subscriptPrec = getInfo(EmitOp::Postfix); + emitOperand(ii->getBase(), leftSide(subscriptOuter, subscriptPrec)); + m_writer->emit("["); + emitOperand(ii->getIndex(), getInfo(EmitOp::General)); + m_writer->emit("]"); + m_writer->emit(" = "); + emitOperand(ii->getElementValue(), getInfo(EmitOp::General)); + m_writer->emit(";\n"); + } + break; } } diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp index fcab737e1..cf1ca794b 100644 --- a/source/slang/slang-emit-hlsl.cpp +++ b/source/slang/slang-emit-hlsl.cpp @@ -1206,10 +1206,11 @@ void HLSLSourceEmitter::emitMeshShaderModifiersImpl(IRInst* varInst) { if(auto modifier = varInst->findDecoration()) { + // DXC requires that mesh payload parameters have "out" specified const char* s = - as(modifier) ? "vertices " - : as(modifier) ? "indices " - : as(modifier) ? "primitives " + as(modifier) ? "out vertices " + : as(modifier) ? "out indices " + : as(modifier) ? "out primitives " : nullptr; SLANG_ASSERT(s && "Unhandled type of mesh output decoration"); m_writer->emit(s); diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index e40dc33ff..c9bc1339b 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -2106,106 +2106,118 @@ static void legalizeMeshOutputParam( // the writes may only be writing to parts of the output struct, or may not // be writes at all (i.e. being passed as an out paramter). // - traverseUsers(g, [&](IRInst* u) - { - auto l = as(u); - SLANG_ASSERT(l && "Mesh Output sentinel parameter wasn't used in a load"); - - std::function assignUses = - [&](ScalarizedVal& d, IRInst* a) + std::function assignUses = + [&](ScalarizedVal& d, IRInst* a) + { + // If we're just writing to an address, we can seamlessly + // replace it with the address to the SOA representation. + // GLSL's `out` function parameters have copy-out semantics, so + // this is all above board. + if(d.flavor == ScalarizedVal::Flavor::address) + { + IRBuilderInsertLocScope locScope{builder}; + builder->setInsertBefore(a); + a->replaceUsesWith(d.irValue); + a->removeAndDeallocate(); + return; + } + // Otherwise, go through the uses one by one and see what we can do + traverseUsers(a, [&](IRInst* s) { - // If we're just writing to an address, we can seamlessly - // replace it with the address to the SOA representation. - // GLSL's `out` function parameters have copy-out semantics, so - // this is all above board. - if(d.flavor == ScalarizedVal::Flavor::address) + IRBuilderInsertLocScope locScope{builder}; + builder->setInsertBefore(s); + if(auto m = as(s)) { - IRBuilderInsertLocScope locScope{builder}; - builder->setInsertBefore(a); - a->replaceUsesWith(d.irValue); - a->removeAndDeallocate(); - return; + auto key = as(m->getField()); + SLANG_ASSERT(key && "Result of getField wasn't a struct key"); + + auto d_ = extractField(builder, d, kMaxUInt, key); + assignUses(d_, m); } - // Otherwise, go through the uses one by one and see what we can do - traverseUsers(a, [&](IRInst* s) + else if(auto ref = as(s)) { - IRBuilderInsertLocScope locScope{builder}; - builder->setInsertBefore(s); - if(auto m = as(s)) - { - auto key = as(m->getField()); - SLANG_ASSERT(key && "Result of getField wasn't a struct key"); - - auto d_ = extractField(builder, d, kMaxUInt, key); - assignUses(d_, m); - } - else if(auto g = as(s)) - { - // Writing to something like `struct Vertex{ Foo foo[10]; }` - // This case is also what's taken in the initial - // traversal, as every mesh output is an array. - auto elemType = composeGetters( - g, - &IRInst::getFullType, - &IRPtrTypeBase::getValueType); - auto d_ = getSubscriptVal(builder, elemType, d, g->getIndex()); - assignUses(d_, g); - } - else if(auto store = as(s)) - { - // Store using the SOA representation + auto elemType = composeGetters( + ref, + &IRInst::getFullType, + &IRPtrTypeBase::getValueType); + auto d_ = getSubscriptVal(builder, elemType, d, ref->getIndex()); + assignUses(d_, ref); + } + else if(auto set = as(s)) + { + auto elemType = composeGetters( + set, + &IRInst::getFullType, + &IRPtrTypeBase::getValueType); + auto d_ = getSubscriptVal(builder, elemType, d, set->getIndex()); + assign(builder, d_, ScalarizedVal::value(set->getElementValue())); + set->removeAndDeallocate(); + } + else if(auto g = as(s)) + { + // Writing to something like `struct Vertex{ Foo foo[10]; }` + // This case is also what's taken in the initial + // traversal, as every mesh output is an array. + auto elemType = composeGetters( + g, + &IRInst::getFullType, + &IRPtrTypeBase::getValueType); + auto d_ = getSubscriptVal(builder, elemType, d, g->getIndex()); + assignUses(d_, g); + } + else if(auto store = as(s)) + { + // Store using the SOA representation - assign( - builder, - d, - ScalarizedVal::value(store->getVal())); + assign( + builder, + d, + ScalarizedVal::value(store->getVal())); - // Stores aren't used, safe to remove here without checking - store->removeAndDeallocate(); - } - else if(auto c = as(s)) + // Stores aren't used, safe to remove here without checking + store->removeAndDeallocate(); + } + else if(auto c = as(s)) + { + // Translate + // foo(vertices[n]) + // to + // tmp + // foo(tmp) + // vertices[n] = tmp; + // + // This has copy-out semantics, which is really the + // best we can hope for without going and + // specializing foo. + auto ptr = as(a->getFullType()); + SLANG_ASSERT(ptr && "Mesh output parameter was passed by value"); + auto t = ptr->getValueType(); + auto tmp = builder->emitVar(t); + for(UInt i = 0; i < c->getOperandCount(); i++) { - // Translate - // foo(vertices[n]) - // to - // tmp - // foo(tmp) - // vertices[n] = tmp; - // - // This has copy-out semantics, which is really the - // best we can hope for without going and - // specializing foo. - auto ptr = as(a->getFullType()); - SLANG_ASSERT(ptr && "Mesh output parameter was passed by value"); - auto t = ptr->getValueType(); - auto tmp = builder->emitVar(t); - for(UInt i = 0; i < c->getOperandCount(); i++) + if(c->getOperand(i) == a) { - if(c->getOperand(i) == a) - { - c->setOperand(i, tmp); - } + c->setOperand(i, tmp); } - builder->setInsertAfter(c); - assign(builder, d, - ScalarizedVal::value(builder->emitLoad(tmp))); - } - else if(const auto swiz = as(s)) - { - SLANG_UNEXPECTED("Swizzled store to a non-address ScalarizedVal"); } - else - { - SLANG_UNEXPECTED("Unhandled use of mesh output parameter during GLSL legalization"); - } - }); - - SLANG_ASSERT(!a->hasUses()); - a->removeAndDeallocate(); - }; + builder->setInsertAfter(c); + assign(builder, d, + ScalarizedVal::value(builder->emitLoad(tmp))); + } + else if(const auto swiz = as(s)) + { + SLANG_UNEXPECTED("Swizzled store to a non-address ScalarizedVal"); + } + else + { + SLANG_UNEXPECTED("Unhandled use of mesh output parameter during GLSL legalization"); + } + }); - assignUses(globalOutputVal, l); - }); + SLANG_ASSERT(!a->hasUses()); + a->removeAndDeallocate(); + }; + assignUses(globalOutputVal, g); // // GLSL requires that builtins are written to a block named @@ -2348,15 +2360,18 @@ static void legalizeMeshOutputParam( { traverseUsers(builtin.param, [&](IRInst* u) { - auto p = as(u); - SLANG_ASSERT(p && "Mesh Output sentinel parameter wasn't used as an array"); - IRBuilderInsertLocScope locScope{builder}; - builder->setInsertBefore(p); - auto e = builder->emitElementAddress(builder->getPtrType(meshOutputBlockType), blockParam, p->getIndex()); + builder->setInsertBefore(u); + IRInst* index; + if(const auto p = as(u)) + index = p->getIndex(); + else if(const auto m = as(u)) + index = m->getIndex(); + else + SLANG_UNEXPECTED("Illegal use of mesh output parameter"); + auto e = builder->emitElementAddress(builder->getPtrType(meshOutputBlockType), blockParam, index); auto a = builder->emitFieldAddress(builder->getPtrType(builtin.type), e, builtin.key); - - p->replaceUsesWith(a); + u->replaceUsesWith(a); }); } } @@ -2461,7 +2476,7 @@ void legalizeEntryPointParameterForGLSL( // - Geometry shader output streams // - Mesh shader outputs // - Mesh shader payload input - if (auto paramPtrType = as(paramType)) + if (auto paramPtrType = as(paramType)) { valueType = paramPtrType->getValueType(); } diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 977fca904..aa0929a57 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -478,6 +478,7 @@ INST(AtomicCounterDecrement, AtomicCounterDecrement, 1, 0) INST(GetNaturalStride, getNaturalStride, 1, 0) INST(MeshOutputRef, meshOutputRef, 2, 0) +INST(MeshOutputSet, meshOutputSet, 3, 0) // Construct a vector from a scalar // diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index a85b279b8..3ae9f04d7 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -1379,12 +1379,20 @@ struct IRGLPositionInputDecoration : public IRDecoration struct IRMeshOutputRef : public IRInst { - enum { kOp = kIROp_MeshOutputRef }; IR_LEAF_ISA(MeshOutputRef) + IRInst* getBase() { return getOperand(0); } IRInst* getIndex() { return getOperand(1); } IRInst* getOutputType() { return cast(getFullType())->getValueType(); } }; +struct IRMeshOutputSet : public IRInst +{ + IR_LEAF_ISA(MeshOutputSet) + IRInst* getBase() { return getOperand(0); } + IRInst* getIndex() { return getOperand(1); } + IRInst* getElementValue() { return getOperand(2); } +}; + /// An attribute that can be attached to another instruction as an operand. /// /// Attributes serve a similar role to decorations, in that both are ways diff --git a/source/slang/slang-ir-spirv-legalize.cpp b/source/slang/slang-ir-spirv-legalize.cpp index 6dbbbcd1f..4dde2a035 100644 --- a/source/slang/slang-ir-spirv-legalize.cpp +++ b/source/slang/slang-ir-spirv-legalize.cpp @@ -1064,6 +1064,22 @@ struct SPIRVLegalizationContext : public SourceEmitterBase processGetElementPtrImpl(gepInst, gepInst->getBase(), gepInst->getIndex()); } + void processMeshOutputGetElementPtr(IRMeshOutputRef* gepInst) + { + processGetElementPtrImpl(gepInst, gepInst->getBase(), gepInst->getIndex()); + } + + void processMeshOutputSet(IRMeshOutputSet* setInst) + { + IRBuilder builder(m_sharedContext->m_irModule); + builder.setInsertBefore(setInst); + const auto p = builder.emitElementAddress(setInst->getBase(), setInst->getIndex()); + const auto s = builder.emitStore(p, setInst->getElementValue()); + setInst->removeAndDeallocate(); + addToWorkList(p); + addToWorkList(s); + } + void processGetOffsetPtr(IRInst* offsetPtrInst) { auto ptrOperandType = as(offsetPtrInst->getOperand(0)->getDataType()); @@ -1752,7 +1768,13 @@ struct SPIRVLegalizationContext : public SourceEmitterBase processImageSubscript(as(inst)); break; case kIROp_RWStructuredBufferGetElementPtr: - processRWStructuredBufferGetElementPtr(as(inst)); + processRWStructuredBufferGetElementPtr(cast(inst)); + break; + case kIROp_MeshOutputRef: + processMeshOutputGetElementPtr(cast(inst)); + break; + case kIROp_MeshOutputSet: + processMeshOutputSet(cast(inst)); break; case kIROp_RWStructuredBufferLoad: case kIROp_StructuredBufferLoad: diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index ebaa58adb..5d7aaa651 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -2278,6 +2278,13 @@ static RefPtr computeEntryPointParameterTypeLayout( state.directionMask |= kEntryPointParameterDirection_Output; } + // For the purposes of type layout, mesh shader outputs are always + // treated as output only, despite missing an 'out' modifier + if(as(paramDeclRef.getDecl()->getType())) + { + state.directionMask = kEntryPointParameterDirection_Output; + } + return processEntryPointVaryingParameterDecl( context, paramDeclRef.getDecl(), diff --git a/tests/pipeline/rasterization/mesh/component-write.slang b/tests/pipeline/rasterization/mesh/component-write.slang index a34f6ee31..afa5cd291 100644 --- a/tests/pipeline/rasterization/mesh/component-write.slang +++ b/tests/pipeline/rasterization/mesh/component-write.slang @@ -29,8 +29,8 @@ const static uint MAX_PRIMS = 1; [numthreads(3, 1, 1)] void main( in uint tig : SV_GroupIndex, - out Vertices verts, - out Indices triangles + OutputVertices verts, + OutputIndices triangles ) { const uint numVertices = 3; diff --git a/tests/pipeline/rasterization/mesh/dead-loop.slang b/tests/pipeline/rasterization/mesh/dead-loop.slang new file mode 100644 index 000000000..875a12db5 --- /dev/null +++ b/tests/pipeline/rasterization/mesh/dead-loop.slang @@ -0,0 +1,82 @@ +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK): -mesh -output-using-type -dx12 -use-dxil -profile sm_6_6 -render-features mesh-shader +//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK): -mesh -output-using-type -vk -profile glsl_450+spirv_1_4 -render-features mesh-shader + +// See https://github.com/shader-slang/slang/issues/3401 + +// CHECK: 0 +// CHECK-NEXT: 1 +// CHECK-NEXT: 4 +// CHECK-NEXT: 9 + +//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer + +RWStructuredBuffer outputBuffer; + +cbuffer Uniforms +{ + float4x4 modelViewProjection; +} + +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 : Color; + int index : Index; + int value : Value; +}; + +const static uint MAX_VERTS = 12; +const static uint MAX_PRIMS = 4; + +[outputtopology("triangle")] +[shader("mesh")] +[numthreads(3, 1, 1)] +void meshMain( + in uint tig : SV_GroupIndex, + OutputVertices verts, + OutputIndices triangles) +{ + const uint numVertices = 12; + const uint numPrimitives = 4; + SetMeshOutputCounts(numVertices, numPrimitives); + + for(uint i = tig; i < numVertices; ++i) + { + const int tri = i / 3; + verts[i] = {float4(positions[i % 3], 0, 1), colors[i % 3], tri, tri*tri}; + } + + for(uint i = tig; i < numPrimitives; ++i) + { + triangles[i] = i * 3 + uint3(0,1,2); + } +} + +// +// Fragment Shader +// + +struct Fragment +{ + float4 color : SV_Target; +}; + +Fragment fragmentMain(Vertex input) +{ + outputBuffer[input.index] = input.value; + + Fragment output; + output.color = float4(input.color, 1.0); + return output; +} diff --git a/tests/pipeline/rasterization/mesh/hello.slang b/tests/pipeline/rasterization/mesh/hello.slang index 54754c42e..54a50079d 100644 --- a/tests/pipeline/rasterization/mesh/hello.slang +++ b/tests/pipeline/rasterization/mesh/hello.slang @@ -39,8 +39,8 @@ const static uint MAX_PRIMS = 1; [numthreads(3, 1, 1)] void main( in uint tig : SV_GroupIndex, - out Vertices verts, - out Indices triangles + OutputVertices verts, + OutputIndices triangles ) { const uint numVertices = 3; diff --git a/tests/pipeline/rasterization/mesh/hlsl-syntax.slang b/tests/pipeline/rasterization/mesh/hlsl-syntax.slang index a0b397ca2..eaa853a04 100644 --- a/tests/pipeline/rasterization/mesh/hlsl-syntax.slang +++ b/tests/pipeline/rasterization/mesh/hlsl-syntax.slang @@ -26,7 +26,7 @@ const static uint MAX_VERTS = 3; const static uint MAX_PRIMS = 1; // Test that we can convert the HLSL Syntax to the typed syntax -void foo(uint tig, out Vertices verts) +void foo(uint tig, OutputVertices verts) { if(tig < 3) { verts[tig] = {float4(positions[tig], 0, 1), colors[tig]}; diff --git a/tests/pipeline/rasterization/mesh/nested-component-write.slang b/tests/pipeline/rasterization/mesh/nested-component-write.slang index 68bb6dfb9..f55d5365e 100644 --- a/tests/pipeline/rasterization/mesh/nested-component-write.slang +++ b/tests/pipeline/rasterization/mesh/nested-component-write.slang @@ -33,8 +33,8 @@ const static uint MAX_PRIMS = 1; [numthreads(3, 1, 1)] void main( in uint tig : SV_GroupIndex, - out Vertices verts, - out Indices triangles + OutputVertices verts, + OutputIndices triangles ) { SetMeshOutputCounts(3, 1); diff --git a/tests/pipeline/rasterization/mesh/passing-outputs.slang b/tests/pipeline/rasterization/mesh/passing-outputs.slang index 20e6abe0b..3fd6fc4a0 100644 --- a/tests/pipeline/rasterization/mesh/passing-outputs.slang +++ b/tests/pipeline/rasterization/mesh/passing-outputs.slang @@ -28,7 +28,7 @@ struct Vertex Texes ts : Coord; }; -void everything(out Vertices vs) +void everything(OutputVertices vs) { vs[0] = {float4(0), float3(1)}; } @@ -56,32 +56,32 @@ void write_struct(out Texes t) } // Split out the things to test to avoid main becoming an unreadable jumble -void a(out Vertices vs) +void a(OutputVertices vs) { // Test passing a reference to the entire array everything(vs); } -void b(out Vertices vs) +void b(OutputVertices vs) { // test passing two references to the same element just_two(vs[0], vs[0]); } -void c(out Vertices vs, uint tig) +void c(OutputVertices vs, uint tig) { // Test passing a reference to an element just_one(vs[tig]); } -void d(out Vertices vs, uint tig) +void d(OutputVertices vs, uint tig) { // Test passing references to different elements (to check that the operand // rewriting doesn't mess the order) just_two(vs[tig], vs[0]); } -void e(out Vertices vs, uint tig) +void e(OutputVertices vs, uint tig) { // Test passing a scalar member and a struct member and a struct member's member part_of_one(vs[tig].pos); @@ -93,8 +93,8 @@ void e(out Vertices vs, uint tig) [numthreads(3, 1, 1)] void main( in uint tig : SV_GroupIndex, - out Vertices verts, - out Indices triangles + OutputVertices verts, + OutputIndices triangles ) { const uint numVertices = 3; diff --git a/tests/pipeline/rasterization/mesh/primitive-output.slang b/tests/pipeline/rasterization/mesh/primitive-output.slang index fdbcf6912..99d4f63b9 100644 --- a/tests/pipeline/rasterization/mesh/primitive-output.slang +++ b/tests/pipeline/rasterization/mesh/primitive-output.slang @@ -36,9 +36,9 @@ const static uint MAX_PRIMS = 1; [numthreads(3, 1, 1)] void main( in uint tig : SV_GroupIndex, - out Indices triangles, - out Vertices verts, - out Primitives primitives + OutputIndices triangles, + OutputVertices verts, + OutputPrimitives primitives ) { const uint numVertices = 3; diff --git a/tests/pipeline/rasterization/mesh/simple.slang b/tests/pipeline/rasterization/mesh/simple.slang index 00047aaad..de1195d71 100644 --- a/tests/pipeline/rasterization/mesh/simple.slang +++ b/tests/pipeline/rasterization/mesh/simple.slang @@ -50,8 +50,8 @@ const static uint MAX_PRIMS = 4; [numthreads(12, 1, 1)] void meshMain( in uint tig : SV_GroupIndex, - out Vertices verts, - out Indices triangles) + OutputVertices verts, + OutputIndices triangles) { const uint numVertices = 12; const uint numPrimitives = 4; diff --git a/tests/pipeline/rasterization/mesh/swizzled-store.slang b/tests/pipeline/rasterization/mesh/swizzled-store.slang index f85f9ed62..713416430 100644 --- a/tests/pipeline/rasterization/mesh/swizzled-store.slang +++ b/tests/pipeline/rasterization/mesh/swizzled-store.slang @@ -11,8 +11,8 @@ const static uint MAX_PRIMS = 1; [numthreads(3, 1, 1)] void main( in uint tig : SV_GroupIndex, - out Vertices verts : SV_Position, - out Indices triangles + OutputVertices verts : SV_Position, + OutputIndices triangles ) { const uint numVertices = 3; diff --git a/tests/pipeline/rasterization/mesh/task-groupshared.slang b/tests/pipeline/rasterization/mesh/task-groupshared.slang index c633aeeb1..518d94bfb 100644 --- a/tests/pipeline/rasterization/mesh/task-groupshared.slang +++ b/tests/pipeline/rasterization/mesh/task-groupshared.slang @@ -71,8 +71,8 @@ const static uint MAX_PRIMS = 4; void meshMain( in uint tig : SV_GroupIndex, in payload MeshPayload meshPayload, - out Vertices verts, - out Indices triangles) + OutputVertices verts, + OutputIndices triangles) { const uint numVertices = 12; const uint numPrimitives = 4; diff --git a/tests/pipeline/rasterization/mesh/task-simple.slang b/tests/pipeline/rasterization/mesh/task-simple.slang index 58ec9a527..dc3de82c0 100644 --- a/tests/pipeline/rasterization/mesh/task-simple.slang +++ b/tests/pipeline/rasterization/mesh/task-simple.slang @@ -73,8 +73,8 @@ void meshMain( // Check that we correctly generate the specific 'in payload' that HLSL // requires: // HLSL: , in payload MeshPayload - out Vertices verts, - out Indices triangles) + OutputVertices verts, + OutputIndices triangles) { const uint numVertices = 12; const uint numPrimitives = 4; -- cgit v1.2.3