summaryrefslogtreecommitdiffstats
path: root/source/slang/emit.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-12-08 14:23:12 -0800
committerGitHub <noreply@github.com>2017-12-08 14:23:12 -0800
commit0f55649cc1aa8ad3218b7f8ba7b1eabdd2ec6526 (patch)
tree0dc7fd5e88fbc530dc121946f4a20085aa5518d8 /source/slang/emit.cpp
parent301cdf5ef42797b1073d9e6c741ef0ba98a38792 (diff)
Cleanups to `ParameterBlock<T>` behavior. (#304)
* Cleanups to `ParameterBlock<T>` behavior. These add some more realistic tests using the `ParameterBlock<T>` support, and show that it can work with the "rewriter" mode. Unfortunately, this code does *not* currently work with the rewriter + the IR at once. That will need to be fixed in a follow-on change, because I now see that the root problem is pretty ugly. * cleanup
Diffstat (limited to 'source/slang/emit.cpp')
-rw-r--r--source/slang/emit.cpp177
1 files changed, 160 insertions, 17 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index b9aa3c027..09d209f6e 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -96,7 +96,9 @@ struct SharedEmitContext
ExtensionUsageTracker extensionUsageTracker;
+ UInt uniqueIDCounter = 1;
Dictionary<IRValue*, UInt> mapIRValueToID;
+ Dictionary<Decl*, UInt> mapDeclToID;
HashSet<Decl*> irDeclsVisited;
@@ -503,6 +505,23 @@ struct EmitVisitor
emitName(name, SourceLoc());
}
+ void emitName(
+ Decl* decl,
+ SourceLoc const& loc)
+ {
+ if(auto name = decl->getName())
+ emitName(name, loc);
+
+ Emit("_S");
+ Emit(getID(decl));
+ }
+
+ void emitName(
+ Decl* decl)
+ {
+ emitName(decl, SourceLoc());
+ }
+
void Emit(IntegerLiteralValue value)
{
char buffer[32];
@@ -3571,31 +3590,95 @@ struct EmitVisitor
auto offsetResource = rr;
- if(kind != LayoutResourceKind::Uniform)
+ if(layout
+ && kind != LayoutResourceKind::Uniform)
{
// Add the base index from the cbuffer into the index of the field
//
// TODO(tfoley): consider maybe not doing this, since it actually
// complicates logic around constant buffers...
- // If the member of the cbuffer uses a resource, it had better
- // appear as part of the cubffer layout as well.
+ // If the member of the cbuffer uses a resource, we would typically
+ // expect to see that the `cbuffer` itself shows up as using that
+ // resource too.
auto cbufferResource = layout->FindResourceInfo(kind);
- SLANG_RELEASE_ASSERT(cbufferResource);
-
- offsetResource.index += cbufferResource->index;
- offsetResource.space += cbufferResource->space;
+ if(cbufferResource)
+ {
+ offsetResource.index += cbufferResource->index;
+ offsetResource.space += cbufferResource->space;
+ }
}
emitHLSLRegisterSemantic(offsetResource, "packoffset");
}
}
+ void emitHLSLParameterBlockDecl(
+ RefPtr<VarDeclBase> varDecl,
+ RefPtr<ParameterBlockType> parameterBlockType,
+ RefPtr<VarLayout> layout)
+ {
+ Emit("cbuffer ");
+
+ emitName(varDecl);
+
+ // We expect to always have layout information
+ layout = maybeFetchLayout(varDecl, layout);
+ SLANG_RELEASE_ASSERT(layout);
+
+ // We expect the layout to be for a parameter group type...
+ RefPtr<ParameterGroupTypeLayout> bufferLayout = layout->typeLayout.As<ParameterGroupTypeLayout>();
+ SLANG_RELEASE_ASSERT(bufferLayout);
+
+ EmitSemantics(varDecl, kESemanticMask_None);
+
+ auto info = layout->FindResourceInfo(LayoutResourceKind::ConstantBuffer);
+ SLANG_RELEASE_ASSERT(info);
+ emitHLSLRegisterSemantic(*info);
+
+ Emit("\n{\n");
+
+ // The user wrote this declaration as, e.g.:
+ //
+ // ParameterBlock<Foo> gFoo;
+ //
+ // and we are desugaring it into something like:
+ //
+ // cbuffer anon0 { Foo gFoo; }
+ //
+
+ RefPtr<Type> elementType = parameterBlockType->elementType;
+ RefPtr<TypeLayout> elementTypeLayout = bufferLayout->elementTypeLayout;
+
+ EmitType(elementType, varDecl->getName());
+
+ // The layout for the field ends up coming from the layout
+ // for the parameter block as a whole.
+ emitHLSLParameterGroupFieldLayoutSemantics(nullptr, layout);
+
+ Emit(";\n");
+ Emit("}\n");
+ }
+
void emitHLSLParameterGroupDecl(
RefPtr<VarDeclBase> varDecl,
RefPtr<ParameterGroupType> parameterGroupType,
RefPtr<VarLayout> layout)
{
+ if( auto parameterBlockType = parameterGroupType->As<ParameterBlockType>())
+ {
+ emitHLSLParameterBlockDecl(varDecl, parameterBlockType, layout);
+ return;
+ }
+ if( auto textureBufferType = parameterGroupType->As<TextureBufferType>() )
+ {
+ Emit("tbuffer ");
+ }
+ else
+ {
+ Emit("cbuffer ");
+ }
+
// The data type that describes where stuff in the constant buffer should go
RefPtr<Type> dataType = parameterGroupType->elementType;
@@ -3610,20 +3693,16 @@ struct EmitVisitor
RefPtr<StructTypeLayout> structTypeLayout = bufferLayout->elementTypeLayout.As<StructTypeLayout>();
SLANG_RELEASE_ASSERT(structTypeLayout);
- if( auto constantBufferType = parameterGroupType->As<ConstantBufferType>() )
- {
- Emit("cbuffer ");
- }
- else if( auto textureBufferType = parameterGroupType->As<TextureBufferType>() )
- {
- Emit("tbuffer ");
- }
+ Emit(" ");
if( auto reflectionNameModifier = varDecl->FindModifier<ParameterGroupReflectionName>() )
{
- Emit(" ");
emitName(reflectionNameModifier->nameAndLoc);
}
+ else
+ {
+ emitName(varDecl->nameAndLoc);
+ }
EmitSemantics(varDecl, kESemanticMask_None);
@@ -4144,6 +4223,28 @@ emitDeclImpl(decl, nullptr);
}
}
+ // Utility code for generating unique IDs as needed
+ // during the emit process (e.g., for declarations
+ // that didn't origianlly have names, but now need to).
+
+ UInt allocateUniqueID()
+ {
+ return context->shared->uniqueIDCounter++;
+ }
+
+ UInt getID(Decl* decl)
+ {
+ auto& mapDeclToID = context->shared->mapDeclToID;
+
+ UInt id = 0;
+ if(mapDeclToID.TryGetValue(decl, id))
+ return id;
+
+ id = allocateUniqueID();
+ mapDeclToID.Add(decl, id);
+ return id;
+ }
+
// IR-level emit logc
UInt getID(IRValue* value)
@@ -4154,7 +4255,7 @@ emitDeclImpl(decl, nullptr);
if (mapIRValueToID.TryGetValue(value, id))
return id;
- id = mapIRValueToID.Count() + 1;
+ id = allocateUniqueID();
mapIRValueToID.Add(value, id);
return id;
}
@@ -6274,11 +6375,53 @@ emitDeclImpl(decl, nullptr);
}
}
+ void emitHLSLParameterBlock(
+ EmitContext* ctx,
+ IRGlobalVar* varDecl,
+ ParameterBlockType* type)
+ {
+ emit("cbuffer ");
+
+ // Generate a dummy name for the block
+ emit("_S");
+ Emit(ctx->shared->uniqueIDCounter++);
+
+ auto layout = getVarLayout(ctx, varDecl);
+ assert(layout);
+
+ auto info = layout->FindResourceInfo(LayoutResourceKind::ConstantBuffer);
+ SLANG_RELEASE_ASSERT(info);
+ emitHLSLRegisterSemantic(*info);
+
+ emit("\n{\n");
+
+ auto elementType = type->getElementType();
+
+ auto typeLayout = layout->typeLayout;
+ if( auto parameterGroupTypeLayout = typeLayout.As<ParameterGroupTypeLayout>() )
+ {
+ typeLayout = parameterGroupTypeLayout->elementTypeLayout;
+ }
+
+ emitIRType(ctx, elementType, getIRName(varDecl));
+
+ emitHLSLParameterGroupFieldLayoutSemantics(nullptr, layout);
+ emit(";\n");
+
+ emit("}\n");
+ }
+
void emitHLSLParameterGroup(
EmitContext* ctx,
IRGlobalVar* varDecl,
UniformParameterGroupType* type)
{
+ if(auto parameterBlockType = type->As<ParameterBlockType>())
+ {
+ emitHLSLParameterBlock(ctx, varDecl, parameterBlockType);
+ return;
+ }
+
emit("cbuffer ");
emit(getIRName(varDecl));