Skip to content

Commit bf61c75

Browse files
Merge branch 'master' into fix-spec-arithmetic
2 parents 1ed7d29 + 4e62f98 commit bf61c75

30 files changed

+533
-105
lines changed

cmake/SlangTarget.cmake

+8-4
Original file line numberDiff line numberDiff line change
@@ -505,10 +505,14 @@ function(slang_add_target dir type)
505505
endif()
506506
install(
507507
TARGETS ${target} ${export_args}
508-
ARCHIVE DESTINATION ${archive_subdir} ${ARGN}
509-
LIBRARY DESTINATION ${library_subdir} ${ARGN}
510-
RUNTIME DESTINATION ${runtime_subdir} ${ARGN}
511-
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ${ARGN}
508+
ARCHIVE DESTINATION ${archive_subdir}
509+
${ARGN}
510+
LIBRARY DESTINATION ${library_subdir}
511+
${ARGN}
512+
RUNTIME DESTINATION ${runtime_subdir}
513+
${ARGN}
514+
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
515+
${ARGN}
512516
)
513517
endmacro()
514518

docs/user-guide/03-convenience-features.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ int rs = foo.staticMethod(a,b);
149149

150150
### Mutability of member function
151151

152-
For GPU performance considerations, the `this` argument in a member function is immutable by default. If you modify the content in `this` argument, the modification will be discarded after the call and does not affect the input object. If you intend to define a member function that mutates the object, use `[mutating]` attribute on the member function as shown in the following example.
152+
For GPU performance considerations, the `this` argument in a member function is immutable by default. Attempting to modify `this` will result in a compile error. If you intend to define a member function that mutates the object, use `[mutating]` attribute on the member function as shown in the following example.
153153

154154
```hlsl
155155
struct Foo
@@ -159,14 +159,14 @@ struct Foo
159159
[mutating]
160160
void setCount(int x) { count = x; }
161161
162-
void setCount2(int x) { count = x; }
162+
// This would fail to compile.
163+
// void setCount2(int x) { count = x; }
163164
}
164165
165166
void test()
166167
{
167168
Foo f;
168-
f.setCount(1); // f.count is 1 after the call.
169-
f.setCount2(2); // f.count is still 1 after the call.
169+
f.setCount(1); // Compiles
170170
}
171171
```
172172

