summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-11-09 13:24:28 -0800
committerGitHub <noreply@github.com>2018-11-09 13:24:28 -0800
commitc07f60af241b1b0f7b7eba62c65d9fe750f8f3b7 (patch)
treee2de0ee14561959f6af02e115d0c615b7ccc5950
parentd782a162a783eab3f4a57a22056c5eba04c2b4ae (diff)
Update Vulkan ray tracing support to final extension spec (#717)
* Update version of glslang used * Update VK raytracing support for final extension spec A lot of this change is just plain renaming: The `NVX` suffixes become just `NV`, and the extension name changes from `GL_NVX_raytracing` to `GL_NV_ray_tracing`. The Slang standard library and the GLSL baselines for the tests are consistently updated. The other detail is that the final spec requires the "payload" identifier in a `traceNV()` call to be a compile-time constant, which means it cannot be defined as a local variable first, as in: ```glsl int payloadID = 0; traceNV(..., payloadID); // ERROR ``` In terms of how the original support was implemented, the payload ID is being computed via a special builtin function that maps each global GLSL payload variable to a unique ID. There are a few ways we could try to resolve the problem here: 1. We could aspire to put our equivalent of the `constexpr` modifier on the output of the function, so that the GLSL variable gets declared `const` and thus fits the GLSL rules for a constant expression. 2. We could introduce a pass to replace the payload-location instructions with literal integers. 3. We could use a special-purpose instruction instead of a builtin function call, and have that instruction indicate that it doesn't have side effects (so it can be folded into the call site) 4. We could somehow mark the builtin function as not having side effects. We choose option (4) simply because it provides a feature that could have other applications. This change adds a `[__readNone]` attribute that can be applied to function declarations to express a promise on the part of the programmer that the given function has no side effects and computes its result strictly from the bits of its input arguments (and not things they point to, etc.). This mirrors an equivalent function attribute in LLVM. We mark the function that computes a ray payload location with this attribute, and propagate the attribute through the layers of the IR, so that when the emit logic asks if an operation has side effects (to see if it can be folded into the arguments of a subsequent expression), we get an affirmative response. This change should get all of the features that were present in the experiemntal `NVX` extension working with the final extension spec. It does not address callable shaders, which will come as a subsequent change.
m---------external/glslang0
-rw-r--r--source/slang/core.meta.slang6
-rw-r--r--source/slang/core.meta.slang.h6
-rw-r--r--source/slang/emit.cpp20
-rw-r--r--source/slang/hlsl.meta.slang47
-rw-r--r--source/slang/hlsl.meta.slang.h47
-rw-r--r--source/slang/ir-insts.h10
-rw-r--r--source/slang/ir-serialize.cpp7
-rw-r--r--source/slang/ir.cpp54
-rw-r--r--source/slang/ir.h13
-rw-r--r--source/slang/lower-to-ir.cpp5
-rw-r--r--source/slang/modifier-defs.h8
-rw-r--r--tests/vkray/anyhit.slang.glsl10
-rw-r--r--tests/vkray/closesthit.slang.glsl14
-rw-r--r--tests/vkray/intersection.slang.glsl14
-rw-r--r--tests/vkray/miss.slang.glsl4
-rw-r--r--tests/vkray/raygen.slang.glsl146
17 files changed, 253 insertions, 158 deletions
diff --git a/external/glslang b/external/glslang
-Subproject a8453d4bc00998049db0d448764784a6a076753
+Subproject 4207c97b938078818140edad101a032cf768191
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 0502c9bf6..26bf1112d 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -1238,3 +1238,9 @@ attribute_syntax [__vulkanHitAttributes] : VulkanHitAttributesAttribute;
__attributeTarget(FunctionDeclBase)
attribute_syntax [mutating] : MutatingAttribute;
+
+ /// Indicates that a function computes its result as a function of its arguments without loading/storing any memory or other state.
+ ///
+ /// This is equivalent to the LLVM `readnone` function attribute.
+__attributeTarget(FunctionDeclBase)
+attribute_syntax [__readNone] : ReadNoneAttribute;
diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h
index 97a2d1edd..5380bd90f 100644
--- a/source/slang/core.meta.slang.h
+++ b/source/slang/core.meta.slang.h
@@ -1256,3 +1256,9 @@ SLANG_RAW("attribute_syntax [__vulkanHitAttributes] : VulkanHitAttributesAttribu
SLANG_RAW("\n")
SLANG_RAW("__attributeTarget(FunctionDeclBase)\n")
SLANG_RAW("attribute_syntax [mutating] : MutatingAttribute;\n")
+SLANG_RAW("\n")
+SLANG_RAW(" /// Indicates that a function computes its result as a function of its arguments without loading/storing any memory or other state.\n")
+SLANG_RAW(" ///\n")
+SLANG_RAW(" /// This is equivalent to the LLVM `readnone` function attribute.\n")
+SLANG_RAW("__attributeTarget(FunctionDeclBase)\n")
+SLANG_RAW("attribute_syntax [__readNone] : ReadNoneAttribute;\n")
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index bb9a6ad8b..5c39dd50c 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -1168,8 +1168,8 @@ struct EmitVisitor
switch (type->op)
{
case kIROp_RaytracingAccelerationStructureType:
- requireGLSLExtension("GL_NVX_raytracing");
- Emit("accelerationStructureNVX");
+ requireGLSLExtension("GL_NV_ray_tracing");
+ Emit("accelerationStructureNV");
break;
// TODO: These "translations" are obviously wrong for GLSL.
@@ -3332,17 +3332,17 @@ struct EmitVisitor
case 'T':
{
// The `$XT` case handles selecting between
- // the `gl_HitTNVX` and `gl_RayTmaxNVX` builtins,
+ // the `gl_HitTNV` and `gl_RayTmaxNV` builtins,
// based on what stage we are using:
switch( ctx->shared->entryPoint->getStage() )
{
default:
- Emit("gl_RayTmaxNVX");
+ Emit("gl_RayTmaxNV");
break;
case Stage::AnyHit:
case Stage::ClosestHit:
- Emit("gl_HitTNVX");
+ Emit("gl_HitTNV");
break;
}
}
@@ -5363,11 +5363,11 @@ struct EmitVisitor
emit("layout(location = ");
Emit(getRayPayloadLocation(ctx, varDecl));
emit(")\n");
- emit("rayPayloadNVX\n");
+ emit("rayPayloadNV\n");
}
if(varDecl->findDecoration<IRVulkanHitAttributesDecoration>())
{
- emit("hitAttributeNVX\n");
+ emit("hitAttributeNV\n");
}
if (!layout)
@@ -5516,13 +5516,13 @@ struct EmitVisitor
case LayoutResourceKind::RayPayload:
{
- emit("rayPayloadInNVX ");
+ emit("rayPayloadInNV ");
}
break;
case LayoutResourceKind::HitAttributes:
{
- emit("hitAttributeNVX ");
+ emit("hitAttributeNV ");
}
break;
@@ -6535,7 +6535,7 @@ String emitEntryPoint(
case Stage::RayGeneration:
if( target == CodeGenTarget::GLSL )
{
- requireGLSLExtension(&context.shared->extensionUsageTracker, "GL_NVX_raytracing");
+ requireGLSLExtension(&context.shared->extensionUsageTracker, "GL_NV_ray_tracing");
requireGLSLVersionImpl(&context.shared->extensionUsageTracker, ProfileVersion::GLSL_460);
}
break;
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index c666dadd3..56741f6b3 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -1369,8 +1369,8 @@ void TraceRay<payload_t>(
RayDesc Ray,
inout payload_t Payload);
-__target_intrinsic(glsl, "traceNVX")
-void __traceNVX(
+__target_intrinsic(glsl, "traceNV")
+void __traceNV(
RaytracingAccelerationStructure AccelerationStructure,
uint RayFlags,
uint InstanceInclusionMask,
@@ -1391,6 +1391,7 @@ void __traceNVX(
//
__generic<Payload>
__target_intrinsic(glsl, "$XP")
+[__readNone]
int __rayPayloadLocation(Payload payload);
__generic<payload_t>
@@ -1409,7 +1410,7 @@ void TraceRay(
static payload_t p;
p = Payload;
- __traceNVX(
+ __traceNV(
AccelerationStructure,
RayFlags,
InstanceInclusionMask,
@@ -1427,8 +1428,8 @@ void TraceRay(
// 10.3.3
bool ReportHit<A>(float tHit, uint hitKind, A attributes);
-__target_intrinsic(glsl, "reportIntersectionNVX")
-bool __reportIntersectionNVX(float tHit, uint hitKind);
+__target_intrinsic(glsl, "reportIntersectionNV")
+bool __reportIntersectionNV(float tHit, uint hitKind);
__generic<A>
__specialized_for_target(glsl)
@@ -1438,15 +1439,15 @@ bool ReportHit(float tHit, uint hitKind, A attributes)
static A a;
a = attributes;
- return __reportIntersectionNVX(tHit, hitKind);
+ return __reportIntersectionNV(tHit, hitKind);
}
// 10.3.4
-__target_intrinsic(glsl, ignoreIntersectionNVX)
+__target_intrinsic(glsl, ignoreIntersectionNV)
void IgnoreHit();
// 10.3.5
-__target_intrinsic(glsl, terminateRayNVX)
+__target_intrinsic(glsl, terminateRayNV)
void AcceptHitAndEndSearch();
// 10.4 - System Values and Special Semantics
@@ -1456,25 +1457,25 @@ void AcceptHitAndEndSearch();
// 10.4.1 - Ray Dispatch System Values
-__target_intrinsic(glsl, "uvec3(gl_LaunchIDNVX, 0)")
+__target_intrinsic(glsl, "(gl_LaunchIDNV)")
uint3 DispatchRaysIndex();
-__target_intrinsic(glsl, "uvec3(gl_LaunchSizeNVX, 0)")
+__target_intrinsic(glsl, "(gl_LaunchSizeNV)")
uint3 DispatchRaysDimensions();
// 10.4.2 - Ray System Values
-__target_intrinsic(glsl, "(gl_WorldRayOriginNVX)")
+__target_intrinsic(glsl, "(gl_WorldRayOriginNV)")
float3 WorldRayOrigin();
-__target_intrinsic(glsl, "(gl_WorldRayDirectionNVX)")
+__target_intrinsic(glsl, "(gl_WorldRayDirectionNV)")
float3 WorldRayDirection();
-__target_intrinsic(glsl, "(gl_RayTminNVX)")
+__target_intrinsic(glsl, "(gl_RayTminNV)")
float RayTMin();
// Note: The `RayTCurrent()` intrinsic should translate to
-// either `gl_HitTNVX` (for hit shaders) or `gl_RayTmaxNVX`
+// either `gl_HitTNV` (for hit shaders) or `gl_RayTmaxNV`
// (for intersection shaders). Right now we are handling this
// during code emission, for simplicity.
//
@@ -1486,12 +1487,12 @@ float RayTMin();
__target_intrinsic(glsl, "$XT")
float RayTCurrent();
-__target_intrinsic(glsl, "(gl_RayFlagsNVX)")
+__target_intrinsic(glsl, "(gl_IncomingRayFlagsNV)")
uint RayFlags();
// 10.4.3 - Primitive/Object Space System Values
-__target_intrinsic(glsl, "(gl_InstanceCustomIndexNVX)")
+__target_intrinsic(glsl, "(gl_InstanceCustomIndexNV)")
uint InstanceIndex();
__target_intrinsic(glsl, "(gl_InstanceID)")
@@ -1500,22 +1501,22 @@ uint InstanceID();
__target_intrinsic(glsl, "(gl_PrimitiveID)")
uint PrimitiveIndex();
-__target_intrinsic(glsl, "(gl_ObjectRayOriginNVX)")
+__target_intrinsic(glsl, "(gl_ObjectRayOriginNV)")
float3 ObjectRayOrigin();
-__target_intrinsic(glsl, "(gl_ObjectRayDirectionNVX)")
+__target_intrinsic(glsl, "(gl_ObjectRayDirectionNV)")
float3 ObjectRayDirection();
-__target_intrinsic(glsl, "transpose(gl_ObjectToWorldNVX)")
+__target_intrinsic(glsl, "transpose(gl_ObjectToWorldNV)")
float3x4 ObjectToWorld3x4();
-__target_intrinsic(glsl, "transpose(gl_WorldToObjectNVX)")
+__target_intrinsic(glsl, "transpose(gl_WorldToObjectNV)")
float3x4 WorldToObject3x4();
-__target_intrinsic(glsl, "(gl_ObjectToWorldNVX)")
+__target_intrinsic(glsl, "(gl_ObjectToWorldNV)")
float4x3 ObjectToWorld4x3();
-__target_intrinsic(glsl, "(gl_WorldToObjectNVX)")
+__target_intrinsic(glsl, "(gl_WorldToObjectNV)")
float4x3 WorldToObject4x3();
// Note: The provisional DXR spec included these unadorned
@@ -1531,5 +1532,5 @@ float3x4 ObjectToWorld() { return ObjectToWorld3x4(); }
float3x4 WorldToObject() { return WorldToObject3x4(); }
// 10.4.4 - Hit Specific System values
-__target_intrinsic(glsl, "(gl_HitKindNVX)")
+__target_intrinsic(glsl, "(gl_HitKindNV)")
uint HitKind();
diff --git a/source/slang/hlsl.meta.slang.h b/source/slang/hlsl.meta.slang.h
index 2db710ccb..5e00c2719 100644
--- a/source/slang/hlsl.meta.slang.h
+++ b/source/slang/hlsl.meta.slang.h
@@ -1417,8 +1417,8 @@ SLANG_RAW(" uint MissShaderIndex,\n")
SLANG_RAW(" RayDesc Ray,\n")
SLANG_RAW(" inout payload_t Payload);\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"traceNVX\")\n")
-SLANG_RAW("void __traceNVX(\n")
+SLANG_RAW("__target_intrinsic(glsl, \"traceNV\")\n")
+SLANG_RAW("void __traceNV(\n")
SLANG_RAW(" RaytracingAccelerationStructure AccelerationStructure,\n")
SLANG_RAW(" uint RayFlags,\n")
SLANG_RAW(" uint InstanceInclusionMask,\n")
@@ -1439,6 +1439,7 @@ SLANG_RAW("// syntax works in a pinch.\n")
SLANG_RAW("//\n")
SLANG_RAW("__generic<Payload>\n")
SLANG_RAW("__target_intrinsic(glsl, \"$XP\")\n")
+SLANG_RAW("[__readNone]\n")
SLANG_RAW("int __rayPayloadLocation(Payload payload);\n")
SLANG_RAW("\n")
SLANG_RAW("__generic<payload_t>\n")
@@ -1457,7 +1458,7 @@ SLANG_RAW(" [__vulkanRayPayload]\n")
SLANG_RAW(" static payload_t p;\n")
SLANG_RAW("\n")
SLANG_RAW(" p = Payload;\n")
-SLANG_RAW(" __traceNVX(\n")
+SLANG_RAW(" __traceNV(\n")
SLANG_RAW(" AccelerationStructure,\n")
SLANG_RAW(" RayFlags,\n")
SLANG_RAW(" InstanceInclusionMask,\n")
@@ -1475,8 +1476,8 @@ SLANG_RAW("\n")
SLANG_RAW("// 10.3.3\n")
SLANG_RAW("bool ReportHit<A>(float tHit, uint hitKind, A attributes);\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"reportIntersectionNVX\")\n")
-SLANG_RAW("bool __reportIntersectionNVX(float tHit, uint hitKind);\n")
+SLANG_RAW("__target_intrinsic(glsl, \"reportIntersectionNV\")\n")
+SLANG_RAW("bool __reportIntersectionNV(float tHit, uint hitKind);\n")
SLANG_RAW("\n")
SLANG_RAW("__generic<A>\n")
SLANG_RAW("__specialized_for_target(glsl)\n")
@@ -1486,15 +1487,15 @@ SLANG_RAW(" [__vulkanHitAttributes]\n")
SLANG_RAW(" static A a;\n")
SLANG_RAW("\n")
SLANG_RAW(" a = attributes;\n")
-SLANG_RAW(" return __reportIntersectionNVX(tHit, hitKind);\n")
+SLANG_RAW(" return __reportIntersectionNV(tHit, hitKind);\n")
SLANG_RAW("}\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.3.4\n")
-SLANG_RAW("__target_intrinsic(glsl, ignoreIntersectionNVX)\n")
+SLANG_RAW("__target_intrinsic(glsl, ignoreIntersectionNV)\n")
SLANG_RAW("void IgnoreHit();\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.3.5\n")
-SLANG_RAW("__target_intrinsic(glsl, terminateRayNVX)\n")
+SLANG_RAW("__target_intrinsic(glsl, terminateRayNV)\n")
SLANG_RAW("void AcceptHitAndEndSearch();\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.4 - System Values and Special Semantics\n")
@@ -1504,25 +1505,25 @@ SLANG_RAW("// they can only be accessed from specific stages.\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.4.1 - Ray Dispatch System Values\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"uvec3(gl_LaunchIDNVX, 0)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_LaunchIDNV)\")\n")
SLANG_RAW("uint3 DispatchRaysIndex();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"uvec3(gl_LaunchSizeNVX, 0)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_LaunchSizeNV)\")\n")
SLANG_RAW("uint3 DispatchRaysDimensions();\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.4.2 - Ray System Values\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldRayOriginNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldRayOriginNV)\")\n")
SLANG_RAW("float3 WorldRayOrigin();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldRayDirectionNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldRayDirectionNV)\")\n")
SLANG_RAW("float3 WorldRayDirection();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_RayTminNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_RayTminNV)\")\n")
SLANG_RAW("float RayTMin();\n")
SLANG_RAW("\n")
SLANG_RAW("// Note: The `RayTCurrent()` intrinsic should translate to\n")
-SLANG_RAW("// either `gl_HitTNVX` (for hit shaders) or `gl_RayTmaxNVX`\n")
+SLANG_RAW("// either `gl_HitTNV` (for hit shaders) or `gl_RayTmaxNV`\n")
SLANG_RAW("// (for intersection shaders). Right now we are handling this\n")
SLANG_RAW("// during code emission, for simplicity.\n")
SLANG_RAW("//\n")
@@ -1534,12 +1535,12 @@ SLANG_RAW("//\n")
SLANG_RAW("__target_intrinsic(glsl, \"$XT\")\n")
SLANG_RAW("float RayTCurrent();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_RayFlagsNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_IncomingRayFlagsNV)\")\n")
SLANG_RAW("uint RayFlags();\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.4.3 - Primitive/Object Space System Values\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_InstanceCustomIndexNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_InstanceCustomIndexNV)\")\n")
SLANG_RAW("uint InstanceIndex();\n")
SLANG_RAW("\n")
SLANG_RAW("__target_intrinsic(glsl, \"(gl_InstanceID)\")\n")
@@ -1548,22 +1549,22 @@ SLANG_RAW("\n")
SLANG_RAW("__target_intrinsic(glsl, \"(gl_PrimitiveID)\")\n")
SLANG_RAW("uint PrimitiveIndex();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectRayOriginNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectRayOriginNV)\")\n")
SLANG_RAW("float3 ObjectRayOrigin();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectRayDirectionNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectRayDirectionNV)\")\n")
SLANG_RAW("float3 ObjectRayDirection();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"transpose(gl_ObjectToWorldNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"transpose(gl_ObjectToWorldNV)\")\n")
SLANG_RAW("float3x4 ObjectToWorld3x4();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"transpose(gl_WorldToObjectNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"transpose(gl_WorldToObjectNV)\")\n")
SLANG_RAW("float3x4 WorldToObject3x4();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectToWorldNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectToWorldNV)\")\n")
SLANG_RAW("float4x3 ObjectToWorld4x3();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldToObjectNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldToObjectNV)\")\n")
SLANG_RAW("float4x3 WorldToObject4x3();\n")
SLANG_RAW("\n")
SLANG_RAW("// Note: The provisional DXR spec included these unadorned\n")
@@ -1579,5 +1580,5 @@ SLANG_RAW("float3x4 ObjectToWorld() { return ObjectToWorld3x4(); }\n")
SLANG_RAW("float3x4 WorldToObject() { return WorldToObject3x4(); }\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.4.4 - Hit Specific System values\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_HitKindNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_HitKindNV)\")\n")
SLANG_RAW("uint HitKind();\n")
diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h
index 6075c247c..db61cae88 100644
--- a/source/slang/ir-insts.h
+++ b/source/slang/ir-insts.h
@@ -147,6 +147,11 @@ struct IRRequireGLSLExtensionDecoration : IRDecoration
StringRepresentation* extensionName;
};
+struct IRReadNoneDecoration : IRDecoration
+{
+ enum { kDecorationOp = kIRDecorationOp_ReadNone };
+};
+
// An instruction that specializes another IR value
// (representing a generic) to a particular set of generic arguments
// (instructions representing types, witness tables, etc.)
@@ -187,6 +192,11 @@ struct IRLookupWitnessTable : IRInst
struct IRCall : IRInst
{
IRUse func;
+
+ IRInst* getCallee() { return getOperand(0); }
+
+ UInt getArgCount() { return getOperandCount() - 1; }
+ IRInst* getArg(UInt index) { return getOperand(index + 1); }
};
struct IRLoad : IRInst
diff --git a/source/slang/ir-serialize.cpp b/source/slang/ir-serialize.cpp
index e2fd6d3f8..7cc3d6384 100644
--- a/source/slang/ir-serialize.cpp
+++ b/source/slang/ir-serialize.cpp
@@ -705,6 +705,7 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
}
case kIRDecorationOp_VulkanRayPayload:
case kIRDecorationOp_VulkanHitAttributes:
+ case kIRDecorationOp_ReadNone:
{
dstInst.m_payloadType = PayloadType::Empty;
break;
@@ -1579,6 +1580,12 @@ IRDecoration* IRSerialReader::_createDecoration(const Ser::Inst& srcInst)
decor->languageVersion = Int(srcInst.m_payload.m_uint32);
return decor;
}
+ case kIRDecorationOp_ReadNone:
+ {
+ auto decor = createEmptyDecoration<IRReadNoneDecoration>(m_module);
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty);
+ return decor;
+ }
default:
{
SLANG_ASSERT(!"Unhandled decoration type");
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index cc3350aef..a66b26e93 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -2939,6 +2939,11 @@ namespace Slang
dump(context, "\n[__vulkanHitAttributes]");
}
break;
+ case kIRDecorationOp_ReadNone:
+ {
+ dump(context, "\n[__readNone]");
+ }
+ break;
}
}
}
@@ -3521,7 +3526,30 @@ namespace Slang
return true;
case kIROp_Call:
- // This is the most interesting.
+ {
+ // In the general case, a function call must be assumed to
+ // have almost arbitrary side effects.
+ //
+ // However, it is possible that the callee can be identified,
+ // and it may be a function with an attribute that explicitly
+ // limits the side effects it is allowed to have.
+ //
+ // For now, we will explicitly check for the `[__readNone]`
+ // attribute, which was used to mark functions that compute
+ // their result strictly as a function of the arguments (and
+ // not anything they point to, or other non-argument state).
+ // Calls to such functions cannot have side effects (except
+ // for things like stack overflow that abstract language models
+ // tend to ignore), and can be subject to dead code elimination,
+ // common subexpression elimination, etc.
+ //
+ auto call = cast<IRCall>(this);
+ auto callee = getResolvedInstForDecorations(call->getCallee());
+ if(callee->findDecoration<IRReadNoneDecoration>())
+ {
+ return false;
+ }
+ }
return true;
case kIROp_Nop:
@@ -5371,6 +5399,12 @@ namespace Slang
}
break;
+ case kIRDecorationOp_ReadNone:
+ {
+ context->builder->addDecoration<IRReadNoneDecoration>(clonedValue);
+ }
+ break;
+
default:
// Don't clone any decorations we don't understand.
break;
@@ -6005,6 +6039,24 @@ namespace Slang
return val;
}
+ IRInst* getResolvedInstForDecorations(IRInst* inst)
+ {
+ IRInst* candidate = inst;
+ while(auto specInst = as<IRSpecialize>(candidate))
+ {
+ auto genericInst = as<IRGeneric>(specInst->getBase());
+ if(!genericInst)
+ break;
+
+ auto returnVal = findGenericReturnVal(genericInst);
+ if(!returnVal)
+ break;
+
+ candidate = returnVal;
+ }
+ return candidate;
+ }
+
bool isDefinition(
IRGlobalValue* inVal)
{
diff --git a/source/slang/ir.h b/source/slang/ir.h
index 41c9ab6ab..def68098d 100644
--- a/source/slang/ir.h
+++ b/source/slang/ir.h
@@ -157,8 +157,9 @@ enum IRDecorationOp : uint16_t
kIRDecorationOp_VulkanHitAttributes,
kIRDecorationOp_RequireGLSLVersion,
kIRDecorationOp_RequireGLSLExtension,
-
- kIRDecorationOp_CountOf
+ kIRDecorationOp_ReadNone,
+
+ kIRDecorationOp_CountOf
};
// represents an object allocated in an IR memory arena
@@ -1048,6 +1049,14 @@ struct IRGeneric : IRGlobalValueWithParams
// a pass can glean information from it.
IRInst* findGenericReturnVal(IRGeneric* generic);
+// Resolve an instruction that might reference a static definition
+// to the most specific IR node possible, so that we can read
+// decorations from it (e.g., if this is a `specialize` instruction,
+// then try to chase down the generic being specialized, and what
+// it seems to return).
+//
+IRInst* getResolvedInstForDecorations(IRInst* inst);
+
// The IR module itself is represented as an instruction, which
// serves at the root of the tree of all instructions in the module.
struct IRModuleInst : IRParentInst
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index 806654ccb..815822495 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -5137,6 +5137,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
decoration->languageVersion = Int(getIntegerLiteralValue(versionMod->versionNumberToken));
}
+ if(decl->FindModifier<ReadNoneAttribute>())
+ {
+ getBuilder()->addDecoration<IRReadNoneDecoration>(irFunc);
+ }
+
// For convenience, ensure that any additional global
// values that were emitted while outputting the function
// body appear before the function itself in the list
diff --git a/source/slang/modifier-defs.h b/source/slang/modifier-defs.h
index dc4e99cdd..bb9aefcb7 100644
--- a/source/slang/modifier-defs.h
+++ b/source/slang/modifier-defs.h
@@ -405,6 +405,14 @@ SIMPLE_SYNTAX_CLASS(VulkanHitAttributesAttribute, Attribute)
//
SIMPLE_SYNTAX_CLASS(MutatingAttribute, Attribute)
+// A `[__readNone]` attribute, which indicates that a function
+// computes its results strictly based on argument values, without
+// reading or writing through any pointer arguments, or any other
+// state that could be observed by a caller.
+//
+SIMPLE_SYNTAX_CLASS(ReadNoneAttribute, Attribute)
+
+
// HLSL modifiers for geometry shader input topology
SIMPLE_SYNTAX_CLASS(HLSLGeometryShaderInputPrimitiveTypeModifier, Modifier)
SIMPLE_SYNTAX_CLASS(HLSLPointModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
diff --git a/tests/vkray/anyhit.slang.glsl b/tests/vkray/anyhit.slang.glsl
index 7fb9ac553..43fd29e01 100644
--- a/tests/vkray/anyhit.slang.glsl
+++ b/tests/vkray/anyhit.slang.glsl
@@ -1,6 +1,6 @@
// anyhit.slang.glsl
#version 460
-#extension GL_NVX_raytracing : require
+#extension GL_NV_ray_tracing : require
struct Params_0
{
@@ -23,13 +23,13 @@ struct SphereHitAttributes_0
{
vec3 normal_0;
};
-hitAttributeNVX SphereHitAttributes_0 _S2;
+hitAttributeNV SphereHitAttributes_0 _S2;
struct ShadowRay_0
{
vec4 hitDistance_0;
};
-rayPayloadInNVX ShadowRay_0 _S3;
+rayPayloadInNV ShadowRay_0 _S3;
void main()
{
@@ -45,11 +45,11 @@ void main()
if(val_0 > float(0))
{
- terminateRayNVX();
+ terminateRayNV();
}
else
{
- ignoreIntersectionNVX();
+ ignoreIntersectionNV();
}
}
diff --git a/tests/vkray/closesthit.slang.glsl b/tests/vkray/closesthit.slang.glsl
index 2db319a7f..d4b9e7a6a 100644
--- a/tests/vkray/closesthit.slang.glsl
+++ b/tests/vkray/closesthit.slang.glsl
@@ -1,6 +1,6 @@
// closesthit.slang.glsl
#version 460
-#extension GL_NVX_raytracing : require
+#extension GL_NV_ray_tracing : require
layout(std430) buffer _S1
{
@@ -12,32 +12,32 @@ struct BuiltInTriangleIntersectionAttributes_0
vec2 barycentrics_0;
};
-hitAttributeNVX BuiltInTriangleIntersectionAttributes_0 _S2;
+hitAttributeNV BuiltInTriangleIntersectionAttributes_0 _S2;
struct ReflectionRay_0
{
vec4 color_0;
};
-rayPayloadInNVX ReflectionRay_0 _S3;
+rayPayloadInNV ReflectionRay_0 _S3;
void main()
{
BuiltInTriangleIntersectionAttributes_0 _S4 = _S2;
- uint _S5 = gl_InstanceCustomIndexNVX;
+ uint _S5 = gl_InstanceCustomIndexNV;
uint _S6 = gl_InstanceID;
uint _S7 = _S5 + _S6;
uint _S8 = gl_PrimitiveID;
uint _S9 = _S7 + _S8;
- uint _S10 = gl_HitKindNVX;
+ uint _S10 = gl_HitKindNV;
vec4 color_1 = colors_0[_S9 + _S10];
- float _S11 = gl_HitTNVX;
- float _S12 = gl_RayTminNVX;
+ float _S11 = gl_HitTNV;
+ float _S12 = gl_RayTminNV;
_S3.color_0 = color_1 * (_S11 - _S12);
diff --git a/tests/vkray/intersection.slang.glsl b/tests/vkray/intersection.slang.glsl
index 2fb999947..cfa53efa7 100644
--- a/tests/vkray/intersection.slang.glsl
+++ b/tests/vkray/intersection.slang.glsl
@@ -1,7 +1,7 @@
//TEST_IGNORE_FILE:
#version 460
-#extension GL_NVX_raytracing : require
+#extension GL_NV_ray_tracing : require
struct Sphere_0
{
@@ -40,28 +40,28 @@ bool rayIntersectsSphere_0(
return tHit_0 >= ray_0.TMin_0;
}
-hitAttributeNVX SphereHitAttributes_0 a_0;
+hitAttributeNV SphereHitAttributes_0 a_0;
bool ReportHit_0(float tHit_1, uint hitKind_0, SphereHitAttributes_0 attributes_0)
{
a_0 = attributes_0;
- bool _S1 = reportIntersectionNVX(tHit_1, hitKind_0);
+ bool _S1 = reportIntersectionNV(tHit_1, hitKind_0);
return _S1;
}
void main()
{
RayDesc_0 ray_1;
- vec3 _S2 = gl_ObjectRayOriginNVX;
+ vec3 _S2 = gl_ObjectRayOriginNV;
ray_1.Origin_0 = _S2;
- vec3 _S3 = gl_ObjectRayDirectionNVX;
+ vec3 _S3 = gl_ObjectRayDirectionNV;
ray_1.Direction_0 = _S3;
- float _S4 = gl_RayTminNVX;
+ float _S4 = gl_RayTminNV;
ray_1.TMin_0 = _S4;
- float _S5 = gl_RayTmaxNVX;
+ float _S5 = gl_RayTmaxNV;
ray_1.TMax_0 = _S5;
diff --git a/tests/vkray/miss.slang.glsl b/tests/vkray/miss.slang.glsl
index 7ced92c24..33cff4a34 100644
--- a/tests/vkray/miss.slang.glsl
+++ b/tests/vkray/miss.slang.glsl
@@ -1,14 +1,14 @@
//TEST_IGNORE_FILE:
#version 460
-#extension GL_NVX_raytracing : require
+#extension GL_NV_ray_tracing : require
struct ShadowRay_0
{
float hitDistance_0;
};
-rayPayloadInNVX ShadowRay_0 _S1;
+rayPayloadInNV ShadowRay_0 _S1;
void main()
{
diff --git a/tests/vkray/raygen.slang.glsl b/tests/vkray/raygen.slang.glsl
index 2df4b9219..512215a73 100644
--- a/tests/vkray/raygen.slang.glsl
+++ b/tests/vkray/raygen.slang.glsl
@@ -1,7 +1,7 @@
//TEST_IGNORE_FILE:
#version 460
-#extension GL_NVX_raytracing : require
+#extension GL_NV_ray_tracing : require
#define TRACING_EPSILON 1e-6
@@ -26,19 +26,19 @@ layout(std140) uniform ubo_0
layout(row_major) mat4x4 model_0;
};
-layout(binding = 5) uniform accelerationStructureNVX as_0;
+layout(binding = 5) uniform accelerationStructureNV as_0;
struct ShadowRay_0
{
float hitDistance_0;
};
-layout(location = 0) rayPayloadNVX ShadowRay_0 p_0;
+layout(location = 0) rayPayloadNV ShadowRay_0 p_0;
struct ReflectionRay_0
{
float color_1;
};
-layout(location = 1) rayPayloadNVX ReflectionRay_0 p_1;
+layout(location = 1) rayPayloadNV ReflectionRay_0 p_1;
layout(rgba32f) layout(binding = 4) uniform image2D outputImage_0;
@@ -51,7 +51,7 @@ struct RayDesc_0
};
void TraceRay_0(
- accelerationStructureNVX AccelerationStructure_0,
+ accelerationStructureNV AccelerationStructure_0,
uint RayFlags_0,
uint InstanceInclusionMask_0,
uint RayContributionToHitGroupIndex_0,
@@ -61,35 +61,30 @@ void TraceRay_0(
inout ShadowRay_0 Payload_0)
{
p_0 = Payload_0;
- vec3 _S1 = Ray_0.Origin_0;
- float _S2 = Ray_0.TMin_0;
- vec3 _S3 = Ray_0.Direction_0;
- float _S4 = Ray_0.TMax_0;
- int _S5 = 0;
- traceNVX(
+ traceNV(
AccelerationStructure_0,
RayFlags_0,
InstanceInclusionMask_0,
RayContributionToHitGroupIndex_0,
MultiplierForGeometryContributionToHitGroupIndex_0,
MissShaderIndex_0,
- _S1,
- _S2,
- _S3,
- _S4,
- _S5);
+ Ray_0.Origin_0,
+ Ray_0.TMin_0,
+ Ray_0.Direction_0,
+ Ray_0.TMax_0,
+ 0);
Payload_0 = p_0;
return;
}
float saturate_0(float x_0)
{
- float _S6 = clamp(x_0, float(0), float(1));
- return _S6;
+ float _S1 = clamp(x_0, float(0), float(1));
+ return _S1;
}
void TraceRay_1(
- accelerationStructureNVX AccelerationStructure_1,
+ accelerationStructureNV AccelerationStructure_1,
uint RayFlags_1,
uint InstanceInclusionMask_1,
uint RayContributionToHitGroupIndex_1,
@@ -99,23 +94,18 @@ void TraceRay_1(
inout ReflectionRay_0 Payload_1)
{
p_1 = Payload_1;
- vec3 _S7 = Ray_1.Origin_0;
- float _S8 = Ray_1.TMin_0;
- vec3 _S9 = Ray_1.Direction_0;
- float _S10 = Ray_1.TMax_0;
- int _S11 = 1;
- traceNVX(
+ traceNV(
AccelerationStructure_1,
RayFlags_1,
InstanceInclusionMask_1,
RayContributionToHitGroupIndex_1,
MultiplierForGeometryContributionToHitGroupIndex_1,
MissShaderIndex_1,
- _S7,
- _S8,
- _S9,
- _S10,
- _S11);
+ Ray_1.Origin_0,
+ Ray_1.TMin_0,
+ Ray_1.Direction_0,
+ Ray_1.TMax_0,
+ 1);
Payload_1 = p_1;
return;
}
@@ -124,27 +114,27 @@ void main()
{
float atten_0;
- uvec3 _S12 = uvec3(gl_LaunchIDNVX, 0);
- float _S13 = float(_S12.x) + 0.5;
- uvec3 _S14 = uvec3(gl_LaunchSizeNVX, 0);
- float _S15 = _S13 / float(_S14.x);
- uvec3 _S16 = uvec3(gl_LaunchIDNVX, 0);
- float _S17 = float(_S16.y) + 0.5;
- uvec3 _S18 = uvec3(gl_LaunchSizeNVX, 0);
- float _S19 = _S17 / float(_S18.y);
- vec2 inUV_0 = vec2(_S15, _S19);
+ uvec3 _S2 = gl_LaunchIDNV;
+ float _S3 = float(_S2.x) + 0.5;
+ uvec3 _S4 = gl_LaunchSizeNV;
+ float _S5 = _S3 / float(_S4.x);
+ uvec3 _S6 = gl_LaunchIDNV;
+ float _S7 = float(_S6.y) + 0.5;
+ uvec3 _S8 = gl_LaunchSizeNV;
+ float _S9 = _S7 / float(_S8.y);
+ vec2 inUV_0 = vec2(_S5, _S9);
- vec4 _S20 = texture(sampler2D(samplerPosition_0, sampler_0), inUV_0);
- vec3 P_0 = _S20.xyz;
+ vec4 _S10 = texture(sampler2D(samplerPosition_0, sampler_0), inUV_0);
+ vec3 P_0 = _S10.xyz;
- vec4 _S21 = texture(sampler2D(samplerNormal_0, sampler_0), inUV_0);
- vec3 N_0 = _S21.xyz * 2.0 - 1.0;
+ vec4 _S11 = texture(sampler2D(samplerNormal_0, sampler_0), inUV_0);
+ vec3 N_0 = _S11.xyz * 2.0 - 1.0;
vec3 lightDelta_0 = light_0.position_0.xyz - P_0;
float lightDist_0 = length(lightDelta_0);
vec3 L_0 = normalize(lightDelta_0);
- float _S22 = 1.0 / (lightDist_0 * lightDist_0);
+ float _S12 = 1.0 / (lightDist_0 * lightDist_0);
RayDesc_0 ray_0;
ray_0.Origin_0 = P_0;
@@ -154,47 +144,47 @@ void main()
ShadowRay_0 shadowRay_0;
shadowRay_0.hitDistance_0 = float(0);
- const uint _S23 = uint(1);
- const uint _S24 = uint(0xFF);
- const uint _S25 = uint(0);
- const uint _S26 = uint(0);
- const uint _S27 = uint(2);
-
- RayDesc_0 _S28 = ray_0;
- ShadowRay_0 _S29;
- _S29 = shadowRay_0;
- TraceRay_0(as_0, _S23, _S24, _S25, _S26, _S27, _S28, _S29);
- shadowRay_0 = _S29;
-
- bool _S30 = shadowRay_0.hitDistance_0 < lightDist_0;
+ const uint _S13 = uint(1);
+ const uint _S14 = uint(0xFF);
+ const uint _S15 = uint(0);
+ const uint _S16 = uint(0);
+ const uint _S17 = uint(2);
+
+ RayDesc_0 _S18 = ray_0;
+ ShadowRay_0 _S19;
+ _S19 = shadowRay_0;
+ TraceRay_0(as_0, _S13, _S14, _S15, _S16, _S17, _S18, _S19);
+ shadowRay_0 = _S19;
+
+ bool _S20 = shadowRay_0.hitDistance_0 < lightDist_0;
ReflectionRay_0 reflectionRay_0;
- if(_S30)
+ if(_S20)
{
atten_0 = (0.00000000000000000000);
}
else
{
- atten_0 = _S22;
+ atten_0 = _S12;
}
- vec3 _S31 = light_0.color_0.xyz;
- float _S32 = dot(N_0, L_0);
- float _S33 = saturate_0(_S32);
- vec3 color_2 = (_S31 * _S33) * atten_0;
-
- const uint _S34 = uint(1);
- const uint _S35 = uint(255);
- const uint _S36 = uint(0);
- const uint _S37 = uint(0);
- const uint _S38 = uint(2);
- RayDesc_0 _S39 = ray_0;
- ReflectionRay_0 _S40;
- _S40 = reflectionRay_0;
- TraceRay_1(as_0, _S34, _S35, _S36, _S37, _S38, _S39, _S40);
-
- vec3 color_3 = color_2 + _S40.color_1;
-
- uvec3 _S41 = uvec3(gl_LaunchIDNVX, 0);
- imageStore(outputImage_0, ivec2(uvec2(ivec2(_S41.xy))), vec4(color_3, 1.0));
+ vec3 _S21 = light_0.color_0.xyz;
+ float _S22 = dot(N_0, L_0);
+ float _S23 = saturate_0(_S22);
+ vec3 color_2 = (_S21 * _S23) * atten_0;
+
+ const uint _S24 = uint(1);
+ const uint _S25 = uint(255);
+ const uint _S26 = uint(0);
+ const uint _S27 = uint(0);
+ const uint _S28 = uint(2);
+ RayDesc_0 _S29 = ray_0;
+ ReflectionRay_0 _S30;
+ _S30 = reflectionRay_0;
+ TraceRay_1(as_0, _S24, _S25, _S26, _S27, _S28, _S29, _S30);
+
+ vec3 color_3 = color_2 + _S30.color_1;
+
+ uvec3 _S31 = gl_LaunchIDNV;
+ imageStore(outputImage_0, ivec2(uvec2(ivec2(_S31.xy))), vec4(color_3, 1.0));
return;
}