summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvenkataram-nv <vedavamadath@nvidia.com>2024-08-12 14:18:02 -0700
committerGitHub <noreply@github.com>2024-08-12 14:18:02 -0700
commit20bd48659d0009de5477380c335e2419f4c66f8b (patch)
tree1b5df96436eaea9adbe5ef524b39fe6da4697387
parent9b580e58417a77109617804362be872f05885f23 (diff)
Warn when inout parameter is never written (#4777)
Addresses #4698 as one approach to diagnose the potential problem. Emit warnings when a user marks a parameter as `inout` but never writes to it in the function. A new intrinsic function `unmodified(out T)` has been added to explicitly indicate that an `inout` variable will not be modified in the function. This is only one way to address the specific validation error in #4698. In general it seems that DXC does some more extensive checks on actual struct fields (as opposed to observing arbitrary struct writes), so that will be the next step.
-rw-r--r--source/slang/core.meta.slang11
-rw-r--r--source/slang/diff.meta.slang63
-rw-r--r--source/slang/slang-diagnostic-defs.h2
-rw-r--r--source/slang/slang-emit-c-like.cpp3
-rw-r--r--source/slang/slang-emit-spirv.cpp1
-rw-r--r--source/slang/slang-ir-addr-inst-elimination.cpp1
-rw-r--r--source/slang/slang-ir-autodiff-transcriber-base.h10
-rw-r--r--source/slang/slang-ir-inst-defs.h2
-rw-r--r--source/slang/slang-ir-insts.h2
-rw-r--r--source/slang/slang-ir-use-uninitialized-values.cpp168
-rw-r--r--source/slang/slang-lower-to-ir.cpp5
-rw-r--r--tests/autodiff/reverse-inout-param-custom-derivative.slang2
-rw-r--r--tests/bugs/gl-33-ext.slang2
-rw-r--r--tests/bugs/optional.slang2
-rw-r--r--tests/diagnostics/inout-never-written.slang48
-rw-r--r--tests/hlsl-intrinsic/matrix-double.slang4
-rw-r--r--tests/hlsl-intrinsic/size-of/align-of-3.slang4
-rw-r--r--tests/hlsl-intrinsic/size-of/size-of-3.slang4
-rw-r--r--tests/language-feature/struct-field-initializers/struct-field-no-initializer-complex-types.slang9
-rw-r--r--tests/language-feature/unsized-array.slang1
-rw-r--r--tests/pipeline/ray-tracing/trace-ray-inline.slang6
21 files changed, 290 insertions, 60 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 2dae7b3c4..695423285 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -2025,13 +2025,20 @@ T reinterpret(U value);
// Use an otherwise unused value
//
-// This can be used to silence the warning about returning before initializing
-// an out paramter.
+// This can be used to silence the warning about returning before initializing an out paramter.
__generic<T>
[__readNone]
[ForceInline]
+__intrinsic_op($(kIROp_Unmodified))
void unused(inout T){}
+// This can be used to silence the warning about not writing to an inout parameter.
+__generic<T>
+[__readNone]
+[ForceInline]
+__intrinsic_op($(kIROp_Unmodified))
+void unmodified(out T){}
+
// Specialized function
/// Given a string returns an integer hash of that string.
diff --git a/source/slang/diff.meta.slang b/source/slang/diff.meta.slang
index c912e026c..a4c468ef7 100644
--- a/source/slang/diff.meta.slang
+++ b/source/slang/diff.meta.slang
@@ -273,7 +273,12 @@ struct TensorView
__subscript(uint index) -> T
{
[ForceInline] [__NoSideEffect] get { return load(index); }
- [ForceInline] set { store(index, newValue); }
+
+ [ForceInline] set
+ {
+ unmodified(this);
+ store(index, newValue);
+ }
[__NoSideEffect]
ref
@@ -288,7 +293,13 @@ struct TensorView
__subscript(uint i1, uint i2) -> T
{
[ForceInline] [__NoSideEffect] get { return load(i1, i2); }
- [ForceInline] set { store(i1, i2, newValue); }
+
+ [ForceInline] set
+ {
+ unmodified(this);
+ store(i1, i2, newValue);
+ }
+
[__NoSideEffect]
ref
{
@@ -302,7 +313,13 @@ struct TensorView
__subscript(uint2 i) -> T
{
[ForceInline] [__NoSideEffect] get { return load(i.x, i.y); }
- [ForceInline] set { store(i.x, i.y, newValue); }
+
+ [ForceInline] set
+ {
+ unmodified(this);
+ store(i.x, i.y, newValue);
+ }
+
[__NoSideEffect]
ref
{
@@ -316,7 +333,13 @@ struct TensorView
__subscript(uint i1, uint i2, uint i3) -> T
{
[ForceInline] [__NoSideEffect] get { return load(i1, i2, i3); }
- [ForceInline] set { store(i1, i2, i3, newValue); }
+
+ [ForceInline] set
+ {
+ unmodified(this);
+ store(i1, i2, i3, newValue);
+ }
+
[__NoSideEffect]
ref
{
@@ -330,7 +353,13 @@ struct TensorView
__subscript(uint3 i) -> T
{
[ForceInline] [__NoSideEffect] get { return load(i.x, i.y, i.z); }
- [ForceInline] set { store(i.x, i.y, i.z, newValue); }
+
+ [ForceInline] set
+ {
+ unmodified(this);
+ store(i.x, i.y, i.z, newValue);
+ }
+
[__NoSideEffect]
ref
{
@@ -344,7 +373,13 @@ struct TensorView
__subscript(uint i1, uint i2, uint i3, uint i4) -> T
{
[ForceInline] [__NoSideEffect] get { return load(i1, i2, i3, i4); }
- [ForceInline] set { store(i1, i2, i3, i4, newValue); }
+
+ [ForceInline] set
+ {
+ unmodified(this);
+ store(i1, i2, i3, i4, newValue);
+ }
+
[__NoSideEffect]
ref
{
@@ -358,7 +393,13 @@ struct TensorView
__subscript(uint4 i) -> T
{
[__NoSideEffect][ForceInline] get { return load(i.x, i.y, i.z, i.w); }
- [ForceInline] set { store(i.x, i.y, i.z, i.w, newValue); }
+
+ [ForceInline] set
+ {
+ unmodified(this);
+ store(i.x, i.y, i.z, i.w, newValue);
+ }
+
[__NoSideEffect]
ref
{
@@ -372,7 +413,13 @@ struct TensorView
__subscript(uint i1, uint i2, uint i3, uint i4, uint i5) -> T
{
[ForceInline] [__NoSideEffect] get { return load(i1, i2, i3, i4, i5); }
- [ForceInline] set { store(i1, i2, i3, i4, i5, newValue); }
+
+ [ForceInline] set
+ {
+ unmodified(this);
+ store(i1, i2, i3, i4, i5, newValue);
+ }
+
[__NoSideEffect]
ref
{
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 6d7be3f92..44e8aa13d 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -752,6 +752,8 @@ DIAGNOSTIC(41018, Warning, returningWithUninitializedOut, "returning without ini
DIAGNOSTIC(41019, Warning, returningWithPartiallyUninitializedOut, "returning without fully initializing out parameter '$0'")
DIAGNOSTIC(41020, Warning, constructorUninitializedField, "exiting constructor without initializing field '$0'")
DIAGNOSTIC(41021, Warning, fieldNotDefaultInitialized, "default initializer for '$0' will not initialize field '$1'")
+DIAGNOSTIC(41022, Warning, inOutNeverStoredInto, "inout parameter '$0' is never written to")
+DIAGNOSTIC(41023, Warning, methodNeverMutates, "method marked `[mutable]` but never modifies `this`")
DIAGNOSTIC(41011, Error, typeDoesNotFitAnyValueSize, "type '$0' does not fit in the size required by its conforming interface.")
DIAGNOSTIC(41012, Note, typeAndLimit, "sizeof($0) is $1, limit is $2")
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index dd5ef8c51..fadf76dd2 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -2889,6 +2889,9 @@ void CLikeSourceEmitter::_emitInst(IRInst* inst)
case kIROp_DebugValue:
break;
+ case kIROp_Unmodified:
+ break;
+
// Insts that needs to be emitted as code blocks.
case kIROp_CudaKernelLaunch:
case kIROp_AtomicCounterIncrement:
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 23eaa4435..bb0a2565c 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -2719,6 +2719,7 @@ struct SPIRVEmitContext
case kIROp_Specialize:
case kIROp_MissingReturn:
case kIROp_StaticAssert:
+ case kIROp_Unmodified:
break;
case kIROp_Var:
result = emitVar(parent, inst);
diff --git a/source/slang/slang-ir-addr-inst-elimination.cpp b/source/slang/slang-ir-addr-inst-elimination.cpp
index 2581ea37f..7889a2f61 100644
--- a/source/slang/slang-ir-addr-inst-elimination.cpp
+++ b/source/slang/slang-ir-addr-inst-elimination.cpp
@@ -169,6 +169,7 @@ struct AddressInstEliminationContext
break;
case kIROp_GetElementPtr:
case kIROp_FieldAddress:
+ case kIROp_Unmodified:
break;
default:
sink->diagnose(use->getUser()->sourceLoc, Diagnostics::unsupportedUseOfLValueForAutoDiff);
diff --git a/source/slang/slang-ir-autodiff-transcriber-base.h b/source/slang/slang-ir-autodiff-transcriber-base.h
index 7b4c293e9..f672631e3 100644
--- a/source/slang/slang-ir-autodiff-transcriber-base.h
+++ b/source/slang/slang-ir-autodiff-transcriber-base.h
@@ -123,8 +123,14 @@ struct AutoDiffTranscriberBase
InstPair transcribeBlock(IRBuilder* builder, IRBlock* origBlock)
{
- HashSet<IRInst*> emptySet;
- return transcribeBlockImpl(builder, origBlock, emptySet);
+ HashSet<IRInst*> ignore;
+ for (auto inst = origBlock->getFirstInst(); inst; inst = inst->next)
+ {
+ if (inst->m_op == kIROp_Unmodified)
+ ignore.add(inst);
+ }
+
+ return transcribeBlockImpl(builder, origBlock, ignore);
}
// Transcribe a generic definition
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index 0e84be2b2..84ee634a1 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -931,6 +931,7 @@ INST_RANGE(BindingQuery, GetRegisterIndex, GetRegisterSpace)
INST(SemanticDecoration, semantic, 2, 0)
INST(ConstructorDecoration, constructor, 1, 0)
+ INST(MethodDecoration, method, 0, 0)
INST(PackOffsetDecoration, packoffset, 2, 0)
// Reflection metadata for a shader parameter that provides the original type name.
@@ -1094,6 +1095,7 @@ INST(ExtractTaggedUnionPayload, extractTaggedUnionPayload, 1, 0)
INST(BitCast, bitCast, 1, 0)
INST(Reinterpret, reinterpret, 1, 0)
+INST(Unmodified, unmodified, 1, 0)
INST(OutImplicitCast, outImplicitCast, 1, 0)
INST(InOutImplicitCast, inOutImplicitCast, 1, 0)
INST(IntCast, intCast, 1, 0)
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 8a801e4e7..e30b903b5 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -1365,6 +1365,8 @@ struct IRConstructorDecorartion : IRDecoration
bool getSynthesizedStatus() { return cast<IRBoolLit>(getOperand(0))->getValue(); }
};
+IR_SIMPLE_DECORATION(MethodDecoration)
+
struct IRPackOffsetDecoration : IRDecoration
{
enum
diff --git a/source/slang/slang-ir-use-uninitialized-values.cpp b/source/slang/slang-ir-use-uninitialized-values.cpp
index ca723a97c..b8dfcc33c 100644
--- a/source/slang/slang-ir-use-uninitialized-values.cpp
+++ b/source/slang/slang-ir-use-uninitialized-values.cpp
@@ -38,30 +38,67 @@ namespace Slang
|| (inst->m_op == kIROp_Var);
}
- static bool isPotentiallyUnintended(IRParam* param)
+ static bool isUnmodifying(IRFunc *func)
{
- auto outType = as<IROutType>(param->getFullType());
- if (!outType)
- return false;
-
- // Don't check `out Vertices<T>` or `out Indices<T>` parameters
- // in mesh shaders.
- // TODO: we should find a better way to represent these mesh shader
- // parameters so they conform to the initialize before use convention.
- // For example, we can use a `OutputVetices` and `OutputIndices` type
- // to represent an output, like `OutputPatch` in domain shader.
- // For now, we just skip the check for these parameters.
- switch (outType->getValueType()->getOp())
- {
- case kIROp_VerticesType:
- case kIROp_IndicesType:
- case kIROp_PrimitivesType:
- return false;
- default:
- break;
+ auto intr = func->findDecoration<IRIntrinsicOpDecoration>();
+ return (intr && intr->getIntrinsicOp() == kIROp_Unmodified);
+ }
+
+ enum ParameterCheckType
+ {
+ Never, // Parameter does NOT to be checked for uninitialization (e.g. is `in` or special type)
+ AsOut, // Parameter DOES need to be checked for usage before initializations
+ AsInOut // Parameter DOES need to be checked to see if it is ever written to
+ };
+
+ static ParameterCheckType isPotentiallyUnintended(IRParam* param, Stage stage, int index)
+ {
+ IRType* type = param->getFullType();
+ if (auto out = as<IROutType>(param->getFullType()))
+ {
+ // Don't check `out Vertices<T>` or `out Indices<T>` parameters
+ // in mesh shaders.
+ // TODO: we should find a better way to represent these mesh shader
+ // parameters so they conform to the initialize before use convention.
+ // For example, we can use a `OutputVetices` and `OutputIndices` type
+ // to represent an output, like `OutputPatch` in domain shader.
+ // For now, we just skip the check for these parameters.
+ switch (out->getValueType()->getOp())
+ {
+ case kIROp_VerticesType:
+ case kIROp_IndicesType:
+ case kIROp_PrimitivesType:
+ return Never;
+ default:
+ break;
+ }
+
+ return AsOut;
+ }
+ else if (auto inout = as<IRInOutType>(type))
+ {
+ // TODO: some way to check if the method
+ // is actually used for autodiff
+ if (as<IRDifferentialPairUserCodeType>(inout->getValueType()))
+ return Never;
+
+ switch (stage)
+ {
+ case Stage::AnyHit:
+ case Stage::ClosestHit:
+ // In HLSL the payload is required to be `inout`
+ return (index == 0) ? Never : AsInOut;
+ case Stage::Geometry:
+ // Second parameter is the triangle stream
+ return (index == 1) ? Never : AsInOut;
+ default:
+ break;
+ }
+
+ return AsInOut;
}
- return true;
+ return Never;
}
static bool isAliasable(IRInst* inst)
@@ -275,6 +312,7 @@ namespace Slang
// Miscellaenous cases
case kIROp_ManagedPtrAttach:
+ case kIROp_Unmodified:
stores.add(user);
break;
@@ -481,6 +519,62 @@ namespace Slang
}
}
+ static void checkParameterAsOut(ReachabilityContext &reachability, IRFunc* func, IRParam* param, DiagnosticSink* sink)
+ {
+ auto loads = getUnresolvedParamLoads(reachability, func, param);
+ for (auto load : loads)
+ {
+ sink->diagnose(load,
+ as<IRTerminatorInst>(load)
+ ? Diagnostics::returningWithUninitializedOut
+ : Diagnostics::usingUninitializedOut,
+ param);
+ }
+ }
+
+ static void checkParameterAsInOut(IRParam* param, IRFunc* func, bool isThis, DiagnosticSink* sink)
+ {
+ // If the inout is used for the sake of interface conformance, let it be
+ for (auto use = func->firstUse; use; use = use->nextUse)
+ {
+ if (as<IRWitnessTableEntry>(use->getUser()))
+ return;
+ }
+
+ // If there is at least one write...
+ List<IRInst*> stores;
+ List<IRInst*> loads;
+
+ for (auto alias : getAliasableInstructions(param))
+ {
+ for (auto use = alias->firstUse; use; use = use->nextUse)
+ {
+ IRInst* user = use->getUser();
+ collectLoadStore(stores, loads, user, alias);
+
+ // ...we will ignore the rest...
+ if (stores.getCount())
+ return;
+ }
+ }
+
+ // ...or if there is an intrinsic_asm instruction
+ for (const auto& b : func->getBlocks())
+ {
+ for (auto inst = b->getFirstInst(); inst; inst = inst->next)
+ {
+ if (as<IRGenericAsm>(inst))
+ return;
+ }
+ }
+
+ sink->diagnose(param,
+ isThis
+ ? Diagnostics::methodNeverMutates
+ : Diagnostics::inOutNeverStoredInto,
+ param);
+ }
+
static void checkUninitializedValues(IRFunc* func, DiagnosticSink* sink)
{
// Differentiable functions will generate undefined values
@@ -495,22 +589,30 @@ namespace Slang
ReachabilityContext reachability(func);
// Used for a further analysis and to skip usual return checks
- auto constructor = func->findDecoration <IRConstructorDecorartion> ();
+ auto constructor = func->findDecoration<IRConstructorDecorartion>();
+
+ // Special checks for stages e.g. raytracing shader
+ Stage stage = Stage::Unknown;
+ if (auto entry = func->findDecoration<IREntryPointDecoration>())
+ stage = entry->getProfile().getStage();
+
+ bool structMethod = func->findDecoration<IRMethodDecoration>();
// Check out parameters
- for (auto param : firstBlock->getParams())
+ if (!isUnmodifying(func))
{
- if (!isPotentiallyUnintended(param))
- continue;
-
- auto loads = getUnresolvedParamLoads(reachability, func, param);
- for (auto load : loads)
+ int index = 0;
+ for (auto param : firstBlock->getParams())
{
- sink->diagnose(load,
- as<IRTerminatorInst>(load)
- ? Diagnostics::returningWithUninitializedOut
- : Diagnostics::usingUninitializedOut,
- param);
+ bool isThis = structMethod && (index == 0);
+
+ ParameterCheckType checkType = isPotentiallyUnintended(param, stage, index);
+ if (checkType == AsOut)
+ checkParameterAsOut(reachability, func, param, sink);
+ else if (checkType == AsInOut)
+ checkParameterAsInOut(param, func, isThis, sink);
+
+ index++;
}
}
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 66918c2f1..50d017fb9 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -9509,7 +9509,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
LoweredValInfo lowerFuncDeclInContext(IRGenContext* subContext, IRBuilder* subBuilder, FunctionDeclBase* decl, bool emitBody = true)
{
-
IRGeneric* outerGeneric = nullptr;
subContext->funcDecl = decl;
@@ -9544,6 +9543,10 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
}
}
+ // For diagnostics
+ if (as<StructDecl>(decl->parentDecl))
+ getBuilder()->addSimpleDecoration<IRMethodDecoration>(irFunc);
+
auto irFuncType = info.type;
auto& irResultType = info.resultType;
auto& parameterLists = info.parameterLists;
diff --git a/tests/autodiff/reverse-inout-param-custom-derivative.slang b/tests/autodiff/reverse-inout-param-custom-derivative.slang
index 8769a33c7..c4549e37b 100644
--- a/tests/autodiff/reverse-inout-param-custom-derivative.slang
+++ b/tests/autodiff/reverse-inout-param-custom-derivative.slang
@@ -5,7 +5,7 @@
//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer
RWStructuredBuffer<float> outputBuffer;
-float rng(inout int state, float x)
+float rng(int state, float x)
{
return state + x;
}
diff --git a/tests/bugs/gl-33-ext.slang b/tests/bugs/gl-33-ext.slang
index fccde99a3..6df9f286a 100644
--- a/tests/bugs/gl-33-ext.slang
+++ b/tests/bugs/gl-33-ext.slang
@@ -4,5 +4,5 @@
public struct A
{
public int state;
- [mutating] public int next() { return state; }
+ public int next() { return state; }
};
diff --git a/tests/bugs/optional.slang b/tests/bugs/optional.slang
index 3512ba29f..7a220b23d 100644
--- a/tests/bugs/optional.slang
+++ b/tests/bugs/optional.slang
@@ -14,7 +14,7 @@ struct P
}
struct Tr
{
- int test<T:IArithmetic>(T t, inout P p)
+ int test<T:IArithmetic>(T t, P p)
{
const IFoo hit = p.f;
let castResult = hit as S;
diff --git a/tests/diagnostics/inout-never-written.slang b/tests/diagnostics/inout-never-written.slang
new file mode 100644
index 000000000..0bc59ecf3
--- /dev/null
+++ b/tests/diagnostics/inout-never-written.slang
@@ -0,0 +1,48 @@
+//TEST:SIMPLE(filecheck=CHK): -target spirv
+
+struct State
+{
+ float3 v;
+ float3 n;
+ int rnd;
+};
+
+//CHK-DAG: ([[# @LINE + 1]]): warning 41022: inout parameter 'x' is never written to
+void int_never_assigned(inout int x) {}
+
+//CHK-DAG: ([[# @LINE + 1]]): warning 41022: inout parameter 'state' is never written to
+void state_never_assigned(inout State state, inout float v)
+{
+ v = state.v.x;
+}
+
+void state_assigned(inout State state)
+{
+ state.rnd = (int) dot(state.v, state.n);
+}
+
+struct A
+{
+ int state;
+
+ //CHK-DAG: ([[# @LINE + 1]]): warning 41023: method marked `[mutable]` but never modifies `this`
+ [mutating] int next() { return state; }
+
+ [mutating] int progress()
+ {
+ unmodified(state);
+ return state;
+ }
+};
+
+__generic <T>
+struct B
+{
+ int state;
+
+ //CHK-DAG: ([[# @LINE + 1]]): warning 41023: method marked `[mutable]` but never modifies `this`
+ [mutating] int next() { return state; }
+};
+
+//CHK-NOT: warning 41022
+//CHK-NOT: warning 41023 \ No newline at end of file
diff --git a/tests/hlsl-intrinsic/matrix-double.slang b/tests/hlsl-intrinsic/matrix-double.slang
index 31ec54f8e..6ed1b42bf 100644
--- a/tests/hlsl-intrinsic/matrix-double.slang
+++ b/tests/hlsl-intrinsic/matrix-double.slang
@@ -46,6 +46,8 @@ IntMatrix makeIntMatrix(int v)
void test1(inout FloatMatrix ft, inout FloatMatrix f, int idx)
{
+ unmodified(f);
+
// fmod
ft += FloatMatrix(IntMatrix(((f % makeFloatMatrix(0.11f)) * makeFloatMatrix(100)) + makeFloatMatrix(0.5)));
@@ -112,6 +114,8 @@ void test1(inout FloatMatrix ft, inout FloatMatrix f, int idx)
void test2(inout FloatMatrix ft, inout FloatMatrix f)
{
+ unmodified(f);
+
ft += pow(makeFloatMatrix(0.5), f);
ft += smoothstep(makeFloatMatrix(0.2), makeFloatMatrix(0.7), f);
diff --git a/tests/hlsl-intrinsic/size-of/align-of-3.slang b/tests/hlsl-intrinsic/size-of/align-of-3.slang
index 28665b5ab..079de9241 100644
--- a/tests/hlsl-intrinsic/size-of/align-of-3.slang
+++ b/tests/hlsl-intrinsic/size-of/align-of-3.slang
@@ -10,7 +10,7 @@
RWStructuredBuffer<int> outputBuffer;
-int getParamSize(inout uint3 v)
+int getParamSize(uint3 v)
{
return alignof(v);
}
@@ -19,7 +19,7 @@ int getParamSize(inout uint3 v)
// With "natural" layout size must be the same across all targets.
// The parameter passing semantic is "value in/value out", so the size
// will always be the size of the *value* regardless. So uint3 in this case.
-int getParamSizeWithDirection(inout uint3 v)
+int getParamSizeWithDirection(uint3 v)
{
return alignof(v);
}
diff --git a/tests/hlsl-intrinsic/size-of/size-of-3.slang b/tests/hlsl-intrinsic/size-of/size-of-3.slang
index 8a211867f..7e55bd320 100644
--- a/tests/hlsl-intrinsic/size-of/size-of-3.slang
+++ b/tests/hlsl-intrinsic/size-of/size-of-3.slang
@@ -10,7 +10,7 @@
RWStructuredBuffer<int> outputBuffer;
-int getParamSize(inout uint3 v)
+int getParamSize(uint3 v)
{
return sizeof(v);
}
@@ -19,7 +19,7 @@ int getParamSize(inout uint3 v)
// With "natural" layout size must be the same across all targets.
// The parameter passing semantic is "value in/value out", so the size
// will always be the size of the *value* regardless. So uint3 in this case.
-int getParamSizeWithDirection(inout uint3 v)
+int getParamSizeWithDirection(uint3 v)
{
return sizeof(v);
}
diff --git a/tests/language-feature/struct-field-initializers/struct-field-no-initializer-complex-types.slang b/tests/language-feature/struct-field-initializers/struct-field-no-initializer-complex-types.slang
index a55c4725d..66a3a2c64 100644
--- a/tests/language-feature/struct-field-initializers/struct-field-no-initializer-complex-types.slang
+++ b/tests/language-feature/struct-field-initializers/struct-field-no-initializer-complex-types.slang
@@ -6,7 +6,7 @@
//TEST_INPUT:ubuffer(data=[0 0], stride=4):out,name=outputBuffer
RWStructuredBuffer<int> outputBuffer;
-struct DefaultData
+struct DefaultData : IDefaultInitializable
{
static const int2 val = int2(0, 1);
float2 size;
@@ -16,13 +16,10 @@ struct DefaultData
extension DefaultData
{
- int someGet()
- {
- return val.x;
- }
+ int someGet() { return val.x; }
}
-int loadDefaultData(inout DefaultData noInit)
+int loadDefaultData(DefaultData noInit)
{
outputBuffer[1] = 1;
return noInit.someGet();
diff --git a/tests/language-feature/unsized-array.slang b/tests/language-feature/unsized-array.slang
index c4479867e..19ab0bd63 100644
--- a/tests/language-feature/unsized-array.slang
+++ b/tests/language-feature/unsized-array.slang
@@ -17,6 +17,7 @@ int test(int arr[])
int test2<T>(inout T arr[])
{
+ unmodified(arr);
return arr.getCount();
}
diff --git a/tests/pipeline/ray-tracing/trace-ray-inline.slang b/tests/pipeline/ray-tracing/trace-ray-inline.slang
index 009dffbc7..b8688c2f5 100644
--- a/tests/pipeline/ray-tracing/trace-ray-inline.slang
+++ b/tests/pipeline/ray-tracing/trace-ray-inline.slang
@@ -57,6 +57,7 @@ void myTriangleClosestHit(inout MyRayPayload payload)
//
bool myTriangleAnyHit(inout MyRayPayload payload)
{
+ unmodified(payload);
return true;
}
@@ -75,6 +76,7 @@ void myProceduralClosestHit(inout MyRayPayload payload, MyProceduralHitAttrs att
}
bool myProceduralAnyHit(inout MyRayPayload payload)
{
+ unmodified(payload);
return true;
}
@@ -87,6 +89,8 @@ bool myProceduralAnyHit(inout MyRayPayload payload)
//
bool myProceduralIntersection(inout float tHit, inout MyProceduralHitAttrs hitAttrs)
{
+ unmodified(tHit);
+ unmodified(hitAttrs);
return true;
}
@@ -180,4 +184,4 @@ void main(uint3 tid : SV_DispatchThreadID)
}
resultBuffer[index] = payload.value;
-} \ No newline at end of file
+}