summaryrefslogtreecommitdiffstats
path: root/source/slang/emit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/emit.cpp')
-rw-r--r--source/slang/emit.cpp155
1 files changed, 140 insertions, 15 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 521a9fe1f..312e8c0b3 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -146,6 +146,8 @@ struct SharedEmitContext
Dictionary<IRInst*, String> mapInstToName;
DiagnosticSink* getSink() { return &entryPoint->compileRequest->mSink; }
+
+ Dictionary<IRInst*, UInt> mapIRValueToRayPayloadLocation;
};
struct EmitContext
@@ -1162,13 +1164,17 @@ struct EmitVisitor
case CodeGenTarget::GLSL:
{
- // TODO: This "translation" is obviously wrong for GLSL.
switch (type->op)
{
+ case kIROp_RaytracingAccelerationStructureType:
+ requireGLSLExtension("GL_NVX_raytracing");
+ Emit("accelerationStructureNVX");
+ break;
+
+ // TODO: These "translations" are obviously wrong for GLSL.
case kIROp_HLSLByteAddressBufferType: Emit("ByteAddressBuffer"); break;
case kIROp_HLSLRWByteAddressBufferType: Emit("RWByteAddressBuffer"); break;
case kIROp_HLSLRasterizerOrderedByteAddressBufferType: Emit("RasterizerOrderedByteAddressBuffer"); break;
- case kIROp_RaytracingAccelerationStructureType: Emit("RaytracingAccelerationStructure"); break;
default:
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled buffer type");
@@ -1886,6 +1892,7 @@ struct EmitVisitor
CASE(GLSL_430, 430);
CASE(GLSL_440, 440);
CASE(GLSL_450, 450);
+ CASE(GLSL_460, 460);
#undef CASE
default:
@@ -2444,6 +2451,10 @@ struct EmitVisitor
{
return true;
}
+ else if(as<IRUntypedBufferResourceType>(type))
+ {
+ return true;
+ }
else if(as<IRSamplerStateTypeBase>(type))
{
return true;
@@ -3236,6 +3247,57 @@ struct EmitVisitor
}
break;
+ // We will use the `$X` case as a prefix for
+ // special logic needed when cross-compiling ray-tracing
+ // shaders.
+ case 'X':
+ {
+ SLANG_RELEASE_ASSERT(*cursor);
+ switch(*cursor++)
+ {
+ case 'P':
+ {
+ // The `$XP` case handles looking up
+ // the assocaited `location` for a variable
+ // used as the argument ray payload at a
+ // trace call site.
+
+ UInt argIndex = 0;
+ SLANG_RELEASE_ASSERT(argCount > argIndex);
+ auto arg = args[argIndex].get();
+ auto argLoad = as<IRLoad>(arg);
+ SLANG_RELEASE_ASSERT(argLoad);
+ auto argVar = argLoad->getOperand(0);
+ Emit(getRayPayloadLocation(ctx, argVar));
+ }
+ break;
+
+ case 'T':
+ {
+ // The `$XT` case handles selecting between
+ // the `gl_HitTNVX` and `gl_RayTmaxNVX` builtins,
+ // based on what stage we are using:
+ switch( ctx->shared->entryPoint->getStage() )
+ {
+ default:
+ Emit("gl_RayTmaxNVX");
+ break;
+
+ case Stage::AnyHit:
+ case Stage::ClosestHit:
+ Emit("gl_HitTNVX");
+ break;
+ }
+ }
+ break;
+
+ default:
+ SLANG_RELEASE_ASSERT(false);
+ break;
+ }
+ }
+ break;
+
default:
SLANG_UNEXPECTED("bad format in intrinsic definition");
break;
@@ -3910,7 +3972,10 @@ struct EmitVisitor
}
else if (auto entryPointLayout = layout->dynamicCast<EntryPointLayout>())
{
- emitIRSemantics(ctx, entryPointLayout->resultLayout);
+ if(auto resultLayout = entryPointLayout->resultLayout)
+ {
+ emitIRSemantics(ctx, resultLayout);
+ }
}
}
}
@@ -4353,18 +4418,7 @@ struct EmitVisitor
{
if(profile.GetVersion() >= ProfileVersion::DX_6_1 )
{
- char const* stageName = nullptr;
- switch(stage)
- {
- #define PROFILE_STAGE(ID, NAME, ENUM) \
- case Stage::ID: stageName = #NAME; break;
-
- #include "profile-defs.h"
-
- default:
- break;
- }
-
+ char const* stageName = getStageName(stage);
if(stageName)
{
emit("[shader(\"");
@@ -4917,6 +4971,13 @@ struct EmitVisitor
EmitContext* ctx,
IRStructType* structType)
{
+ // If the selected `struct` type is actually an intrinsic
+ // on our target, then we don't want to emit anything at all.
+ if(auto intrinsicDecoration = findTargetIntrinsicDecoration(ctx, structType))
+ {
+ return;
+ }
+
emit("struct ");
emit(getIRName(structType));
emit("\n{\n");
@@ -5102,12 +5163,43 @@ struct EmitVisitor
}
}
+ UInt getRayPayloadLocation(
+ EmitContext* ctx,
+ IRInst* inst)
+ {
+ auto& map = ctx->shared->mapIRValueToRayPayloadLocation;
+ UInt value = 0;
+ if(map.TryGetValue(inst, value))
+ return value;
+
+ value = map.Count();
+ map.Add(inst, value);
+ return value;
+ }
+
void emitIRVarModifiers(
EmitContext* ctx,
VarLayout* layout,
IRInst* varDecl,
IRType* varType)
{
+ // Deal with Vulkan raytracing layout stuff *before* we
+ // do the check for whether `layout` is null, because
+ // the payload won't automatically get a layout applied
+ // (it isn't part of the user-visible interface...)
+ //
+ if(varDecl->findDecoration<IRVulkanRayPayloadDecoration>())
+ {
+ emit("layout(location = ");
+ Emit(getRayPayloadLocation(ctx, varDecl));
+ emit(")\n");
+ emit("rayPayloadNVX\n");
+ }
+ if(varDecl->findDecoration<IRVulkanHitAttributesDecoration>())
+ {
+ emit("hitAttributeNVX\n");
+ }
+
if (!layout)
return;
@@ -5252,6 +5344,18 @@ struct EmitVisitor
}
break;
+ case LayoutResourceKind::RayPayload:
+ {
+ emit("rayPayloadInNVX ");
+ }
+ break;
+
+ case LayoutResourceKind::HitAttributes:
+ {
+ emit("hitAttributeNVX ");
+ }
+ break;
+
default:
continue;
}
@@ -6239,6 +6343,27 @@ String emitEntryPoint(
}
destroyIRSpecializationState(irSpecializationState);
+ // Deal with cases where a particular stage requires certain GLSL versions
+ // and/or extensions.
+ switch( entryPoint->getStage() )
+ {
+ default:
+ break;
+
+ case Stage::AnyHit:
+ case Stage::Callable:
+ case Stage::ClosestHit:
+ case Stage::Intersection:
+ case Stage::Miss:
+ case Stage::RayGeneration:
+ if( target == CodeGenTarget::GLSL )
+ {
+ requireGLSLExtension(&context.shared->extensionUsageTracker, "GL_NVX_raytracing");
+ requireGLSLVersionImpl(&context.shared->extensionUsageTracker, ProfileVersion::GLSL_460);
+ }
+ break;
+ }
+
String code = sharedContext.sb.ProduceString();
sharedContext.sb.Clear();