source/compiler-core/slang-nvrtc-compiler.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,9 @@ SlangResult NVRTCDownstreamCompiler::compile(
943943

944944
CommandLine cmdLine;
945945

946+
// --dopt option is only available in CUDA 11.7 and later
947+
bool hasDoptOption = m_desc.version >= SemanticVersion(11, 7);
948+
946949
switch (options.debugInfoType)
947950
{
948951
case DebugInfoType::None:
@@ -952,12 +955,20 @@ SlangResult NVRTCDownstreamCompiler::compile(
952955
default:
953956
{
954957
cmdLine.addArg("--device-debug");
958+
if (hasDoptOption)
959+
{
960+
cmdLine.addArg("--dopt=on");
961+
}
955962
break;
956963
}
957964
case DebugInfoType::Maximal:
958965
{
959966
cmdLine.addArg("--device-debug");
960967
cmdLine.addArg("--generate-line-info");
968+
if (hasDoptOption)
969+
{
970+
cmdLine.addArg("--dopt=on");
971+
}
961972
break;
962973
}
963974
}

source/slang/hlsl.meta.slang

+15-1
Original file line numberDiff line numberDiff line change
@@ -20932,6 +20932,8 @@ struct ConstBufferPointer
2093220932
// new aliased bindings for each distinct cast type.
2093320933
//
2093420934

20935+
//@public:
20936+
2093520937
/// Represent the kind of a descriptor type.
2093620938
enum DescriptorKind
2093720939
{
@@ -21048,8 +21050,18 @@ ${{{{
2104821050
}
2104921051
}}}}
2105021052

21051-
/// Represents a bindless resource handle. A bindless resource handle is always a concrete type and can be
21053+
/// Represents a bindless handle to a descriptor. A descriptor handle is always an ordinary data type and can be
2105221054
/// declared in any memory location.
21055+
/// @remarks Opaque descriptor types such as textures(`Texture2D` etc.), `SamplerState` and buffers (e.g. `StructuredBuffer`)
21056+
/// can have undefined size and data representation on many targets. On platforms such as Vulkan and D3D12, descriptors are
21057+
/// communicated to the shader code by calling the host side API to write the descriptor into a descriptor set or table, instead
21058+
/// of directly writing bytes into an ordinary GPU accessible buffer. As a result, oapque handle types cannot be used in places
21059+
/// that refer to a ordinary buffer location, such as as element types of a `StructuredBuffer`.
21060+
/// However, a `DescriptorHandle<T>` stores a handle (or address) to the actual descriptor, and is always an ordinary data type
21061+
/// that can be manipulated directly in the shader code. This gives the developer the flexibility to embed and pass around descriptor
21062+
/// parameters throughout the code, to enable cleaner modular designs.
21063+
/// See [User Guide](https://shader-slang.com/slang/user-guide/convenience-features.html#descriptorhandle-for-bindless-descriptor-access)
21064+
/// for more information on how to use `DescriptorHandle<T>` in your code.
2105321065
__magic_type(DescriptorHandleType)
2105421066
__intrinsic_type($(kIROp_DescriptorHandleType))
2105521067
struct DescriptorHandle<T:IOpaqueDescriptor> : IComparable
@@ -21140,6 +21152,8 @@ extern T getDescriptorFromHandle<T:IOpaqueDescriptor>(DescriptorHandle<T> handle
2114021152
__intrinsic_op($(kIROp_NonUniformResourceIndex))
2114121153
DescriptorHandle<T> nonuniform<T:IOpaqueDescriptor>(DescriptorHandle<T> ptr);
2114221154

21155+
//@hidden:
21156+
2114321157
__glsl_version(450)
2114421158
__glsl_extension(GL_ARB_shader_clock)
2114521159
[require(glsl_spirv, GL_ARB_shader_clock)]

source/slang/slang-ast-modifier.h

+14-6
Original file line numberDiff line numberDiff line change
@@ -973,9 +973,14 @@ class GLSLLayoutLocalSizeAttribute : public Attribute
973973
//
974974
// TODO: These should be accessors that use the
975975
// ordinary `args` list, rather than side data.
976-
IntVal* x;
977-
IntVal* y;
978-
IntVal* z;
976+
IntVal* extents[3];
977+
978+
bool axisIsSpecConstId[3];
979+
980+
// References to specialization constants, for defining the number of
981+
// threads with them. If set, the corresponding axis is set to nullptr
982+
// above.
983+
DeclRef<VarDeclBase> specConstExtents[3];
979984
};
980985

981986
class GLSLLayoutDerivativeGroupQuadAttribute : public Attribute
@@ -1038,9 +1043,12 @@ class NumThreadsAttribute : public Attribute
10381043
//
10391044
// TODO: These should be accessors that use the
10401045
// ordinary `args` list, rather than side data.
1041-
IntVal* x;
1042-
IntVal* y;
1043-
IntVal* z;
1046+
IntVal* extents[3];
1047+
1048+
// References to specialization constants, for defining the number of
1049+
// threads with them. If set, the corresponding axis is set to nullptr
1050+
// above.
1051+
DeclRef<VarDeclBase> specConstExtents[3];
10441052
};
10451053

10461054
class WaveSizeAttribute : public Attribute

source/slang/slang-check-impl.h

+2
Original file line numberDiff line numberDiff line change
@@ -1656,6 +1656,8 @@ struct SemanticsVisitor : public SemanticsContext
16561656

16571657
void visitModifier(Modifier*);
16581658

1659+
DeclRef<VarDeclBase> tryGetIntSpecializationConstant(Expr* expr);
1660+
16591661
AttributeDecl* lookUpAttributeDecl(Name* attributeName, Scope* scope);
16601662

16611663
bool hasIntArgs(Attribute* attr, int numArgs);

source/slang/slang-check-modifier.cpp

+91-17
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,36 @@ void SemanticsVisitor::visitModifier(Modifier*)
114114
// Do nothing with modifiers for now
115115
}
116116

