diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-05-31 17:20:37 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-05-31 17:20:37 -0400 |
| commit | 6cbc3929a54d37bd23cb5efa8e3320ba02f78b2f (patch) | |
| tree | 5a23cb47782e9e2a77762c90dd35da1005eba8d0 /source/slang/type-layout.h | |
| parent | b81ff3ef968d1cc4e954b31a1812b3c391d17b02 (diff) | |
Use slang- prefix on slang compiler and core source (#973)
* Prefixing source files in source/slang with slang-
* Prefix source in source/slang with slang- prefix.
* Rename core source files with slang- prefix.
* Update project files.
* Fix problems from automatic merge.
Diffstat (limited to 'source/slang/type-layout.h')
| -rw-r--r-- | source/slang/type-layout.h | 1118 |
1 files changed, 0 insertions, 1118 deletions
diff --git a/source/slang/type-layout.h b/source/slang/type-layout.h deleted file mode 100644 index c58f92cfb..000000000 --- a/source/slang/type-layout.h +++ /dev/null @@ -1,1118 +0,0 @@ -#ifndef SLANG_TYPE_LAYOUT_H -#define SLANG_TYPE_LAYOUT_H - -#include "../core/basic.h" -#include "compiler.h" -#include "profile.h" -#include "syntax.h" - -#include "../../slang.h" - -namespace Slang { - -// Forward declarations - -enum class BaseType; -class Type; - -// - -enum class LayoutRule -{ - Std140, - Std430, - HLSLConstantBuffer, - HLSLStructuredBuffer, -}; - -#if 0 -enum class LayoutRulesFamily -{ - HLSL, - GLSL, -}; -#endif - -// A "size" that can either be a simple finite size or -// the special case of an infinite/unbounded size. -// -struct LayoutSize -{ - typedef size_t RawValue; - - LayoutSize() - : raw(0) - {} - - LayoutSize(RawValue size) - : raw(size) - { - SLANG_ASSERT(size != RawValue(-1)); - } - - static LayoutSize infinite() - { - LayoutSize result; - result.raw = RawValue(-1); - return result; - } - - bool isInfinite() const { return raw == RawValue(-1); } - - bool isFinite() const { return raw != RawValue(-1); } - RawValue getFiniteValue() const { SLANG_ASSERT(isFinite()); return raw; } - - bool operator==(LayoutSize that) const - { - return raw == that.raw; - } - - bool operator!=(LayoutSize that) const - { - return raw != that.raw; - } - - void operator+=(LayoutSize right) - { - if( isInfinite() ) {} - else if( right.isInfinite() ) - { - *this = LayoutSize::infinite(); - } - else - { - *this = LayoutSize(raw + right.raw); - } - } - - void operator*=(LayoutSize right) - { - // Deal with zero first, so that anything (even the "infinite" value) times zero is zero. - if( raw == 0 ) - { - return; - } - - if( right.raw == 0 ) - { - raw = 0; - return; - } - - // Next we deal with infinite cases, so that infinite times anything non-zero is infinite - if( isInfinite() ) - { - return; - } - - if( right.isInfinite() ) - { - *this = LayoutSize::infinite(); - return; - } - - // Finally deal with the case where both sides are finite - *this = LayoutSize(raw * right.raw); - } - - void operator-=(RawValue right) - { - if( isInfinite() ) {} - else - { - *this = LayoutSize(raw - right); - } - } - - void operator/=(RawValue right) - { - if( isInfinite() ) {} - else - { - *this = LayoutSize(raw / right); - } - } - RawValue raw; -}; - -inline LayoutSize operator+(LayoutSize left, LayoutSize right) -{ - LayoutSize result(left); - result += right; - return result; -} - -inline LayoutSize operator*(LayoutSize left, LayoutSize right) -{ - LayoutSize result(left); - result *= right; - return result; -} - -inline LayoutSize operator-(LayoutSize left, LayoutSize::RawValue right) -{ - LayoutSize result(left); - result -= right; - return result; -} - -inline LayoutSize operator/(LayoutSize left, LayoutSize::RawValue right) -{ - LayoutSize result(left); - result /= right; - return result; -} - -inline LayoutSize maximum(LayoutSize left, LayoutSize right) -{ - if(left.isInfinite() || right.isInfinite()) - return LayoutSize::infinite(); - - return LayoutSize(Math::Max( - left.getFiniteValue(), - right.getFiniteValue())); -} - -inline bool operator>(LayoutSize left, LayoutSize::RawValue right) -{ - return left.isInfinite() || (left.getFiniteValue() > right); -} - -inline bool operator<=(LayoutSize left, LayoutSize::RawValue right) -{ - return left.isFinite() && (left.getFiniteValue() <= right); -} - -// Layout appropriate to "just memory" scenarios, -// such as laying out the members of a constant buffer. -struct UniformLayoutInfo -{ - LayoutSize size; - size_t alignment; - - UniformLayoutInfo() - : size(0) - , alignment(1) - {} - - UniformLayoutInfo( - LayoutSize size, - size_t alignment) - : size(size) - , alignment(alignment) - {} -}; - -// Extended information required for an array of uniform data, -// including the "stride" of the array (the space between -// consecutive elements). -struct UniformArrayLayoutInfo : UniformLayoutInfo -{ - size_t elementStride; - - UniformArrayLayoutInfo() - : elementStride(0) - {} - - UniformArrayLayoutInfo( - LayoutSize size, - size_t alignment, - size_t elementStride) - : UniformLayoutInfo(size, alignment) - , elementStride(elementStride) - {} -}; - -typedef slang::ParameterCategory LayoutResourceKind; - -// Layout information for a value that only consumes -// a single resource kind. -struct SimpleLayoutInfo -{ - // What kind of resource should we consume? - LayoutResourceKind kind; - - // How many resources of that kind? - LayoutSize size; - - // only useful in the uniform case - size_t alignment; - - SimpleLayoutInfo() - : kind(LayoutResourceKind::None) - , size(0) - , alignment(1) - {} - - SimpleLayoutInfo( - UniformLayoutInfo uniformInfo) - : kind(LayoutResourceKind::Uniform) - , size(uniformInfo.size) - , alignment(uniformInfo.alignment) - {} - - SimpleLayoutInfo(LayoutResourceKind kind, LayoutSize size, size_t alignment=1) - : kind(kind) - , size(size) - , alignment(alignment) - {} - - // Convert to layout for uniform data - UniformLayoutInfo getUniformLayout() - { - if(kind == LayoutResourceKind::Uniform) - { - return UniformLayoutInfo(size, alignment); - } - else - { - return UniformLayoutInfo(0, 1); - } - } -}; - -// Only useful in the case of a homogeneous array -struct SimpleArrayLayoutInfo : SimpleLayoutInfo -{ - // This field is only useful in the uniform case - size_t elementStride; - - // Convert to layout for uniform data - UniformArrayLayoutInfo getUniformLayout() - { - if(kind == LayoutResourceKind::Uniform) - { - return UniformArrayLayoutInfo(size, alignment, elementStride); - } - else - { - return UniformArrayLayoutInfo(0, 1, 0); - } - } -}; - -struct LayoutRulesImpl; - -// Base class for things that store layout info -class Layout : public RefObject -{ -}; - -// A reified representation of a particular laid-out type -class TypeLayout : public Layout -{ -public: - // The type that was laid out - RefPtr<Type> type; - Type* getType() { return type.Ptr(); } - - // The layout rules that were used to produce this type - LayoutRulesImpl* rules; - - struct ResourceInfo - { - // What kind of register was it? - LayoutResourceKind kind = LayoutResourceKind::None; - - // How many registers of the above kind did we use? - LayoutSize count; - }; - - List<ResourceInfo> resourceInfos; - - // For uniform data, alignment matters, but not for - // any other resource category, so we don't waste - // the space storing it in the above array - UInt uniformAlignment = 1; - - - /// The layout for data that is conceptually owned by this type, but which is pending layout. - /// - /// When a type contains interface/existential fields (recursively), the - /// actual data referenced by these fields needs to get allocated somewhere, - /// but it cannot go inline at the point where the interface/existential - /// type appears, or else the layout of a composite object would change - /// when the concrete type(s) we plug in change. - /// - /// We solve this problem by tracking this data that is "pending" layout, - /// and then "flushing" the pending data at appropriate places during - /// the layout process. - /// - RefPtr<TypeLayout> pendingDataTypeLayout; - - ResourceInfo* FindResourceInfo(LayoutResourceKind kind) - { - for(auto& rr : resourceInfos) - { - if(rr.kind == kind) - return &rr; - } - return nullptr; - } - - ResourceInfo* findOrAddResourceInfo(LayoutResourceKind kind) - { - auto existing = FindResourceInfo(kind); - if(existing) return existing; - - ResourceInfo info; - info.kind = kind; - info.count = 0; - resourceInfos.add(info); - return &resourceInfos.getLast(); - } - - void addResourceUsage(ResourceInfo info) - { - if(info.count == 0) return; - - findOrAddResourceInfo(info.kind)->count += info.count; - } - - void addResourceUsage(LayoutResourceKind kind, LayoutSize count) - { - ResourceInfo info; - info.kind = kind; - info.count = count; - addResourceUsage(info); - } - - void addResourceUsageFrom(TypeLayout* otherTypeLayout); - - /// "Unwrap" any layers of array-ness from this type layout. - /// - /// If this is an `ArrayTypeLayout`, returns the result of unwrapping the element type layout. - /// Otherwise, returns this type layout. - /// - RefPtr<TypeLayout> unwrapArray(); -}; - -typedef unsigned int VarLayoutFlags; -enum VarLayoutFlag : VarLayoutFlags -{ - HasSemantic = 1 << 1 -}; - -// A reified layout for a particular variable, field, etc. -class VarLayout : public Layout -{ -public: - // The variable we are laying out - DeclRef<VarDeclBase> varDecl; - VarDeclBase* getVariable() { return varDecl.getDecl(); } - - Name* getName() { return getVariable()->getName(); } - - // The result of laying out the variable's type - RefPtr<TypeLayout> typeLayout; - TypeLayout* getTypeLayout() { return typeLayout.Ptr(); } - - // Additional flags - VarLayoutFlags flags = 0; - - // System-value semantic (and index) if this is a system value - String systemValueSemantic; - int systemValueSemanticIndex; - - // General case semantic name and index - // TODO: this and the system-value field are redundant - // TODO: the `VarLayout` type is getting bloated; we need to not store this - // information unless actually required. - String semanticName; - int semanticIndex; - - // The stage this variable belongs to, in case it is - // stage-specific. - // TODO: This is wasteful to be storing on every single - // variable layout. - Stage stage = Stage::Unknown; - - // The start register(s) for any resources - struct ResourceInfo - { - // What kind of register was it? - LayoutResourceKind kind = LayoutResourceKind::None; - - // What binding space (HLSL) or set (Vulkan) are we placed in? - UInt space; - - // What is our starting register in that space? - // - // (In the case of uniform data, this is a byte offset) - UInt index; - }; - List<ResourceInfo> resourceInfos; - - ResourceInfo* FindResourceInfo(LayoutResourceKind kind) - { - for(auto& rr : resourceInfos) - { - if(rr.kind == kind) - return &rr; - } - return nullptr; - } - - ResourceInfo* AddResourceInfo(LayoutResourceKind kind) - { - ResourceInfo info; - info.kind = kind; - info.space = 0; - info.index = 0; - - resourceInfos.add(info); - return &resourceInfos.getLast(); - } - - ResourceInfo* findOrAddResourceInfo(LayoutResourceKind kind) - { - auto existing = FindResourceInfo(kind); - if(existing) return existing; - - return AddResourceInfo(kind); - } - - RefPtr<VarLayout> pendingVarLayout; -}; - -// type layout for a variable that has a constant-buffer type -class ParameterGroupTypeLayout : public TypeLayout -{ -public: - // The layout of the "container" part itself. - // E.g., for a constant buffer, this would reflect - // the resource usage of the container, without - // the element type factored in. All of the offsets - // for this variable should be zero, but it is included - // for completeness. - RefPtr<VarLayout> containerVarLayout; - - // A variable layout for the element of the container. - // The offsets of the variable layout will reflect - // the offsets that need to applied to get past the - // container types resource usage, while the actual - // type layout won't have offsets applied (unlike - // `offsetElementTypeLayout` below). - RefPtr<VarLayout> elementVarLayout; - - // The layout of the element type, with offsets applied - // so that any fields (if the element type is a `struct`) - // will be offset by the resource usage of the container. - RefPtr<TypeLayout> offsetElementTypeLayout; - - // If the element type layout had any "pending" data, then - // as much of that data as possible will be flushed to - // fit into the overall layout of the parameter group. - // - // This field stores the offset information for where - // the pending data got stored relative to the start of - // the group. - // -// RefPtr<VarLayout> flushedDataVarLayout; -}; - -// type layout for a variable that has a constant-buffer type -class StructuredBufferTypeLayout : public TypeLayout -{ -public: - RefPtr<TypeLayout> elementTypeLayout; -}; - - /// Type layout for a logical sequence type -class SequenceTypeLayout : public TypeLayout -{ -public: - /// The layout of the element type. - /// - /// This layout may include adjustments to make lookups in elements - /// of the array Just Work, and may not be the same as the layout - /// of the element type when used in a non-array context. - /// - RefPtr<TypeLayout> elementTypeLayout; - - /// The stride in bytes between elements. - size_t uniformStride = 0; -}; - - /// Type layout for an array type -class ArrayTypeLayout : public SequenceTypeLayout -{ -public: - /// The original layout of the element type. - /// - /// This layout does not include any adjustments that - /// were made to the element type in order to make - /// lookup into array elements Just Work. - /// - RefPtr<TypeLayout> originalElementTypeLayout; -}; - -// type layout for a variable with stream-output type -class StreamOutputTypeLayout : public TypeLayout -{ -public: - RefPtr<TypeLayout> elementTypeLayout; -}; - -class VectorTypeLayout : public SequenceTypeLayout -{ -public: -}; - - -class MatrixTypeLayout : public SequenceTypeLayout -{ -public: - /// Is this matrix laid out as row-major or column-major? - /// - /// Note that this does *not* affect the interpretation - /// of the `elementTypeLayout` field, which always represents - /// the logical elements of the matrix type, which are its - /// rows. - /// - MatrixLayoutMode mode; -}; - -// Specific case of type layout for a struct -class StructTypeLayout : public TypeLayout -{ -public: - // An ordered list of layouts for the known fields - List<RefPtr<VarLayout>> fields; - - // Map a variable to its layout directly. - // - // Note that in the general case, there may be entries - // in the `fields` array that came from multiple - // translation units, and in cases where there are - // multiple declarations of the same parameter, only - // one will appear in `fields`, while all of - // them will be reflected in `mapVarToLayout`. - // - // TODO: This should map from a declaration to the *index* - // in the array above, rather than to the actual pointer, - // so that we - Dictionary<Decl*, RefPtr<VarLayout>> mapVarToLayout; - - // As an accellerator for type layouts created at the - // IR layer, we include a second map that use IR "key" - // instructions to map to fields. - // - Dictionary<IRInst*, RefPtr<VarLayout>> mapKeyToLayout; -}; - -class GenericParamTypeLayout : public TypeLayout -{ -public: - RefPtr<GlobalGenericParamDecl> getGlobalGenericParamDecl(); - int paramIndex = 0; -}; - - /// Layout information for a tagged union type. -class TaggedUnionTypeLayout : public TypeLayout -{ -public: - /// The layouts of each of the case types. - /// - /// The order of entries in this array matches - /// the order of case types on the original - /// `TaggedUnionType`, and the index of a case - /// type is also the tag value for that case. - /// - List<RefPtr<TypeLayout>> caseTypeLayouts; - - /// The byte offset for the tag field. - /// - /// The tag field will always be allocated as - /// a `uint`, so we don't store a separate layout - /// for it. - /// - LayoutSize tagOffset; -}; - - /// Layout information for a type with existential (sub-)field types specialized. -class ExistentialSpecializedTypeLayout : public TypeLayout -{ -public: - RefPtr<TypeLayout> baseTypeLayout; - RefPtr<VarLayout> pendingDataVarLayout; -}; - - /// Layout for a scoped entity like a program, module, or entry point -class ScopeLayout : public Layout -{ -public: - // The layout for the parameters of this entity. - // - RefPtr<VarLayout> parametersLayout; -}; - -StructTypeLayout* getScopeStructLayout( - ScopeLayout* programLayout); - -// Layout information for a single shader entry point -// within a program -// -// Treated as a subclass of `StructTypeLayout` because -// it needs to include computed layout information -// for the parameters of the entry point. -// -// TODO: where to store layout info for the return -// type of the function? -class EntryPointLayout : public ScopeLayout -{ -public: - // The corresponding function declaration - RefPtr<FuncDecl> entryPoint; - - // The shader profile that was used to compile the entry point - Profile profile; - - // Layout for any results of the entry point - RefPtr<VarLayout> resultLayout; - - enum Flag : unsigned - { - usesAnySampleRateInput = 0x1, - }; - unsigned flags = 0; - - /// Layouts for all tagged union types required by this entry point. - /// - /// These are any tagged union types used by the generic - /// arguments that this entry point is being compiled with. - List<RefPtr<TypeLayout>> taggedUnionTypeLayouts; -}; - -class GenericParamLayout : public Layout -{ -public: - RefPtr<GlobalGenericParamDecl> decl; - int index; -}; - -// Layout information for the global scope of a program -class ProgramLayout : public ScopeLayout -{ -public: - /* - // We store a layout for the declarations at the global - // scope. Note that this will *either* be a single - // `StructTypeLayout` with the fields stored directly, - // or it will be a single `ParameterGroupTypeLayout`, - // where the global-scope fields are the members of - // that constant buffer. - // - // The `struct` case will be used if there are no - // "naked" global-scope uniform variables, and the - // constant-buffer case will be used if there are - // (since a constant buffer will have to be allocated - // to store them). - // - RefPtr<VarLayout> globalScopeLayout; - */ - - /// The target and program for which layout was computed - TargetProgram* targetProgram; - - TargetProgram* getTargetProgram() { return targetProgram; } - TargetRequest* getTargetReq() { return targetProgram->getTargetReq(); } - Program* getProgram() { return targetProgram->getProgram(); } - - - // We catalog the requested entry points here, - // and any entry-point-specific parameter data - // will (eventually) belong there... - List<RefPtr<EntryPointLayout>> entryPoints; - - List<RefPtr<GenericParamLayout>> globalGenericParams; - Dictionary<String, GenericParamLayout*> globalGenericParamsMap; -}; - -StructTypeLayout* getGlobalStructLayout( - ProgramLayout* programLayout); - -struct LayoutRulesFamilyImpl; - -// A delineation of shader parameter types into fine-grained -// categories that can then be mapped down to actual resources -// by a given set of rules. -// -// TODO(tfoley): `SlangParameterCategory` and `slang::ParameterCategory` -// are badly named, and need to be revised so they can't be confused -// with this concept. -enum class ShaderParameterKind -{ - ConstantBuffer, - TextureUniformBuffer, - ShaderStorageBuffer, - - StructuredBuffer, - MutableStructuredBuffer, - - RawBuffer, - MutableRawBuffer, - - Buffer, - MutableBuffer, - - Texture, - MutableTexture, - - TextureSampler, - MutableTextureSampler, - - InputRenderTarget, - - SamplerState, - - Image, - MutableImage, - - RegisterSpace, -}; - -struct SimpleLayoutRulesImpl -{ - // Get size and alignment for a single value of base type. - virtual SimpleLayoutInfo GetScalarLayout(BaseType baseType) = 0; - - // Get size and alignment for an array of elements - virtual SimpleArrayLayoutInfo GetArrayLayout(SimpleLayoutInfo elementInfo, LayoutSize elementCount) = 0; - - // Get layout for a vector or matrix type - virtual SimpleLayoutInfo GetVectorLayout(SimpleLayoutInfo elementInfo, size_t elementCount) = 0; - virtual SimpleArrayLayoutInfo GetMatrixLayout(SimpleLayoutInfo elementInfo, size_t rowCount, size_t columnCount) = 0; - - // Begin doing layout on a `struct` type - virtual UniformLayoutInfo BeginStructLayout() = 0; - - // Add a field to a `struct` type, and return the offset for the field - virtual LayoutSize AddStructField(UniformLayoutInfo* ioStructInfo, UniformLayoutInfo fieldInfo) = 0; - - // End layout for a struct, and finalize its size/alignment. - virtual void EndStructLayout(UniformLayoutInfo* ioStructInfo) = 0; -}; - -struct ObjectLayoutRulesImpl -{ - // Compute layout info for an object type - virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind) = 0; -}; - -struct LayoutRulesImpl -{ - LayoutRulesFamilyImpl* family; - SimpleLayoutRulesImpl* simpleRules; - ObjectLayoutRulesImpl* objectRules; - - // Forward `SimpleLayoutRulesImpl` interface - - SimpleLayoutInfo GetScalarLayout(BaseType baseType) - { - return simpleRules->GetScalarLayout(baseType); - } - - SimpleArrayLayoutInfo GetArrayLayout(SimpleLayoutInfo elementInfo, LayoutSize elementCount) - { - return simpleRules->GetArrayLayout(elementInfo, elementCount); - } - - SimpleLayoutInfo GetVectorLayout(SimpleLayoutInfo elementInfo, size_t elementCount) - { - return simpleRules->GetVectorLayout(elementInfo, elementCount); - } - - SimpleArrayLayoutInfo GetMatrixLayout(SimpleLayoutInfo elementInfo, size_t rowCount, size_t columnCount) - { - return simpleRules->GetMatrixLayout(elementInfo, rowCount, columnCount); - } - - UniformLayoutInfo BeginStructLayout() - { - return simpleRules->BeginStructLayout(); - } - - LayoutSize AddStructField(UniformLayoutInfo* ioStructInfo, UniformLayoutInfo fieldInfo) - { - return simpleRules->AddStructField(ioStructInfo, fieldInfo); - } - - void EndStructLayout(UniformLayoutInfo* ioStructInfo) - { - return simpleRules->EndStructLayout(ioStructInfo); - } - - // Forward `ObjectLayoutRulesImpl` interface - - SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind) - { - return objectRules->GetObjectLayout(kind); - } - - // - - LayoutRulesFamilyImpl* getLayoutRulesFamily() { return family; } -}; - -struct LayoutRulesFamilyImpl -{ - virtual LayoutRulesImpl* getConstantBufferRules() = 0; - virtual LayoutRulesImpl* getPushConstantBufferRules() = 0; - virtual LayoutRulesImpl* getTextureBufferRules() = 0; - virtual LayoutRulesImpl* getVaryingInputRules() = 0; - virtual LayoutRulesImpl* getVaryingOutputRules() = 0; - virtual LayoutRulesImpl* getSpecializationConstantRules()= 0; - virtual LayoutRulesImpl* getShaderStorageBufferRules() = 0; - virtual LayoutRulesImpl* getParameterBlockRules() = 0; - - virtual LayoutRulesImpl* getRayPayloadParameterRules() = 0; - virtual LayoutRulesImpl* getCallablePayloadParameterRules() = 0; - virtual LayoutRulesImpl* getHitAttributesParameterRules()= 0; - - virtual LayoutRulesImpl* getShaderRecordConstantBufferRules() = 0; -}; - -typedef List<RefPtr<GenericParamLayout>> GenericParamLayouts; - -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; - - // The target request that is triggering layout - TargetRequest* targetReq; - - // A parent program layout that will establish the ordering - // of all global generic type parameters. - // - ProgramLayout* programLayout; - - // Whether to lay out matrices column-major - // or row-major. - MatrixLayoutMode matrixLayoutMode; - - // The concrete types (if any) to plug into the currently in-scope - // existential type slots. - // - Int existentialTypeArgCount = 0; - ExistentialTypeSlots::Arg const* existentialTypeArgs = nullptr; - - LayoutRulesImpl* getRules() { return rules; } - LayoutRulesFamilyImpl* getRulesFamily() const { return rules->getLayoutRulesFamily(); } - - TypeLayoutContext with(LayoutRulesImpl* inRules) const - { - TypeLayoutContext result = *this; - result.rules = inRules; - return result; - } - - TypeLayoutContext with(MatrixLayoutMode inMatrixLayoutMode) const - { - TypeLayoutContext result = *this; - result.matrixLayoutMode = inMatrixLayoutMode; - return result; - } - - TypeLayoutContext withExistentialTypeArgs( - Int argCount, - ExistentialTypeSlots::Arg const* args) const - { - TypeLayoutContext result = *this; - result.existentialTypeArgCount = argCount; - result.existentialTypeArgs = args; - return result; - } - - TypeLayoutContext withExistentialTypeSlotsOffsetBy( - Int offset) const - { - TypeLayoutContext result = *this; - if( existentialTypeArgCount > offset ) - { - result.existentialTypeArgCount = existentialTypeArgCount - offset; - result.existentialTypeArgs = existentialTypeArgs + offset; - } - else - { - result.existentialTypeArgCount = 0; - result.existentialTypeArgs = nullptr; - } - return result; - - } -}; - -// - - /// A custom tuple to capture the outputs of type layout -struct TypeLayoutResult -{ - /// The actual heap-allocated layout object with all the details - RefPtr<TypeLayout> layout; - - /// A simplified representation of layout information. - /// - /// This information is suitable for the case where a type only - /// consumes a single resource. - /// - SimpleLayoutInfo info; - - /// Default constructor. - TypeLayoutResult() - {} - - /// Construct a result from the given layout object and simple layout info. - TypeLayoutResult(RefPtr<TypeLayout> inLayout, SimpleLayoutInfo const& inInfo) - : layout(inLayout) - , info(inInfo) - {} -}; - - /// Helper type for building `struct` type layouts -struct StructTypeLayoutBuilder -{ -public: - /// Begin the layout process for `type`, using `rules` - void beginLayout( - Type* type, - LayoutRulesImpl* rules); - - /// Begin the layout process for `type`, using `rules`, if it hasn't already been begun. - /// - /// This functions allows for a `StructTypeLayoutBuilder` to be use lazily, - /// only allocating a type layout object if it is actaully needed. - /// - void beginLayoutIfNeeded( - Type* type, - LayoutRulesImpl* rules); - - /// Add a field to the struct type layout. - /// - /// One of the `beginLayout*()` functions must have been called previously. - /// - RefPtr<VarLayout> addField( - DeclRef<VarDeclBase> field, - TypeLayoutResult fieldResult); - - /// Add a field to the struct type layout. - /// - /// One of the `beginLayout*()` functions must have been called previously. - /// - RefPtr<VarLayout> addField( - DeclRef<VarDeclBase> field, - RefPtr<TypeLayout> fieldTypeLayout); - - /// Complete layout. - /// - /// If layout was begun, ensures that the result of `getTypeLayout()` is usable. - /// If layout was never begin, does nothing. - /// - void endLayout(); - - /// Get the type layout. - /// - /// This can be called any time after `beginLayout*()`. - /// In particular, it can be called before `endLayout`. - /// - RefPtr<StructTypeLayout> getTypeLayout(); - - /// The the type layout result. - /// - /// This is primarily useful for implementation code in `_createTypeLayout`. - /// - TypeLayoutResult getTypeLayoutResult(); - -private: - /// The layout rules being used, if layout has begun. - LayoutRulesImpl* m_rules = nullptr; - - /// The type layout being computed, if layout has begun. - RefPtr<StructTypeLayout> m_typeLayout; - - /// Uniform offset/alignment statte used when computing offset for uniform fields. - UniformLayoutInfo m_info; -}; - -// - -// Get an appropriate set of layout rules (packaged up -// as a `TypeLayoutContext`) to perform type layout -// for the given target. -// -// The provided `programLayout` is used to establish -// the ordering of all global generic type paramters. -// -TypeLayoutContext getInitialLayoutContextForTarget( - TargetRequest* targetReq, - ProgramLayout* programLayout); - - /// Direction(s) of a varying shader parameter -typedef unsigned int EntryPointParameterDirectionMask; -enum -{ - kEntryPointParameterDirection_Input = 0x1, - kEntryPointParameterDirection_Output = 0x2, -}; - - - /// Get layout information for a simple varying parameter type. - /// - /// A simple varying parameter is a scalar, vector, or matrix. - /// -RefPtr<TypeLayout> getSimpleVaryingParameterTypeLayout( - TypeLayoutContext const& context, - Type* type, - EntryPointParameterDirectionMask directionMask); - -// 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 layout for a parameter-group type (a `ConstantBuffer` or `ParameterBlock`). -RefPtr<TypeLayout> createParameterGroupTypeLayout( - TypeLayoutContext const& context, - RefPtr<ParameterGroupType> parameterGroupType); - - /// Create a wrapper constant buffer type layout, if needed. - /// - /// When dealing with entry-point `uniform` and global-scope parameters, - /// we want to create a wrapper constant buffer for all the parameters - /// if and only if there exist some parameters that use "ordinary" data - /// (`LayoutResourceKind::Uniform`). - /// - /// This function determines whether such a wrapper is needed, based - /// on the `elementTypeLayout` given, and either creates and returns - /// the layout for the wrapper, or the unmodified `elementTypeLayout`. - /// -RefPtr<TypeLayout> createConstantBufferTypeLayoutIfNeeded( - TypeLayoutContext const& context, - RefPtr<TypeLayout> elementTypeLayout); - -// Create a type layout for a structured buffer type. -RefPtr<StructuredBufferTypeLayout> -createStructuredBufferTypeLayout( - TypeLayoutContext const& context, - ShaderParameterKind kind, - RefPtr<Type> structuredBufferType, - RefPtr<Type> elementType); - -int findGenericParam(List<RefPtr<GenericParamLayout>> & genericParameters, GlobalGenericParamDecl * decl); -// - -// Given an existing type layout `oldTypeLayout`, apply offsets -// to any contained fields based on the resource infos in `offsetVarLayout`. -RefPtr<TypeLayout> applyOffsetToTypeLayout( - RefPtr<TypeLayout> oldTypeLayout, - RefPtr<VarLayout> offsetVarLayout); - -} - -#endif |
