Skip to content

Commit a26b6f4

Browse files
authored
Merge branch 'master' into push-wrqrnwmqxtzm
2 parents 05f5632 + 1e20eed commit a26b6f4

14 files changed

+284
-41
lines changed

source/core/slang-hex-dump-util.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ SlangResult HexDumpUtil::dumpSourceBytes(
7979

8080
// each byte is output as "0xAA, "
8181
// Ends with '\n"
82-
const size_t lineBytes = count * (4 + 1 + 1) * count + 1;
82+
const size_t lineBytes = count * 6 + 1;
8383

8484
char* startDst = writer->beginAppendBuffer(lineBytes);
8585
char* dst = startDst;

source/slang/slang-diagnostic-defs.h

+6
Original file line numberDiff line numberDiff line change
@@ -2437,6 +2437,12 @@ DIAGNOSTIC(
24372437
invalidTessellationDomain,
24382438
"'Domain' should be either 'triangles' or 'quads'.")
24392439

2440+
DIAGNOSTIC(
2441+
50060,
2442+
Error,
2443+
invalidMeshStageOutputTopology,
2444+
"Invalid mesh stage output topology '$0' for target '$1', must be one of: $2")
2445+
24402446
DIAGNOSTIC(
24412447
50082,
24422448
Error,

source/slang/slang-emit-glsl.cpp

+21-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "../core/slang-writer.h"
55
#include "slang-emit-source-writer.h"
66
#include "slang-ir-call-graph.h"
7+
#include "slang-ir-entry-point-decorations.h"
78
#include "slang-ir-layout.h"
89
#include "slang-ir-util.h"
910
#include "slang-legalize-types.h"
@@ -1415,6 +1416,23 @@ void GLSLSourceEmitter::emitParameterGroupImpl(
14151416
_emitGLSLParameterGroup(varDecl, type);
14161417
}
14171418

1419+
static String getOutputTopologyString(OutputTopologyType topology)
1420+
{
1421+
SLANG_ASSERT(topology != OutputTopologyType::Unknown);
1422+
1423+
switch (topology)
1424+
{
1425+
case OutputTopologyType::Point:
1426+
return "points";
1427+
case OutputTopologyType::Line:
1428+
return "lines";
1429+
case OutputTopologyType::Triangle:
1430+
return "triangles";
1431+
default:
1432+
return "";
1433+
}
1434+
}
1435+
14181436
void GLSLSourceEmitter::emitEntryPointAttributesImpl(
14191437
IRFunc* irFunc,
14201438
IREntryPointDecoration* entryPointDecor)
@@ -1617,12 +1635,10 @@ void GLSLSourceEmitter::emitEntryPointAttributesImpl(
16171635
}
16181636
if (auto decor = as<IROutputTopologyDecoration>(decoration))
16191637
{
1620-
// TODO: Ellie validate here/elsewhere, what's allowed here is
1621-
// different from the tesselator
1622-
// The naming here is plural, so add an 's'
16231638
m_writer->emit("layout(");
1624-
m_writer->emit(decor->getTopology()->getStringSlice());
1625-
m_writer->emit("s) out;\n");
1639+
m_writer->emit(
1640+
getOutputTopologyString(OutputTopologyType(decor->getTopologyType())));
1641+
m_writer->emit(") out;\n");
16261642
}
16271643
break;
16281644
default:

source/slang/slang-emit-hlsl.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -577,9 +577,6 @@ void HLSLSourceEmitter::emitEntryPointAttributesImpl(
577577
emitNumThreadsAttribute();
578578
if (auto decor = irFunc->findDecoration<IROutputTopologyDecoration>())
579579
{
580-
// TODO: Ellie validate here/elsewhere, what's allowed here is
581-
// different from the tesselator
582-
// The naming here is plural, so add an 's'
583580
_emitHLSLDecorationSingleString("outputtopology", irFunc, decor->getTopology());
584581
}
585582
break;

source/slang/slang-emit-metal.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "../core/slang-writer.h"
55
#include "slang-emit-source-writer.h"
6+
#include "slang-ir-entry-point-decorations.h"
67
#include "slang-ir-util.h"
78
#include "slang-mangled-lexer.h"
89

@@ -1261,15 +1262,15 @@ void MetalSourceEmitter::emitSimpleTypeImpl(IRType* type)
12611262
m_writer->emit(", ");
12621263
emitOperand(meshType->getNumPrimitives(), getInfo(EmitOp::General));
12631264
m_writer->emit(", metal::topology::");
1264-
switch (meshType->getTopology()->getValue())
1265+
switch (OutputTopologyType(meshType->getTopology()->getValue()))
12651266
{
1266-
case 1:
1267+
case OutputTopologyType::Point:
12671268
m_writer->emit("point");
12681269
break;
1269-
case 2:
1270+
case OutputTopologyType::Line:
12701271
m_writer->emit("line");
12711272
break;
1272-
case 3:
1273+
case OutputTopologyType::Triangle:
12731274
m_writer->emit("triangle");
12741275
break;
12751276
}

source/slang/slang-emit-spirv.cpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "slang-compiler.h"
55
#include "slang-emit-base.h"
66
#include "slang-ir-call-graph.h"
7+
#include "slang-ir-entry-point-decorations.h"
78
#include "slang-ir-insts.h"
89
#include "slang-ir-layout.h"
910
#include "slang-ir-redundancy-removal.h"
@@ -4684,7 +4685,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
46844685
entryPoint ? entryPoint->findDecoration<IREntryPointDecoration>() : nullptr;
46854686

46864687
const auto o = cast<IROutputTopologyDecoration>(decoration);
4687-
const auto t = o->getTopology()->getStringSlice();
4688+
const auto topologyType = OutputTopologyType(o->getTopologyType());
46884689

46894690
SpvExecutionMode m = SpvExecutionModeMax;
46904691
if (entryPointDecor)
@@ -4693,20 +4694,20 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
46934694
{
46944695
case Stage::Domain:
46954696
case Stage::Hull:
4696-
if (t == "triangle_cw")
4697+
if (topologyType == OutputTopologyType::TriangleCW)
46974698
m = SpvExecutionModeVertexOrderCw;
4698-
else if (t == "triangle_ccw")
4699+
else if (topologyType == OutputTopologyType::TriangleCCW)
46994700
m = SpvExecutionModeVertexOrderCcw;
47004701
break;
47014702
}
47024703
}
47034704
if (m == SpvExecutionModeMax)
47044705
{
4705-
if (t == "triangle")
4706+
if (topologyType == OutputTopologyType::Triangle)
47064707
m = SpvExecutionModeOutputTrianglesEXT;
4707-
else if (t == "line")
4708+
else if (topologyType == OutputTopologyType::Line)
47084709
m = SpvExecutionModeOutputLinesEXT;
4709-
else if (t == "point")
4710+
else if (topologyType == OutputTopologyType::Point)
47104711
m = SpvExecutionModeOutputPoints;
47114712
}
47124713

source/slang/slang-emit.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "slang-ir-early-raytracing-intrinsic-simplification.h"
3939
#include "slang-ir-eliminate-multilevel-break.h"
4040
#include "slang-ir-eliminate-phis.h"
41+
#include "slang-ir-entry-point-decorations.h"
4142
#include "slang-ir-entry-point-raw-ptr-params.h"
4243
#include "slang-ir-entry-point-uniforms.h"
4344
#include "slang-ir-explicit-global-context.h"
@@ -722,6 +723,8 @@ Result linkAndOptimizeIR(
722723
#endif
723724
validateIRModuleIfEnabled(codeGenContext, irModule);
724725

726+
checkEntryPointDecorations(irModule, target, sink);
727+
725728
// Another transformation that needed to wait until we
726729
// had layout information on parameters is to take uniform
727730
// parameters of a shader entry point and move them into
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#include "slang-ir-entry-point-decorations.h"
2+
3+
#include "compiler-core/slang-diagnostic-sink.h"
4+
#include "core/slang-signal.h"
5+
#include "core/slang-string.h"
6+
#include "core/slang-type-text-util.h"
7+
#include "slang-compiler.h"
8+
#include "slang-ir-insts.h"
9+
#include "slang-ir.h"
10+
#include "slang-options.h"
11+
12+
namespace Slang
13+
{
14+
15+
class CheckEntryPointDecorationsContext
16+
{
17+
public:
18+
CheckEntryPointDecorationsContext(IRModule* module, CodeGenTarget target, DiagnosticSink* sink)
19+
: m_module(module), m_target(target), m_sink(sink)
20+
{
21+
}
22+
23+
void check()
24+
{
25+
for (auto inst : m_module->getGlobalInsts())
26+
{
27+
const auto func = as<IRFunc>(inst);
28+
if (!func)
29+
continue;
30+
const auto entryPointDecoration = func->findDecoration<IREntryPointDecoration>();
31+
if (!entryPointDecoration)
32+
continue;
33+
34+
checkEntryPoint(func, entryPointDecoration->getProfile().getStage());
35+
}
36+
}
37+
38+
private:
39+
void checkEntryPoint(IRFunc* entryPoint, Stage stage)
40+
{
41+
for (auto decoration : entryPoint->getDecorations())
42+
{
43+
if (auto outputTopologyDecoration = as<IROutputTopologyDecoration>(decoration))
44+
{
45+
checkOutputTopologyDecoration(outputTopologyDecoration, stage);
46+
}
47+
}
48+
}
49+
50+
void checkOutputTopologyDecoration(IROutputTopologyDecoration* decoration, Stage stage)
51+
{
52+
if (stage == Stage::Mesh)
53+
{
54+
const auto outputTopologyType = OutputTopologyType(decoration->getTopologyType());
55+
if (isTargetGLSL() || isTargetSPIRV() || isTargetMetal())
56+
{
57+
if (outputTopologyType != OutputTopologyType::Point &&
58+
outputTopologyType != OutputTopologyType::Line &&
59+
outputTopologyType != OutputTopologyType::Triangle)
60+
{
61+
diagnoseInvalidMeshStageOutputTopology(
62+
decoration,
63+
"'point', 'line', 'triangle'");
64+
}
65+
}
66+
else if (isTargetHLSL())
67+
{
68+
if (outputTopologyType != OutputTopologyType::Line &&
69+
outputTopologyType != OutputTopologyType::Triangle)
70+
{
71+
diagnoseInvalidMeshStageOutputTopology(decoration, "'line', 'triangle'");
72+
}
73+
}
74+
else
75+
{
76+
SLANG_UNEXPECTED("Invalid compilation target for mesh stage");
77+
}
78+
}
79+
}
80+
81+
void diagnoseInvalidMeshStageOutputTopology(
82+
IROutputTopologyDecoration* decoration,
83+
String validTopologies)
84+
{
85+
m_sink->diagnose(
86+
decoration,
87+
Diagnostics::invalidMeshStageOutputTopology,
88+
decoration->getTopology()->getStringSlice(),
89+
TypeTextUtil::getCompileTargetName(SlangCompileTarget(m_target)),
90+
validTopologies);
91+
}
92+
93+
bool isTargetHLSL() const { return m_target == CodeGenTarget::HLSL; }
94+
95+
bool isTargetGLSL() const { return m_target == CodeGenTarget::GLSL; }
96+
97+
bool isTargetSPIRV() const
98+
{
99+
return m_target == CodeGenTarget::SPIRV || m_target == CodeGenTarget::SPIRVAssembly;
100+
}
101+
102+
bool isTargetMetal() const
103+
{
104+
return m_target == CodeGenTarget::Metal || m_target == CodeGenTarget::MetalLib ||
105+
m_target == CodeGenTarget::MetalLibAssembly;
106+
}
107+
108+
IRModule* m_module;
109+
const CodeGenTarget m_target;
110+
DiagnosticSink* m_sink;
111+
};
112+
113+
void checkEntryPointDecorations(IRModule* module, CodeGenTarget target, DiagnosticSink* sink)
114+
{
115+
CheckEntryPointDecorationsContext(module, target, sink).check();
116+
}
117+
118+
OutputTopologyType convertOutputTopologyStringToEnum(String rawOutputTopology)
119+
{
120+
auto name = rawOutputTopology.toLower();
121+
122+
OutputTopologyType outputTopologyType = OutputTopologyType::Unknown;
123+
124+
#define CASE(ID, NAME) \
125+
if (name == String(#NAME).toLower()) \
126+
{ \
127+
outputTopologyType = OutputTopologyType::ID; \
128+
} \
129+
else
130+
131+
OUTPUT_TOPOLOGY_TYPES(CASE)
132+
#undef CASE
133+
{
134+
outputTopologyType = OutputTopologyType::Unknown;
135+
// no match
136+
}
137+
return outputTopologyType;
138+
}
139+
140+
} // namespace Slang
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// slang-ir-entry-point-decorations.h
2+
#pragma once
3+
4+
#include "slang-ir.h"
5+
6+
namespace Slang
7+
{
8+
enum class CodeGenTarget;
9+
class DiagnosticSink;
10+
11+
/// Checks entry point decoration values to ensure that they are valid for
12+
/// the shader stage and target.
13+
void checkEntryPointDecorations(IRModule* module, CodeGenTarget target, DiagnosticSink* sink);
14+
15+
16+
// OutputTopologyType member definition macro
17+
#define OUTPUT_TOPOLOGY_TYPES(M) \
18+
M(Point, point) \
19+
M(Line, line) \
20+
M(Triangle, triangle) \
21+
M(TriangleCW, triangle_cw) \
22+
M(TriangleCCW, triangle_ccw) \
23+
/* end */
24+
25+
enum class OutputTopologyType
26+
{
27+
Unknown = 0,
28+
#define CASE(ID, NAME) ID,
29+
OUTPUT_TOPOLOGY_TYPES(CASE)
30+
#undef CASE
31+
};
32+
33+
34+
OutputTopologyType convertOutputTopologyStringToEnum(String rawOutputTopology);
35+
36+
} // namespace Slang

source/slang/slang-ir-inst-defs.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ INST_RANGE(BindingQuery, GetRegisterIndex, GetRegisterSpace)
860860
INST(PatchConstantFuncDecoration, patchConstantFunc, 1, 0)
861861
INST(MaxTessFactorDecoration, maxTessFactor, 1, 0)
862862
INST(OutputControlPointsDecoration, outputControlPoints, 1, 0)
863-
INST(OutputTopologyDecoration, outputTopology, 1, 0)
863+
INST(OutputTopologyDecoration, outputTopology, 2, 0)
864864
INST(PartitioningDecoration, partioning, 1, 0)
865865
INST(DomainDecoration, domain, 1, 0)
866866
INST(MaxVertexCountDecoration, maxVertexCount, 1, 0)

source/slang/slang-ir-insts.h

+2
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,8 @@ struct IROutputTopologyDecoration : IRDecoration
561561
IR_LEAF_ISA(OutputTopologyDecoration)
562562

563563
IRStringLit* getTopology() { return cast<IRStringLit>(getOperand(0)); }
564+
565+
IRIntegerValue getTopologyType() { return cast<IRIntLit>(getOperand(1))->getValue(); }
564566
};
565567

566568
struct IRPartitioningDecoration : IRDecoration

source/slang/slang-ir-legalize-varying-params.cpp

+1-20
Original file line numberDiff line numberDiff line change
@@ -3518,27 +3518,8 @@ class LegalizeMetalEntryPointContext : public LegalizeShaderEntryPointContext
35183518
SLANG_UNEXPECTED("Mesh shader output decoration missing");
35193519
return;
35203520
}
3521-
const auto topology = outputDeco->getTopology();
3522-
const auto topStr = topology->getStringSlice();
3523-
UInt topologyEnum = 0;
3524-
if (topStr.caseInsensitiveEquals(toSlice("point")))
3525-
{
3526-
topologyEnum = 1;
3527-
}
3528-
else if (topStr.caseInsensitiveEquals(toSlice("line")))
3529-
{
3530-
topologyEnum = 2;
3531-
}
3532-
else if (topStr.caseInsensitiveEquals(toSlice("triangle")))
3533-
{
3534-
topologyEnum = 3;
3535-
}
3536-
else
3537-
{
3538-
SLANG_UNEXPECTED("unknown topology");
3539-
return;
3540-
}
35413521

3522+
const auto topologyEnum = outputDeco->getTopologyType();
35423523
IRInst* topologyConst = builder.getIntValue(builder.getIntType(), topologyEnum);
35433524

35443525
IRType* vertexType = nullptr;

0 commit comments

Comments
 (0)