117+
DeclRef<VarDeclBase> SemanticsVisitor::tryGetIntSpecializationConstant(Expr* expr)
118+
{
119+
// First type-check the expression as normal
120+
expr = CheckExpr(expr);
121+
122+
if (IsErrorExpr(expr))
123+
return DeclRef<VarDeclBase>();
124+
125+
if (!isScalarIntegerType(expr->type))
126+
return DeclRef<VarDeclBase>();
127+
128+
auto specConstVar = as<VarExpr>(expr);
129+
if (!specConstVar || !specConstVar->declRef)
130+
return DeclRef<VarDeclBase>();
131+
132+
auto decl = specConstVar->declRef.getDecl();
133+
if (!decl)
134+
return DeclRef<VarDeclBase>();
135+
136+
for (auto modifier : decl->modifiers)
137+
{
138+
if (as<SpecializationConstantAttribute>(modifier) || as<VkConstantIdAttribute>(modifier))
139+
{
140+
return specConstVar->declRef.as<VarDeclBase>();
141+
}
142+
}
143+
144+
return DeclRef<VarDeclBase>();
145+
}
146+
117147
static bool _isDeclAllowedAsAttribute(DeclRef<Decl> declRef)
118148
{
119149
if (as<AttributeDecl>(declRef.getDecl()))
@@ -350,15 +380,21 @@ Modifier* SemanticsVisitor::validateAttribute(
350380
{
351381
SLANG_ASSERT(attr->args.getCount() == 3);
352382

353-
IntVal* values[3];
354-
355383
for (int i = 0; i < 3; ++i)
356384
{
357385
IntVal* value = nullptr;
358386

359387
auto arg = attr->args[i];
360388
if (arg)
361389
{
390+
auto specConstDecl = tryGetIntSpecializationConstant(arg);
391+
if (specConstDecl)
392+
{
393+
numThreadsAttr->extents[i] = nullptr;
394+
numThreadsAttr->specConstExtents[i] = specConstDecl;
395+
continue;
396+
}
397+
362398
auto intValue = checkLinkTimeConstantIntVal(arg);
363399
if (!intValue)
364400
{
@@ -390,12 +426,8 @@ Modifier* SemanticsVisitor::validateAttribute(
390426
{
391427
value = m_astBuilder->getIntVal(m_astBuilder->getIntType(), 1);
392428
}
393-
values[i] = value;
429+
numThreadsAttr->extents[i] = value;
394430
}
395-
396-
numThreadsAttr->x = values[0];
397-
numThreadsAttr->y = values[1];
398-
numThreadsAttr->z = values[2];
399431
}
400432
else if (auto waveSizeAttr = as<WaveSizeAttribute>(attr))
401433
{
@@ -1831,23 +1863,70 @@ Modifier* SemanticsVisitor::checkModifier(
18311863
{
18321864
SLANG_ASSERT(attr->args.getCount() == 3);
18331865

1834-
IntVal* values[3];
1866+
// GLSLLayoutLocalSizeAttribute is always attached to an EmptyDecl.
1867+
auto decl = as<EmptyDecl>(syntaxNode);
1868+
SLANG_ASSERT(decl);
18351869

18361870
for (int i = 0; i < 3; ++i)
18371871
{
1838-
IntVal* value = nullptr;
1872+
attr->extents[i] = nullptr;
18391873

18401874
auto arg = attr->args[i];
18411875
if (arg)
18421876
{
1877+
auto specConstDecl = tryGetIntSpecializationConstant(arg);
1878+
if (specConstDecl)
1879+
{
1880+
attr->specConstExtents[i] = specConstDecl;
1881+
continue;
1882+
}
1883+
18431884
auto intValue = checkConstantIntVal(arg);
18441885
if (!intValue)
18451886
{
18461887
return nullptr;
18471888
}
18481889
if (auto cintVal = as<ConstantIntVal>(intValue))
18491890
{
1850-
if (cintVal->getValue() < 1)
1891+
if (attr->axisIsSpecConstId[i])
1892+
{
1893+
// This integer should actually be a reference to a
1894+
// specialization constant with this ID.
1895+
Int specConstId = cintVal->getValue();
1896+
1897+
for (auto member : decl->parentDecl->members)
1898+
{
1899+
auto constantId = member->findModifier<VkConstantIdAttribute>();
1900+
if (constantId)
1901+
{
1902+
SLANG_ASSERT(constantId->args.getCount() == 1);
1903+
auto id = checkConstantIntVal(constantId->args[0]);
1904+
if (id->getValue() == specConstId)
1905+
{
1906+
attr->specConstExtents[i] =
1907+
DeclRef<VarDeclBase>(member->getDefaultDeclRef());
1908+
break;
1909+
}
1910+
}
1911+
}
1912+
1913+
// If not found, we need to create a new specialization
1914+
// constant with this ID.
1915+
if (!attr->specConstExtents[i])
1916+
{
1917+
auto specConstVarDecl = getASTBuilder()->create<VarDecl>();
1918+
auto constantIdModifier =
1919+
getASTBuilder()->create<VkConstantIdAttribute>();
1920+
constantIdModifier->location = (int32_t)specConstId;
1921+
specConstVarDecl->type.type = getASTBuilder()->getIntType();
1922+
addModifier(specConstVarDecl, constantIdModifier);
1923+
decl->parentDecl->addMember(specConstVarDecl);
1924+
attr->specConstExtents[i] =
1925+
DeclRef<VarDeclBase>(specConstVarDecl->getDefaultDeclRef());
1926+
}
1927+
continue;
1928+
}
1929+
else if (cintVal->getValue() < 1)
18511930
{
18521931
getSink()->diagnose(
18531932
attr,
@@ -1856,18 +1935,13 @@ Modifier* SemanticsVisitor::checkModifier(
18561935
return nullptr;
18571936
}
18581937
}
1859-
value = intValue;
1938+
attr->extents[i] = intValue;
18601939
}
18611940
else
18621941
{
1863-
value = m_astBuilder->getIntVal(m_astBuilder->getIntType(), 1);
1942+
attr->extents[i] = m_astBuilder->getIntVal(m_astBuilder->getIntType(), 1);
18641943
}
1865-
values[i] = value;
18661944
}
1867-
1868-
attr->x = values[0];
1869-
attr->y = values[1];
1870-
attr->z = values[2];
18711945
}
18721946

18731947
// Default behavior is to leave things as they are,

source/slang/slang-diagnostic-defs.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -2060,7 +2060,7 @@ DIAGNOSTIC(
20602060
DIAGNOSTIC(41000, Warning, unreachableCode, "unreachable code detected")
20612061
DIAGNOSTIC(41001, Error, recursiveType, "type '$0' contains cyclic reference to itself.")
20622062

2063-
DIAGNOSTIC(41010, Warning, missingReturn, "control flow may reach end of non-'void' function")
2063+
DIAGNOSTIC(41010, Warning, missingReturn, "non-void function does not return in all cases")
20642064
DIAGNOSTIC(
20652065
41011,
20662066
Error,
@@ -2459,6 +2459,12 @@ DIAGNOSTIC(
24592459
Error,
24602460
unsupportedTargetIntrinsic,
24612461
"intrinsic operation '$0' is not supported for the current target.")
2462+
DIAGNOSTIC(
2463+
55205,
2464+
Error,
2465+
unsupportedSpecializationConstantForNumThreads,
2466+
"Specialization constants are not supported in the 'numthreads' attribute for the current "
2467+
"target.")
24622468
DIAGNOSTIC(
24632469
56001,
24642470
Error,

0 commit comments

Comments
 (0)