summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-11-13 14:17:09 -0800
committerGitHub <noreply@github.com>2017-11-13 14:17:09 -0800
commitc9d94248dc73fe41c344b0a23230e597f7b94a2c (patch)
tree07330bef7fc8685f5615212de33250bb32adc918 /source
parentc9368fe3ec8f8d8bc58947ddb1b5fd2caa4bd70a (diff)
Parameter block work (#276)
* Don't auto-enable IR use for compute tests The `COMPARE_COMPUTE` and `COMPARE_RENDER_COMPUTE` test fixtures were set up to always enable the `-use-ir` flag on Slang, which precludes having any tests that confirm functionality on the old non-IR path (which is still required by our main customer). This change adds the `-xslang -use-ir` flags explicitly to any compute test cases that left them out, and makes the fixture no longer add it by default. * Continue building out parameter block support The initial front-end logic for parameter blocks was already added, but they are still missing a bunch of functionality. This change addresses some of the known issues: - Bug fix: don't try to emit HLSL `register` bindings for variables that consume whole register spaces/sets - Overhaul type layout logic so that it can make decisions based on a given code generation target (currently passed in as a `TargetRequest`), which allows us to decide whether or not a parameter block should get its own register set on a per-target basis. - Always use a register space/set for Vulkan - Never use a register space/set for HLSL SM 5.0 and lower - By default, don't use register spaces/sets for HLSL output - Add a command-line flag and some "target flags" to enable register-space usage for D3D targets - Hackily add initial support for parameter blocks in the AST-to-AST path - This just blindly lowers `ParameterBlock<T>` to `T`, which shouldn't quite work - A more complete overhaul will probably need to wait until the AST-to-AST legalization is changed to use the `LegalType`s from the IR legalization pass. - Add a compute-based test case to actually run code using parameter blocks - This file runs test cases both with and without the IR
Diffstat (limited to 'source')
-rw-r--r--source/slang/compiler.h6
-rw-r--r--source/slang/emit.cpp121
-rw-r--r--source/slang/ir-legalize-types.cpp16
-rw-r--r--source/slang/lower.cpp14
-rw-r--r--source/slang/options.cpp12
-rw-r--r--source/slang/parameter-binding.cpp103
-rw-r--r--source/slang/slang.cpp22
-rw-r--r--source/slang/type-layout.cpp433
-rw-r--r--source/slang/type-layout.h83
9 files changed, 556 insertions, 254 deletions
diff --git a/source/slang/compiler.h b/source/slang/compiler.h
index 7a045d23c..f42f36c1f 100644
--- a/source/slang/compiler.h
+++ b/source/slang/compiler.h
@@ -176,8 +176,10 @@ namespace Slang
class TargetRequest : public RefObject
{
public:
- CompileRequest* compileRequest;
- CodeGenTarget target;
+ CompileRequest* compileRequest;
+ CodeGenTarget target;
+ SlangTargetFlags targetFlags = 0;
+ Slang::Profile targetProfile = Slang::Profile::Unknown;
// The resulting reflection layout information
RefPtr<ProgramLayout> layout;
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 039aea27d..a8cd11af4 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -3425,75 +3425,84 @@ struct EmitVisitor
// Keyword to use in the uniform case (`register` for globals, `packoffset` inside a `cbuffer`)
char const* uniformSemanticSpelling = "register")
{
- if( info.kind == LayoutResourceKind::Uniform )
+ switch(info.kind)
{
- size_t offset = info.index;
+ case LayoutResourceKind::Uniform:
+ {
+ size_t offset = info.index;
- // The HLSL `c` register space is logically grouped in 16-byte registers,
- // while we try to traffic in byte offsets. That means we need to pick
- // a register number, based on the starting offset in 16-byte register
- // units, and then a "component" within that register, based on 4-byte
- // offsets from there. We cannot support more fine-grained offsets than that.
+ // The HLSL `c` register space is logically grouped in 16-byte registers,
+ // while we try to traffic in byte offsets. That means we need to pick
+ // a register number, based on the starting offset in 16-byte register
+ // units, and then a "component" within that register, based on 4-byte
+ // offsets from there. We cannot support more fine-grained offsets than that.
- Emit(": ");
- Emit(uniformSemanticSpelling);
- Emit("(c");
+ Emit(": ");
+ Emit(uniformSemanticSpelling);
+ Emit("(c");
- // Size of a logical `c` register in bytes
- auto registerSize = 16;
+ // Size of a logical `c` register in bytes
+ auto registerSize = 16;
- // Size of each component of a logical `c` register, in bytes
- auto componentSize = 4;
+ // Size of each component of a logical `c` register, in bytes
+ auto componentSize = 4;
- size_t startRegister = offset / registerSize;
- Emit(int(startRegister));
+ size_t startRegister = offset / registerSize;
+ Emit(int(startRegister));
- size_t byteOffsetInRegister = offset % registerSize;
+ size_t byteOffsetInRegister = offset % registerSize;
- // If this field doesn't start on an even register boundary,
- // then we need to emit additional information to pick the
- // right component to start from
- if (byteOffsetInRegister != 0)
- {
- // The value had better occupy a whole number of components.
- SLANG_RELEASE_ASSERT(byteOffsetInRegister % componentSize == 0);
+ // If this field doesn't start on an even register boundary,
+ // then we need to emit additional information to pick the
+ // right component to start from
+ if (byteOffsetInRegister != 0)
+ {
+ // The value had better occupy a whole number of components.
+ SLANG_RELEASE_ASSERT(byteOffsetInRegister % componentSize == 0);
- size_t startComponent = byteOffsetInRegister / componentSize;
+ size_t startComponent = byteOffsetInRegister / componentSize;
- static const char* kComponentNames[] = {"x", "y", "z", "w"};
- Emit(".");
- Emit(kComponentNames[startComponent]);
- }
- Emit(")");
- }
- else
- {
- Emit(": register(");
- switch( info.kind )
- {
- case LayoutResourceKind::ConstantBuffer:
- Emit("b");
- break;
- case LayoutResourceKind::ShaderResource:
- Emit("t");
- break;
- case LayoutResourceKind::UnorderedAccess:
- Emit("u");
- break;
- case LayoutResourceKind::SamplerState:
- Emit("s");
- break;
- default:
- SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled HLSL register type");
- break;
+ static const char* kComponentNames[] = {"x", "y", "z", "w"};
+ Emit(".");
+ Emit(kComponentNames[startComponent]);
+ }
+ Emit(")");
}
- Emit(info.index);
- if(info.space)
+ break;
+
+ case LayoutResourceKind::RegisterSpace:
+ // ignore
+ break;
+
+ default:
{
- Emit(", space");
- Emit(info.space);
+ Emit(": register(");
+ switch( info.kind )
+ {
+ case LayoutResourceKind::ConstantBuffer:
+ Emit("b");
+ break;
+ case LayoutResourceKind::ShaderResource:
+ Emit("t");
+ break;
+ case LayoutResourceKind::UnorderedAccess:
+ Emit("u");
+ break;
+ case LayoutResourceKind::SamplerState:
+ Emit("s");
+ break;
+ default:
+ SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled HLSL register type");
+ break;
+ }
+ Emit(info.index);
+ if(info.space)
+ {
+ Emit(", space");
+ Emit(info.space);
+ }
+ Emit(")");
}
- Emit(")");
}
}
diff --git a/source/slang/ir-legalize-types.cpp b/source/slang/ir-legalize-types.cpp
index 5b42407c2..5b08acee8 100644
--- a/source/slang/ir-legalize-types.cpp
+++ b/source/slang/ir-legalize-types.cpp
@@ -660,13 +660,13 @@ static LegalVal declareSimpleVar(
// those to all the nested resource infos.
for (auto vv = varChain; vv; vv = vv->next)
{
- auto parentSpaceInfo = vv->varLayout->findOrAddResourceInfo(LayoutResourceKind::ParameterBlock);
+ auto parentSpaceInfo = vv->varLayout->findOrAddResourceInfo(LayoutResourceKind::RegisterSpace);
if (!parentSpaceInfo)
continue;
for (auto& rr : varLayout->resourceInfos)
{
- if (rr.kind == LayoutResourceKind::ParameterBlock)
+ if (rr.kind == LayoutResourceKind::RegisterSpace)
{
rr.index += parentSpaceInfo->index;
}
@@ -827,21 +827,13 @@ static void legalizeGlobalVar(
RefPtr<VarLayout> varLayout = findVarLayout(irGlobalVar);
RefPtr<TypeLayout> typeLayout = varLayout ? varLayout->typeLayout : nullptr;
- // If we've decided to do implicit deref on the type,
- // then go ahead and declare a value of the pointed-to type.
- LegalType maybeSimpleType = legalValueType;
- while (maybeSimpleType.flavor == LegalType::Flavor::implicitDeref)
- {
- maybeSimpleType = maybeSimpleType.getImplicitDeref()->valueType;
- }
-
- switch (maybeSimpleType.flavor)
+ switch (legalValueType.flavor)
{
case LegalType::Flavor::simple:
// Easy case: the type is usable as-is, and we
// should just do that.
irGlobalVar->type = context->session->getPtrType(
- maybeSimpleType.getSimple());
+ legalValueType.getSimple());
break;
default:
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index ccf302027..a15104d6a 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -797,6 +797,20 @@ struct LoweringVisitor
lowerType(type->valueType));
}
+ RefPtr<Type> visitParameterBlockType(ParameterBlockType* type)
+ {
+ // TODO: When doing AST-to-AST lowering, we want to lower
+ // a `ParameterBlock<T>` just like a `ConstantBuffer<T>`.
+ //
+ // HACK: for now we will try to simply lower the type
+ // directly to its stated element type, and see how
+ // that works.
+
+ return lowerType(type->getElementType());
+// return getSession()->getConstantBufferType(
+// lowerType(type->getElementType());
+ }
+
RefPtr<Type> transformSyntaxField(Type* type)
{
return lowerType(type);
diff --git a/source/slang/options.cpp b/source/slang/options.cpp
index 7eea3fecc..452e7c439 100644
--- a/source/slang/options.cpp
+++ b/source/slang/options.cpp
@@ -80,6 +80,7 @@ struct OptionsParser
int profileOptionCount = 0;
SlangCompileFlags flags = 0;
+ SlangTargetFlags targetFlags = 0;
struct RawOutputPath
{
@@ -279,6 +280,10 @@ struct OptionsParser
{
requestImpl->shouldSkipCodegen = true;
}
+ else if(argStr == "-parameter-blocks-use-register-spaces" )
+ {
+ targetFlags |= SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES;
+ }
else if (argStr == "-backend" || argStr == "-target")
{
String name = tryReadCommandLineArgument(arg, &argCursor, argEnd);
@@ -729,6 +734,13 @@ struct OptionsParser
}
}
+ // If the user specifed and per-compilation-target flags, make sure
+ // to apply them here.
+ if(targetFlags)
+ {
+ spSetTargetFlags(compileRequest, 0, targetFlags);
+ }
+
// Next, we want to make sure that entry points get attached to the appropriate translation
// unit that will provide them.
{
diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp
index 05b9d924e..fa015186b 100644
--- a/source/slang/parameter-binding.cpp
+++ b/source/slang/parameter-binding.cpp
@@ -188,6 +188,13 @@ struct SharedParameterBindingContext
// The base compile request
CompileRequest* compileRequest;
+ // The target request that is triggering layout
+ //
+ // TODO: We should eventually strip this down to
+ // just the subset of fields on the target that
+ // can influence layout decisions.
+ TargetRequest* targetRequest;
+
LayoutRulesFamilyImpl* defaultLayoutRules;
// All shader parameters we've discovered so far, and started to lay out...
@@ -208,6 +215,8 @@ struct SharedParameterBindingContext
// Which register spaces have been claimed so far?
UsedRanges usedSpaces;
+
+ TargetRequest* getTargetRequest() { return targetRequest; }
};
static DiagnosticSink* getSink(SharedParameterBindingContext* shared)
@@ -225,8 +234,9 @@ struct ParameterBindingContext
// All the shared state needs to be available
SharedParameterBindingContext* shared;
- // The layout rules to use while computing usage...
- LayoutRulesFamilyImpl* layoutRules;
+ // The type layout context to use when computing
+ // the resource usage of shader parameters.
+ TypeLayoutContext layoutContext;
// A dictionary to accellerate looking up parameters by name
Dictionary<Name*, ParameterInfo*> mapNameToParameterInfo;
@@ -236,6 +246,9 @@ struct ParameterBindingContext
// The source language we are trying to use
SourceLanguage sourceLanguage;
+
+ TargetRequest* getTargetRequest() { return shared->getTargetRequest(); }
+ LayoutRulesFamilyImpl* getRulesFamily() { return layoutContext.getRulesFamily(); }
};
static DiagnosticSink* getSink(ParameterBindingContext* context)
@@ -475,7 +488,8 @@ getTypeLayoutForGlobalShaderParameter_GLSL(
ParameterBindingContext* context,
VarDeclBase* varDecl)
{
- auto rules = context->layoutRules;
+ auto layoutContext = context->layoutContext;
+ auto rules = layoutContext.getRulesFamily();
auto type = varDecl->getType();
// A GLSL shader parameter will be marked with
@@ -489,36 +503,56 @@ getTypeLayoutForGlobalShaderParameter_GLSL(
// We want to check for a constant-buffer type with a `push_constant` layout
// qualifier before we move on to anything else.
- if (varDecl->HasModifier<GLSLPushConstantLayoutModifier>() && type->As<ConstantBufferType>())
- return CreateTypeLayout(type, rules->getPushConstantBufferRules());
+ if( varDecl->HasModifier<GLSLPushConstantLayoutModifier>() && type->As<ConstantBufferType>() )
+ {
+ return CreateTypeLayout(
+ layoutContext.with(rules->getPushConstantBufferRules()),
+ type);
+ }
// TODO(tfoley): We have multiple variations of
// the `uniform` modifier right now, and that
// needs to get fixed...
- if(varDecl->HasModifier<HLSLUniformModifier>() || type->As<ConstantBufferType>())
- return CreateTypeLayout(type, rules->getConstantBufferRules());
+ if( varDecl->HasModifier<HLSLUniformModifier>() || type->As<ConstantBufferType>() )
+ {
+ return CreateTypeLayout(
+ layoutContext.with(rules->getConstantBufferRules()),
+ type);
+ }
- if(varDecl->HasModifier<GLSLBufferModifier>() || type->As<GLSLShaderStorageBufferType>())
- return CreateTypeLayout(type, rules->getShaderStorageBufferRules());
+ if( varDecl->HasModifier<GLSLBufferModifier>() || type->As<GLSLShaderStorageBufferType>() )
+ {
+ return CreateTypeLayout(
+ layoutContext.with(rules->getShaderStorageBufferRules()),
+ type);
+ }
if (auto effectiveVaryingInputType = tryGetEffectiveTypeForGLSLVaryingInput(context, varDecl))
{
// We expect to handle these elsewhere
SLANG_DIAGNOSE_UNEXPECTED(getSink(context), varDecl, "GLSL varying input");
- return CreateTypeLayout(effectiveVaryingInputType, rules->getVaryingInputRules());
+ return CreateTypeLayout(
+ layoutContext.with(rules->getVaryingInputRules()),
+ effectiveVaryingInputType);
}
if (auto effectiveVaryingOutputType = tryGetEffectiveTypeForGLSLVaryingOutput(context, varDecl))
{
// We expect to handle these elsewhere
SLANG_DIAGNOSE_UNEXPECTED(getSink(context), varDecl, "GLSL varying output");
- return CreateTypeLayout(effectiveVaryingOutputType, rules->getVaryingOutputRules());
+ return CreateTypeLayout(
+ layoutContext.with(rules->getVaryingOutputRules()),
+ effectiveVaryingOutputType);
}
// A `const` global with a `layout(constant_id = ...)` modifier
// is a declaration of a specialization constant.
- if(varDecl->HasModifier<GLSLConstantIDLayoutModifier>())
- return CreateTypeLayout(type, rules->getSpecializationConstantRules());
+ if( varDecl->HasModifier<GLSLConstantIDLayoutModifier>() )
+ {
+ return CreateTypeLayout(
+ layoutContext.with(rules->getSpecializationConstantRules()),
+ type);
+ }
// GLSL says that an "ordinary" global variable
// is just a (thread local) global and not a
@@ -531,7 +565,8 @@ getTypeLayoutForGlobalShaderParameter_HLSL(
ParameterBindingContext* context,
VarDeclBase* varDecl)
{
- auto rules = context->layoutRules;
+ auto layoutContext = context->layoutContext;
+ auto rules = layoutContext.getRulesFamily();
auto type = varDecl->getType();
// HLSL `static` modifier indicates "thread local"
@@ -546,7 +581,9 @@ getTypeLayoutForGlobalShaderParameter_HLSL(
// An "ordinary" global variable is implicitly a uniform
// shader parameter.
- return CreateTypeLayout(type, rules->getConstantBufferRules());
+ return CreateTypeLayout(
+ layoutContext.with(rules->getConstantBufferRules()),
+ type);
}
// Determine how to lay out a global variable that might be
@@ -983,7 +1020,7 @@ static void completeBindingsForParameter(
// a parameter wants to claim an entire register
// space to itself (for a parameter block), since
// that can't be handled like other resources.
- if (kind == LayoutResourceKind::ParameterBlock)
+ if (kind == LayoutResourceKind::RegisterSpace)
{
// We need to snag a register space of our own.
@@ -991,6 +1028,11 @@ static void completeBindingsForParameter(
bindingInfo.count = count;
bindingInfo.index = space;
+
+ // TODO: what should we store as the "space" for
+ // an allocation of register spaces? Either zero
+ // or `space` makes sense, but it isn't clear
+ // which is a better choice.
bindingInfo.space = 0;
continue;
@@ -1158,8 +1200,10 @@ static RefPtr<TypeLayout> processSimpleEntryPointParameter(
// We also need to track this as an ordinary varying output from the stage,
// since that is how GLSL will want to see it.
- auto rules = context->layoutRules->getVaryingOutputRules();
- SimpleLayoutInfo layout = GetLayout(type, rules);
+ auto rules = context->getRulesFamily()->getVaryingOutputRules();
+ SimpleLayoutInfo layout = GetLayout(
+ context->layoutContext.with(rules),
+ type);
typeLayout->addResourceUsage(layout.kind, layout.size);
}
}
@@ -1179,15 +1223,19 @@ static RefPtr<TypeLayout> processSimpleEntryPointParameter(
if (state.directionMask & kEntryPointParameterDirection_Input)
{
- auto rules = context->layoutRules->getVaryingInputRules();
- SimpleLayoutInfo layout = GetLayout(type, rules);
+ auto rules = context->getRulesFamily()->getVaryingInputRules();
+ SimpleLayoutInfo layout = GetLayout(
+ context->layoutContext.with(rules),
+ type);
typeLayout->addResourceUsage(layout.kind, layout.size);
}
if (state.directionMask & kEntryPointParameterDirection_Output)
{
- auto rules = context->layoutRules->getVaryingOutputRules();
- SimpleLayoutInfo layout = GetLayout(type, rules);
+ auto rules = context->getRulesFamily()->getVaryingOutputRules();
+ SimpleLayoutInfo layout = GetLayout(
+ context->layoutContext.with(rules),
+ type);
typeLayout->addResourceUsage(layout.kind, layout.size);
}
}
@@ -1610,11 +1658,11 @@ void generateParameterBindings(
CompileRequest* compileReq = targetReq->compileRequest;
// Try to find rules based on the selected code-generation target
- auto rules = GetLayoutRulesFamilyImpl(targetReq->target);
+ auto layoutContext = getInitialLayoutContextForTarget(targetReq);
// If there was no target, or there are no rules for the target,
// then bail out here.
- if (!rules)
+ if (!layoutContext.rules)
return;
RefPtr<ProgramLayout> programLayout = new ProgramLayout;
@@ -1623,7 +1671,7 @@ void generateParameterBindings(
// of generating parameter bindings
SharedParameterBindingContext sharedContext;
sharedContext.compileRequest = compileReq;
- sharedContext.defaultLayoutRules = rules;
+ sharedContext.defaultLayoutRules = layoutContext.getRulesFamily();
sharedContext.programLayout = programLayout;
// Create a sub-context to collect parameters that get
@@ -1631,7 +1679,7 @@ void generateParameterBindings(
ParameterBindingContext context;
context.shared = &sharedContext;
context.translationUnit = nullptr;
- context.layoutRules = sharedContext.defaultLayoutRules;
+ context.layoutContext = layoutContext;
// Walk through AST to discover all the parameters
collectParameters(&context, compileReq);
@@ -1698,7 +1746,7 @@ void generateParameterBindings(
// For legacy GLSL targets, we'd probably need a distinct resource
// kind and set of rules here, since legacy uniforms are not the
// same as the contents of a constant buffer.
- auto globalScopeRules = context.layoutRules->getConstantBufferRules();
+ auto globalScopeRules = context.getRulesFamily()->getConstantBufferRules();
RefPtr<StructTypeLayout> globalScopeStructLayout = new StructTypeLayout();
globalScopeStructLayout->rules = globalScopeRules;
@@ -1746,6 +1794,7 @@ void generateParameterBindings(
if( anyGlobalUniforms )
{
auto globalConstantBufferLayout = createParameterGroupTypeLayout(
+ layoutContext,
nullptr,
globalScopeRules,
globalScopeRules->GetObjectLayout(ShaderParameterKind::ConstantBuffer),
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index fe24fbd19..17f8ea96d 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -746,12 +746,30 @@ SLANG_API void spSetCodeGenTarget(
req->addTarget(Slang::CodeGenTarget(target));
}
-SLANG_API void spAddCodeGenTarget(
+SLANG_API int spAddCodeGenTarget(
SlangCompileRequest* request,
SlangCompileTarget target)
{
auto req = REQ(request);
- req->addTarget(Slang::CodeGenTarget(target));
+ return (int) req->addTarget(Slang::CodeGenTarget(target));
+}
+
+SLANG_API void spSetTargetProfile(
+ SlangCompileRequest* request,
+ int targetIndex,
+ SlangProfileID profile)
+{
+ auto req = REQ(request);
+ req->targets[targetIndex]->targetProfile = profile;
+}
+
+SLANG_API void spSetTargetFlags(
+ SlangCompileRequest* request,
+ int targetIndex,
+ SlangTargetFlags flags)
+{
+ auto req = REQ(request);
+ req->targets[targetIndex]->targetFlags = flags;
}
SLANG_API void spSetOutputContainerFormat(
diff --git a/source/slang/type-layout.cpp b/source/slang/type-layout.cpp
index 9f2aee922..8fa790dd8 100644
--- a/source/slang/type-layout.cpp
+++ b/source/slang/type-layout.cpp
@@ -616,20 +616,9 @@ LayoutRulesImpl* GetLayoutRulesImpl(LayoutRule rule)
}
}
-LayoutRulesFamilyImpl* GetLayoutRulesFamilyImpl(LayoutRulesFamily rule)
+LayoutRulesFamilyImpl* getDefaultLayoutRulesFamilyForTarget(TargetRequest* targetReq)
{
- switch (rule)
- {
- case LayoutRulesFamily::HLSL: return &kHLSLLayoutRulesFamilyImpl;
- case LayoutRulesFamily::GLSL: return &kGLSLLayoutRulesFamilyImpl;
- default:
- return nullptr;
- }
-}
-
-LayoutRulesFamilyImpl* GetLayoutRulesFamilyImpl(CodeGenTarget target)
-{
- switch (target)
+ switch (targetReq->target)
{
case CodeGenTarget::HLSL:
case CodeGenTarget::DXBytecode:
@@ -648,6 +637,24 @@ LayoutRulesFamilyImpl* GetLayoutRulesFamilyImpl(CodeGenTarget target)
}
}
+TypeLayoutContext getInitialLayoutContextForTarget(TargetRequest* targetReq)
+{
+ LayoutRulesFamilyImpl* rulesFamily = getDefaultLayoutRulesFamilyForTarget(targetReq);
+
+ TypeLayoutContext context;
+ context.targetReq = targetReq;
+ context.rules = nullptr;
+ context.matrixLayoutMode = MatrixLayoutMode::kMatrixLayoutMode_RowMajor;
+
+ if( rulesFamily )
+ {
+ context.rules = rulesFamily->getConstantBufferRules();
+ context.matrixLayoutMode = rulesFamily->getDefaultMatrixLayoutMode();
+ }
+
+ return context;
+}
+
static int GetElementCount(RefPtr<IntVal> val)
{
@@ -718,10 +725,17 @@ static SimpleLayoutInfo getParameterGroupLayoutInfo(
}
else if (type->As<ParameterBlockType>())
{
- // TODO(tfoley): Should a parameter block *always* consume at least
- // one `set`/`space`, or should we hold back and just allocate this
- // if it actually contains anything?
- return SimpleLayoutInfo(LayoutResourceKind::ParameterBlock, 1);
+ // Note: we default to consuming zero register spces here, because
+ // a parameter block might not contain anything (or all it contains
+ // is other blocks), and so it won't get a space allocated.
+ //
+ // This choice *also* means that in the case where we don't actually
+ // want to allocate register spaces to blocks at all, we haven't
+ // committed to that choice here.
+ //
+ // TODO: wouldn't it be any different to just allocate this
+ // as an empty `SimpleLayoutInfo` of any other kind?
+ return SimpleLayoutInfo(LayoutResourceKind::RegisterSpace, 0);
}
// TODO: the vertex-input and fragment-output cases should
@@ -742,31 +756,118 @@ static SimpleLayoutInfo getParameterGroupLayoutInfo(
}
}
-struct TypeLayoutContext
+RefPtr<TypeLayout> createTypeLayout(
+ TypeLayoutContext const& context,
+ Type* type,
+ SimpleLayoutInfo offset);
+
+static bool isOpenGLTarget(TargetRequest*)
{
- // The layout rules to use (e.g., we compute
- // layout differently in a `cbuffer` vs. the
- // parameter list of a fragment shader).
- LayoutRulesImpl* rules;
+ // We aren't officially supporting OpenGL right now
+ return false;
+}
- // Whether to lay out matrices column-major
- // or row-major.
- MatrixLayoutMode matrixLayoutMode;
-};
+static bool isD3DTarget(TargetRequest* targetReq)
+{
+ switch( targetReq->target )
+ {
+ case CodeGenTarget::HLSL:
+ case CodeGenTarget::DXBytecode:
+ case CodeGenTarget::DXBytecodeAssembly:
+ case CodeGenTarget::DXIL:
+ case CodeGenTarget::DXILAssembly:
+ return true;
-RefPtr<TypeLayout> createTypeLayout(
- TypeLayoutContext* context,
- Type* type,
- SimpleLayoutInfo offset);
+ default:
+ return false;
+ }
+}
+
+static bool isD3D11Target(TargetRequest*)
+{
+ // We aren't officially supporting D3D11 right now
+ return false;
+}
+
+static bool isD3D12Target(TargetRequest* targetReq)
+{
+ // We are currently only officially supporting D3D12
+ return isD3DTarget(targetReq);
+}
+
+
+static bool isSM5OrEarlier(TargetRequest* targetReq)
+{
+ if(!isD3DTarget(targetReq))
+ return false;
+
+ auto profile = targetReq->targetProfile;
+
+ if(profile.getFamily() == ProfileFamily::DX)
+ {
+ if(profile.GetVersion() <= ProfileVersion::DX_5_0)
+ return true;
+ }
+
+ return false;
+}
+
+static bool isVulkanTarget(TargetRequest* targetReq)
+{
+ switch( targetReq->target )
+ {
+ default:
+ return false;
+
+ case CodeGenTarget::GLSL:
+ case CodeGenTarget::SPIRV:
+ case CodeGenTarget::SPIRVAssembly:
+ break;
+ }
+
+ // For right now, any GLSL-related target is assumed
+ // to be a Vulkan target.
+
+ return true;
+}
+
+static bool shouldAllocateRegisterSpaceForParameterBlock(
+ TypeLayoutContext const& context)
+{
+ auto targetReq = context.targetReq;
+
+ // We *never* want to use register spaces/sets under
+ // OpenGL, D3D11, or for Shader Model 5.0 or earlier.
+ if(isOpenGLTarget(targetReq) || isD3D11Target(targetReq) || isSM5OrEarlier(targetReq))
+ return false;
+
+ // If we know that we are targetting Vulkan, then
+ // the only way to effectively use parameter blocks
+ // is by using descriptor sets.
+ if(isVulkanTarget(targetReq))
+ return true;
+
+ // If none of the above passed, then it seems like we
+ // are generating code for D3D12, and using SM5.1 or later.
+ // We will use a register space for parameter blocks *if*
+ // the target options tell us to:
+ if( isD3D12Target(targetReq) )
+ {
+ if(targetReq->targetFlags & SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES)
+ return true;
+ }
+
+ return false;
+}
RefPtr<ParameterGroupTypeLayout>
createParameterGroupTypeLayout(
- TypeLayoutContext* context,
+ TypeLayoutContext const& context,
RefPtr<ParameterGroupType> parameterGroupType,
SimpleLayoutInfo parameterGroupInfo,
RefPtr<TypeLayout> elementTypeLayout)
{
- auto parameterGroupRules = context->rules;
+ auto parameterGroupRules = context.rules;
auto typeLayout = new ParameterGroupTypeLayout();
@@ -780,9 +881,8 @@ createParameterGroupTypeLayout(
// originally (which should be a single binding "slot"
// and hence no uniform data).
//
- typeLayout->uniformAlignment = parameterGroupInfo.alignment;
- SLANG_RELEASE_ASSERT(!typeLayout->FindResourceInfo(LayoutResourceKind::Uniform));
- SLANG_RELEASE_ASSERT(typeLayout->uniformAlignment == 1);
+ SLANG_RELEASE_ASSERT(parameterGroupInfo.kind != LayoutResourceKind::Uniform);
+ typeLayout->uniformAlignment = 1;
// TODO(tfoley): There is a subtle question here of whether
// a constant buffer declaration that then contains zero
@@ -801,59 +901,125 @@ createParameterGroupTypeLayout(
parameterGroupInfo.size);
}
- // The layout rules for a constant buffer, vs. a "parameter block"
- // are different, with respect to how they expose layout information
- // for underlying resources.
- //
- // A parameter block should *not* expose the fine-grained resource
- // prameters it contains, and should only expose a total number
- // of `space`s or `set`s that it consumes.
- if (parameterGroupInfo.kind == LayoutResourceKind::ParameterBlock)
- {
- // Iterate over element types, but *only* accumulate usage
- // info for types that consume whole register sets/spaces.
- for( auto elementResourceInfo : elementTypeLayout->resourceInfos )
+ // There are several different cases that need to be handled here,
+ // depending on whether we have a `ParameterBlock`, a `ConstantBuffer`,
+ // or some other kind of parameter group. Furthermore, in the
+ // `ParameterBlock` case, we need to deal with differnet layout
+ // rules depending on whether a block should map to a register `space`
+ // in HLSL or not.
+
+ // Check if we are working with a parameter block...
+ auto parameterBlockType = parameterGroupType->As<ParameterBlockType>();
+
+ // Check if we have a parameter block *and* it should be
+ // allocated into its own register space(s)
+ bool ownRegisterSpace = false;
+ if (parameterBlockType)
+ {
+ if( shouldAllocateRegisterSpaceForParameterBlock(context) )
{
- if(elementResourceInfo.kind != LayoutResourceKind::ParameterBlock)
- break;
+ ownRegisterSpace = true;
+ }
- typeLayout->addResourceUsage(elementResourceInfo);
+ // If the parameter block contains any uniform data, then we
+ // had better allocate a constant buffer for it.
+ bool anyUniformData = false;
+ if(auto elementUniformInfo = elementTypeLayout->FindResourceInfo(LayoutResourceKind::Uniform) )
+ {
+ if( elementUniformInfo->count != 0 )
+ {
+ // We have a non-zero number of bytes of uniform data here.
+ anyUniformData = true;
+ }
}
- }
- else
- {
- // In the ordinary case (e.g., a constant buffer) then we need
- // to make sure that any resources nested in the element type
- // get counted against the container type, so that we can
- // allocate registers to it directly.
- for( auto elementResourceInfo : elementTypeLayout->resourceInfos )
+
+ if( anyUniformData )
+ {
+ typeLayout->addResourceUsage(LayoutResourceKind::ConstantBuffer, 1);
+ }
+
+ // Next, if we are going to allocate whole register space(s) to the
+ // parameter block, check if it actually needs one (it might be empty,
+ // or only contain other parameter blocks).
+ if( ownRegisterSpace )
{
- // Skip uniform data, since that is encapsualted behind the constant buffer
- if(elementResourceInfo.kind == LayoutResourceKind::Uniform)
- break;
+ bool needsARegisterSpace = false;
+ for( auto elementResourceInfo : elementTypeLayout->resourceInfos )
+ {
+ if(elementResourceInfo.kind != LayoutResourceKind::RegisterSpace)
+ {
+ needsARegisterSpace = true;
+ break;
+ }
+ }
- typeLayout->addResourceUsage(elementResourceInfo);
+ if( needsARegisterSpace )
+ {
+ typeLayout->addResourceUsage(LayoutResourceKind::RegisterSpace, 1);
+ }
}
}
+ // The layout for the element type was computed without any knowledge
+ // of what resources the parent type was going to consume; we now
+ // need to go through and offset that any starting locations (e.g.,
+ // in nested `StructTypeLayout`s) based on what we allocated to
+ // the parent.
+
+ // TODO(tfoley): actually implement that!
+ // Now we will (possibly) accumulate the resources used by the element
+ // type into the resources used by the parameter group. The reason
+ // this is "possibly" is because, e.g., a `ConstantBuffer<Foo>` should
+ // not report itself as consuming `sizeof(Foo)` bytes of uniform data,
+ // or else it would mess up layout for any type that contains the
+ // constant buffer. Similarly, a parameter block that consumes whole
+ // register `space`s shouldn't report its fine-grained resource
+ // usage inside those spces.
+ for( auto elementResourceInfo : elementTypeLayout->resourceInfos )
+ {
+ switch( elementResourceInfo.kind )
+ {
+ case LayoutResourceKind::RegisterSpace:
+ // Register spaces consumed by the element type should be
+ // reflected in the resource usage of the parent type.
+ typeLayout->addResourceUsage(elementResourceInfo);
+ break;
+
+ case LayoutResourceKind::Uniform:
+ // Uniform resource usages will always be hidden.
+ break;
+
+ default:
+ // All other register types should be hidden *if* we
+ // are allocating a whole register space, and exposed
+ // otherwise.
+ if( ownRegisterSpace )
+ {
+ // don't expose internal register/binding use outside
+ }
+ else
+ {
+ typeLayout->addResourceUsage(elementResourceInfo);
+ }
+ break;
+ }
+ }
+
return typeLayout;
}
RefPtr<ParameterGroupTypeLayout>
createParameterGroupTypeLayout(
+ TypeLayoutContext const& context,
RefPtr<ParameterGroupType> parameterGroupType,
LayoutRulesImpl* parameterGroupRules,
SimpleLayoutInfo parameterGroupInfo,
RefPtr<TypeLayout> elementTypeLayout)
{
- TypeLayoutContext context;
- context.rules = parameterGroupRules;
- context.matrixLayoutMode = parameterGroupRules->getDefaultMatrixLayoutMode();
-
return createParameterGroupTypeLayout(
- &context,
+ context.with(parameterGroupRules).with(parameterGroupRules->getDefaultMatrixLayoutMode()),
parameterGroupType,
parameterGroupInfo,
elementTypeLayout);
@@ -861,12 +1027,12 @@ createParameterGroupTypeLayout(
RefPtr<ParameterGroupTypeLayout>
createParameterGroupTypeLayout(
- TypeLayoutContext* context,
+ TypeLayoutContext const& context,
RefPtr<ParameterGroupType> parameterGroupType,
RefPtr<Type> elementType,
LayoutRulesImpl* elementTypeRules)
{
- auto parameterGroupRules = context->rules;
+ auto parameterGroupRules = context.rules;
// First compute resource usage of the block itself.
// For now we assume that the layout of the block can
@@ -891,10 +1057,8 @@ createParameterGroupTypeLayout(
// the elements of the block use the same resource kind consumed
// by the block itself.
- TypeLayoutContext elementContext = *context;
- elementContext.rules = elementTypeRules;
auto elementTypeLayout = createTypeLayout(
- &elementContext,
+ context.with(elementTypeRules),
elementType,
info);
@@ -942,10 +1106,10 @@ LayoutRulesImpl* getParameterBufferElementTypeLayoutRules(
RefPtr<ParameterGroupTypeLayout>
createParameterGroupTypeLayout(
- TypeLayoutContext* context,
+ TypeLayoutContext const& context,
RefPtr<ParameterGroupType> parameterGroupType)
{
- auto parameterGroupRules = context->rules;
+ auto parameterGroupRules = context.rules;
// Determine the layout rules to use for the contents of the block
auto elementTypeRules = getParameterBufferElementTypeLayoutRules(
@@ -964,11 +1128,12 @@ createParameterGroupTypeLayout(
// Create a type layout for a structured buffer type.
RefPtr<StructuredBufferTypeLayout>
createStructuredBufferTypeLayout(
- ShaderParameterKind kind,
- RefPtr<Type> structuredBufferType,
- RefPtr<TypeLayout> elementTypeLayout,
- LayoutRulesImpl* rules)
+ TypeLayoutContext const& context,
+ ShaderParameterKind kind,
+ RefPtr<Type> structuredBufferType,
+ RefPtr<TypeLayout> elementTypeLayout)
{
+ auto rules = context.rules;
auto info = rules->GetObjectLayout(kind);
auto typeLayout = new StructuredBufferTypeLayout();
@@ -997,50 +1162,50 @@ createStructuredBufferTypeLayout(
// Create a type layout for a structured buffer type.
RefPtr<StructuredBufferTypeLayout>
createStructuredBufferTypeLayout(
- ShaderParameterKind kind,
- RefPtr<Type> structuredBufferType,
- RefPtr<Type> elementType,
- LayoutRulesImpl* rules)
+ TypeLayoutContext const& context,
+ ShaderParameterKind kind,
+ RefPtr<Type> structuredBufferType,
+ RefPtr<Type> elementType)
{
- // TODO(tfoley): need to compute the layout for the constant
- // buffer's contents...
+ // TODO(tfoley): we should be looking up the appropriate rules
+ // via the `LayoutRulesFamily` in use here...
auto structuredBufferLayoutRules = GetLayoutRulesImpl(
LayoutRule::HLSLStructuredBuffer);
// Create and save type layout for the buffer contents.
auto elementTypeLayout = CreateTypeLayout(
- elementType.Ptr(),
- structuredBufferLayoutRules);
+ context.with(structuredBufferLayoutRules),
+ elementType.Ptr());
return createStructuredBufferTypeLayout(
+ context,
kind,
structuredBufferType,
- elementTypeLayout,
- rules);
+ elementTypeLayout);
}
SimpleLayoutInfo GetLayoutImpl(
- TypeLayoutContext* context,
- Type* type,
- RefPtr<TypeLayout>* outTypeLayout,
- SimpleLayoutInfo offset);
+ TypeLayoutContext const& context,
+ Type* type,
+ RefPtr<TypeLayout>* outTypeLayout,
+ SimpleLayoutInfo offset);
SimpleLayoutInfo GetLayoutImpl(
- TypeLayoutContext* context,
- Type* type,
- RefPtr<TypeLayout>* outTypeLayout)
+ TypeLayoutContext const& context,
+ Type* type,
+ RefPtr<TypeLayout>* outTypeLayout)
{
return GetLayoutImpl(context, type, outTypeLayout, SimpleLayoutInfo());
}
SimpleLayoutInfo GetLayoutImpl(
- TypeLayoutContext* context,
- Type* type,
- RefPtr<TypeLayout>* outTypeLayout,
- Decl* declForModifiers)
+ TypeLayoutContext const& context,
+ Type* type,
+ RefPtr<TypeLayout>* outTypeLayout,
+ Decl* declForModifiers)
{
- TypeLayoutContext subContext = *context;
+ TypeLayoutContext subContext = context;
if (declForModifiers)
{
@@ -1054,16 +1219,16 @@ SimpleLayoutInfo GetLayoutImpl(
// layout, such as GLSL `std140`.
}
- return GetLayoutImpl(&subContext, type, outTypeLayout, SimpleLayoutInfo());
+ return GetLayoutImpl(subContext, type, outTypeLayout, SimpleLayoutInfo());
}
SimpleLayoutInfo GetLayoutImpl(
- TypeLayoutContext* context,
- Type* type,
- RefPtr<TypeLayout>* outTypeLayout,
- SimpleLayoutInfo offset)
+ TypeLayoutContext const& context,
+ Type* type,
+ RefPtr<TypeLayout>* outTypeLayout,
+ SimpleLayoutInfo offset)
{
- auto rules = context->rules;
+ auto rules = context.rules;
if (auto parameterGroupType = type->As<ParameterGroupType>())
{
@@ -1176,10 +1341,10 @@ SimpleLayoutInfo GetLayoutImpl(
if (outTypeLayout) \
{ \
*outTypeLayout = createStructuredBufferTypeLayout( \
+ context, \
ShaderParameterKind::KIND, \
type_##TYPE, \
- type_##TYPE->elementType.Ptr(), \
- rules); \
+ type_##TYPE->elementType.Ptr()); \
} \
return info; \
} while(0)
@@ -1225,7 +1390,7 @@ SimpleLayoutInfo GetLayoutImpl(
{
return GetSimpleLayoutImpl(
rules->GetVectorLayout(
- GetLayout(vecType->elementType.Ptr(), rules),
+ GetLayout(context, vecType->elementType.Ptr()),
(size_t) GetIntVal(vecType->elementCount)),
type,
rules,
@@ -1245,7 +1410,7 @@ SimpleLayoutInfo GetLayoutImpl(
//
size_t rowCount = (size_t) GetIntVal(matType->getRowCount());
size_t colCount = (size_t) GetIntVal(matType->getColumnCount());
- if (context->matrixLayoutMode == kMatrixLayoutMode_ColumnMajor)
+ if (context.matrixLayoutMode == kMatrixLayoutMode_ColumnMajor)
{
size_t tmp = rowCount;
rowCount = colCount;
@@ -1253,7 +1418,7 @@ SimpleLayoutInfo GetLayoutImpl(
}
auto info = rules->GetMatrixLayout(
- GetLayout(matType->getElementType(), rules),
+ GetLayout(context, matType->getElementType()),
rowCount,
colCount);
@@ -1265,7 +1430,7 @@ SimpleLayoutInfo GetLayoutImpl(
typeLayout->type = type;
typeLayout->rules = rules;
typeLayout->uniformAlignment = info.alignment;
- typeLayout->mode = context->matrixLayoutMode;
+ typeLayout->mode = context.matrixLayoutMode;
typeLayout->addResourceUsage(info.kind, info.size);
}
@@ -1459,19 +1624,17 @@ SimpleLayoutInfo GetLayoutImpl(
outTypeLayout);
}
-SimpleLayoutInfo GetLayout(Type* inType, LayoutRulesImpl* rules)
+SimpleLayoutInfo GetLayout(
+ TypeLayoutContext const& context,
+ Type* inType)
{
- TypeLayoutContext context;
- context.rules = rules;
- context.matrixLayoutMode = rules->getDefaultMatrixLayoutMode();
-
- return GetLayoutImpl(&context, inType, nullptr);
+ return GetLayoutImpl(context, inType, nullptr);
}
RefPtr<TypeLayout> createTypeLayout(
- TypeLayoutContext* context,
- Type* type,
- SimpleLayoutInfo offset)
+ TypeLayoutContext const& context,
+ Type* type,
+ SimpleLayoutInfo offset)
{
RefPtr<TypeLayout> typeLayout;
GetLayoutImpl(context, type, &typeLayout, offset);
@@ -1479,8 +1642,8 @@ RefPtr<TypeLayout> createTypeLayout(
}
RefPtr<TypeLayout> createTypeLayout(
- TypeLayoutContext* context,
- Type* type)
+ TypeLayoutContext const& context,
+ Type* type)
{
RefPtr<TypeLayout> typeLayout;
GetLayoutImpl(context, type, &typeLayout, SimpleLayoutInfo());
@@ -1488,28 +1651,20 @@ RefPtr<TypeLayout> createTypeLayout(
}
RefPtr<TypeLayout> CreateTypeLayout(
- Type* type,
- LayoutRulesImpl* rules,
- SimpleLayoutInfo offset)
+ TypeLayoutContext const& context,
+ Type* type,
+ SimpleLayoutInfo offset)
{
- TypeLayoutContext context;
- context.rules = rules;
- context.matrixLayoutMode = rules->getDefaultMatrixLayoutMode();
-
RefPtr<TypeLayout> typeLayout;
- GetLayoutImpl(&context, type, &typeLayout, offset);
+ GetLayoutImpl(context, type, &typeLayout, offset);
return typeLayout;
}
-RefPtr<TypeLayout> CreateTypeLayout(Type* type, LayoutRulesImpl* rules)
-{
- return CreateTypeLayout(type, rules, SimpleLayoutInfo());
-}
-
-SimpleLayoutInfo GetLayout(Type* type, LayoutRule rule)
+RefPtr<TypeLayout> CreateTypeLayout(
+ TypeLayoutContext const& context,
+ Type* type)
{
- LayoutRulesImpl* rulesImpl = GetLayoutRulesImpl(rule);
- return GetLayout(type, rulesImpl);
+ return CreateTypeLayout(context, type, SimpleLayoutInfo());
}
} // namespace Slang
diff --git a/source/slang/type-layout.h b/source/slang/type-layout.h
index 257bfa310..363b01486 100644
--- a/source/slang/type-layout.h
+++ b/source/slang/type-layout.h
@@ -28,11 +28,13 @@ enum class LayoutRule
HLSLStructuredBuffer,
};
+#if 0
enum class LayoutRulesFamily
{
HLSL,
GLSL,
};
+#endif
// Layout appropriate to "just memory" scenarios,
// such as laying out the members of a constant buffer.
@@ -559,43 +561,92 @@ struct LayoutRulesFamilyImpl
virtual MatrixLayoutMode getDefaultMatrixLayoutMode() = 0;
};
-LayoutRulesImpl* GetLayoutRulesImpl(LayoutRule rule);
-LayoutRulesFamilyImpl* GetLayoutRulesFamilyImpl(LayoutRulesFamily rule);
-LayoutRulesFamilyImpl* GetLayoutRulesFamilyImpl(CodeGenTarget target);
+struct TypeLayoutContext
+{
+ // The layout rules to use (e.g., we compute
+ // layout differently in a `cbuffer` vs. the
+ // parameter list of a fragment shader).
+ LayoutRulesImpl* rules;
-SimpleLayoutInfo GetLayout(Type* type, LayoutRulesImpl* rules);
+ // The target request that is triggering layout
+ TargetRequest* targetReq;
-SimpleLayoutInfo GetLayout(Type* type, LayoutRule rule = LayoutRule::Std430);
+ // Whether to lay out matrices column-major
+ // or row-major.
+ MatrixLayoutMode matrixLayoutMode;
-RefPtr<TypeLayout> CreateTypeLayout(Type* type, LayoutRulesImpl* rules);
-RefPtr<TypeLayout> CreateTypeLayout(Type* type, LayoutRulesImpl* rules, SimpleLayoutInfo offset);
+ LayoutRulesImpl* getRules() { return rules; }
+ LayoutRulesFamilyImpl* getRulesFamily() { return rules->getLayoutRulesFamily(); }
-//
+ TypeLayoutContext with(LayoutRulesImpl* inRules) const
+ {
+ TypeLayoutContext result = *this;
+ result.rules = inRules;
+ return result;
+ }
-struct TypeLayoutContext;
+ TypeLayoutContext with(MatrixLayoutMode inMatrixLayoutMode) const
+ {
+ TypeLayoutContext result = *this;
+ result.matrixLayoutMode = inMatrixLayoutMode;
+ return result;
+ }
+};
+
+
+// Get an appropriate set of layout rules (packaged up
+// as a `TypeLayoutContext`) to perform type layout
+// for the given target.
+TypeLayoutContext getInitialLayoutContextForTarget(
+ TargetRequest* targetReq);
+
+// Get the "simple" layout for a type accordinging to a given set of layout
+// rules. Note that a "simple" layout can only consume one `LayoutResourceKind`,
+// and so this operation may not correctly capture the full resource usage
+// of a type.
+SimpleLayoutInfo GetLayout(
+ TypeLayoutContext const& context,
+ Type* type);
+
+// Create a full type-layout object for a type,
+// according to the layout rules in `context`.
+RefPtr<TypeLayout> CreateTypeLayout(
+ TypeLayoutContext const& context,
+ Type* type);
+
+// Create a full type layout for a type, while applying the given "simple"
+// layout information as an offset to any `VarLayout`s created along
+// the way.
+RefPtr<TypeLayout> CreateTypeLayout(
+ TypeLayoutContext const& context,
+ Type* type,
+ SimpleLayoutInfo offset);
+
+//
// Create a type layout for a parameter block type.
RefPtr<ParameterGroupTypeLayout>
createParameterGroupTypeLayout(
- TypeLayoutContext* context,
+ TypeLayoutContext const& context,
RefPtr<ParameterGroupType> parameterGroupType);
RefPtr<ParameterGroupTypeLayout>
createParameterGroupTypeLayout(
- TypeLayoutContext* context,
+ TypeLayoutContext const& context,
RefPtr<ParameterGroupType> parameterGroupType,
RefPtr<Type> elementType,
LayoutRulesImpl* elementTypeRules);
RefPtr<ParameterGroupTypeLayout>
createParameterGroupTypeLayout(
- TypeLayoutContext* context,
+ TypeLayoutContext const& context,
RefPtr<ParameterGroupType> parameterGroupType,
SimpleLayoutInfo parameterGroupInfo,
RefPtr<TypeLayout> elementTypeLayout);
RefPtr<ParameterGroupTypeLayout>
createParameterGroupTypeLayout(
+ TypeLayoutContext const& context,
RefPtr<ParameterGroupType> parameterGroupType,
LayoutRulesImpl* parameterGroupRules,
SimpleLayoutInfo parameterGroupInfo,
@@ -604,10 +655,10 @@ createParameterGroupTypeLayout(
// Create a type layout for a structured buffer type.
RefPtr<StructuredBufferTypeLayout>
createStructuredBufferTypeLayout(
- ShaderParameterKind kind,
- RefPtr<Type> structuredBufferType,
- RefPtr<Type> elementType,
- LayoutRulesImpl* rules);
+ TypeLayoutContext const& context,
+ ShaderParameterKind kind,
+ RefPtr<Type> structuredBufferType,
+ RefPtr<Type> elementType);
//