Skip to content

Commit 8b16bbf

Browse files
author
Tim Foley
authored
Emit directives to control matrix layout (shader-slang#590)
The HLSL/GLSL output by Slang should try to be robust against whatever flags somebody uses to compile it. Therefore, we will go ahead and output a target-language-specific directive to control the default matrix layout mode so that we can override whatever might be specified via flags. Also, as long as we are at it, this change goes ahead and makes Slang unconditionally emit row/column-major layout modifiers on all matrices (and arrays of matrices) whereas before these were only being output sometimes (the code to do it seemed buggy to me...).
1 parent 698ba86 commit 8b16bbf

File tree

1 file changed

+74
-8
lines changed

1 file changed

+74
-8
lines changed

source/slang/emit.cpp

+74-8
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ struct EmitVisitor
979979
case CodeGenTarget::GLSL_Vulkan_OneDesc:
980980
{
981981
// Need to special case if there is a single element in the vector
982-
// as there is no such thing in glsl as vec1
982+
// as there is no such thing in glsl as vec1
983983
IRInst* elementCountInst = vecType->getElementCount();
984984

985985
if (elementCountInst->op != kIROp_IntLit)
@@ -1914,6 +1914,68 @@ struct EmitVisitor
19141914
// TODO: handle other cases...
19151915
}
19161916

1917+
/// Emit directives to control overall layout computation for the emitted code.
1918+
void emitLayoutDirectives(TargetRequest* targetReq)
1919+
{
1920+
// We are going to emit the target-language-specific directives
1921+
// needed to get the default matrix layout to match what was requested
1922+
// for the given target.
1923+
//
1924+
// Note: we do not rely on the defaults for the target language,
1925+
// because a user could take the HLSL/GLSL generated by Slang and pass
1926+
// it to another compiler with non-default options specified on
1927+
// the command line, leading to all kinds of trouble.
1928+
//
1929+
// TODO: We need an approach to "global" layout directives that will work
1930+
// in the presence of multiple modules. If modules A and B were each
1931+
// compiled with different assumptions about how layout is performed,
1932+
// then types/variables defined in those modules should be emitted in
1933+
// a way that is consistent with that layout...
1934+
1935+
auto matrixLayoutMode = targetReq->defaultMatrixLayoutMode;
1936+
1937+
switch(context->shared->target)
1938+
{
1939+
default:
1940+
return;
1941+
1942+
case CodeGenTarget::GLSL:
1943+
// Reminder: the meaning of row/column major layout
1944+
// in our semantics is the *opposite* of what GLSL
1945+
// calls them, because what they call "columns"
1946+
// are what we call "rows."
1947+
//
1948+
switch(matrixLayoutMode)
1949+
{
1950+
case kMatrixLayoutMode_RowMajor:
1951+
default:
1952+
Emit("layout(column_major) uniform;\n");
1953+
Emit("layout(column_major) buffer;\n");
1954+
break;
1955+
1956+
case kMatrixLayoutMode_ColumnMajor:
1957+
Emit("layout(row_major) uniform;\n");
1958+
Emit("layout(row_major) buffer;\n");
1959+
break;
1960+
}
1961+
break;
1962+
1963+
case CodeGenTarget::HLSL:
1964+
switch(matrixLayoutMode)
1965+
{
1966+
case kMatrixLayoutMode_RowMajor:
1967+
default:
1968+
Emit("#pragma pack_matrix(row_major)\n");
1969+
break;
1970+
1971+
case kMatrixLayoutMode_ColumnMajor:
1972+
Emit("#pragma pack_matrix(column_major)\n");
1973+
break;
1974+
}
1975+
break;
1976+
}
1977+
}
1978+
19171979
// Utility code for generating unique IDs as needed
19181980
// during the emit process (e.g., for declarations
19191981
// that didn't origianlly have names, but now need to).
@@ -4611,12 +4673,15 @@ struct EmitVisitor
46114673
EmitContext* ctx,
46124674
VarLayout* layout)
46134675
{
4614-
// We need to handle the case where the variable has
4615-
// a matrix type, and has been given a non-standard
4616-
// layout attribute (for HLSL, `row_major` is the
4617-
// non-standard layout).
4676+
// When a variable has a matrix type, we want to emit an explicit
4677+
// layout qualifier based on what the layout has been computed to be.
46184678
//
4619-
if (auto matrixTypeLayout = layout->typeLayout.As<MatrixTypeLayout>())
4679+
4680+
auto typeLayout = layout->typeLayout;
4681+
while(auto arrayTypeLayout = typeLayout.As<ArrayTypeLayout>())
4682+
typeLayout = arrayTypeLayout->elementTypeLayout;
4683+
4684+
if (auto matrixTypeLayout = typeLayout.As<MatrixTypeLayout>())
46204685
{
46214686
auto target = ctx->shared->target;
46224687

@@ -4626,7 +4691,6 @@ struct EmitVisitor
46264691
switch (matrixTypeLayout->mode)
46274692
{
46284693
case kMatrixLayoutMode_ColumnMajor:
4629-
if(target == CodeGenTarget::GLSL)
46304694
emit("column_major ");
46314695
break;
46324696

@@ -4645,7 +4709,6 @@ struct EmitVisitor
46454709
switch (matrixTypeLayout->mode)
46464710
{
46474711
case kMatrixLayoutMode_ColumnMajor:
4648-
if(target == CodeGenTarget::GLSL)
46494712
emit("layout(row_major)\n");
46504713
break;
46514714

@@ -5815,6 +5878,9 @@ String emitEntryPoint(
58155878

58165879
// There may be global-scope modifiers that we should emit now
58175880
visitor.emitGLSLPreprocessorDirectives(translationUnitSyntax);
5881+
5882+
visitor.emitLayoutDirectives(targetRequest);
5883+
58185884
String prefix = sharedContext.sb.ProduceString();
58195885

58205886

0 commit comments

Comments
 (0)