diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2023-08-15 20:28:42 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-15 20:28:42 +0800 |
| commit | 00bd481e001e8c0b8008eaff5a38fa37963e6f99 (patch) | |
| tree | d068f0649167bff80b9cd3aa7d32d790540e9564 /source/slang/slang-ir-layout-on-types.cpp | |
| parent | 113a257aafe4403c3ab905098d0560635ca94286 (diff) | |
SPIR-V WIP (#3064)
* Add type layout for structured buffer
* Default to generating spirv directly
* vk test for compute simple
* Add spirv-dis as a downstream compiler
* Emit Array types in SPIR-V
* makevector for spirv
* Dump whole spirv module on validation failure
* register array types
todo, use emitTypeInst
* Neater formatting for unhandled inst printing
* break out emitCompositeConstruct
* Correct array type generation
* neaten
* Allow getElement for vector
* Remove unused
* Allow predicating target intrinsics on types
* Consider functions with intrinsics to have definitions
We need to specialize these if they are predicated on types
* Correct array type generation
* makeArray for spir-v
* replace getElement with getElementPtr for spirv
* Correct translation of field access for spirv
* Push layouts to types for spirv
* Spirv intrinsics * operator now makes a pointer
* Add structured buffer of struct test
* Preserve type layout in spirv structured buffer legalization
* neaten
* makeVectorFromScalar for SPIRV
* placeholder for layouts on param groups
* More type safe spirv op construction
* Know that constants and types only go in one section
* Remove emitTypeInst
* Add todo for spirv sampling
* Add links to spirv documentation on emit functions
* OpTypeImage support for SPIR-V
* Add simpler texture test for spirv
* s/spirv_direct/spirv/g
* Allow several string literals in target_intrinsic
* Handle global params without a var layour for SPIR-V
For example groupshared vars
* uint spirv asm type
* Add todo for isDefinition
It is currently too broad
* Some atomic op spirv intrinsics
* Strip ConstantBuffer wrappers for spirv
* Add todo for matrix annotations
* Do not associate decorations insts with spirv counterparts
* Correct entry point parameter generation
* Spelling
* Assert that fieldAddress is returning a pointer
* Add error for existential type layout getting to spir-v emit
* Add IRTupleTypeLayout
Unused so far
* Allow getElementPtr to work with vectors
* Correct target name in test
* Hide default spirv direct behind a premake option --default-spirv-direct=true
* Do not insert space at start of intrinsic def
* Correct asm rendering in tests
* remove redundant option
* Emit directly from direct test
* Add source language options for spirv-dis
* Add comments to spirv dis
* Add dead debug print for before spirv module
* Correct asm rendering in tests
* s/spirv_direct/spirv/g
* Only specialize intrinsic functions with predicates
* regenerate vs projects
* squash warnings
* squash warnings
* remove duplication
* Silence warnings from msvc
* squash warnings
* Overload for zero sized array
* More msvc warnings
* warnings
* Add spirv-tools to path for tests
* Do not be specific about dxc version for diag test
* Normalize line endings from spirv-dis
* Correct filecheck matches
* Temporarily disable two spirv tests
Failing on CI, undebuggable hang :/
* Do not emit storage class more than once for spirv snippet
* Do not pass spir-v to spirv-dis by stdin
* Do not get spirv-dis output via stream, use file
* normalize file endings in spirv-dis output
Diffstat (limited to 'source/slang/slang-ir-layout-on-types.cpp')
| -rw-r--r-- | source/slang/slang-ir-layout-on-types.cpp | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/source/slang/slang-ir-layout-on-types.cpp b/source/slang/slang-ir-layout-on-types.cpp new file mode 100644 index 000000000..a1e480067 --- /dev/null +++ b/source/slang/slang-ir-layout-on-types.cpp @@ -0,0 +1,153 @@ +#include "slang-ir-layout-on-types.h" + +#include "slang-ir-insts.h" +#include "slang-ir.h" + +namespace Slang +{ + +struct TypeTypeLayout +{ + IRType* type; + IRTypeLayout* layout; +}; + +template<typename Struct, typename StructuredBuffer, typename Array, typename Base> +static void zipPreorderTypeAndTypeLayout( + Struct struct_, + StructuredBuffer structuredBuffer, + Array array, + Base base, + IRType* type, + IRTypeLayout* layout) +{ + auto go = [&](auto& go, IRType* type, IRLayout* layout) -> void{ + if(const auto structTypeLayout = as<IRStructTypeLayout>(layout)) + { + const auto structType = as<IRStructType>(type); + SLANG_ASSERT(structType); + struct_(structType, structTypeLayout); + + Index i = 0; + for(const auto field : structType->getFields()) + { + const auto fieldVarLayout = structTypeLayout->getFieldLayout(i); + const auto fieldTypeLayout = fieldVarLayout->getTypeLayout(); + const auto fieldType = field->getFieldType(); + go(go, fieldType, fieldTypeLayout); + ++i; + } + } + else if(const auto structuredBufferTypeLayout = as<IRStructuredBufferTypeLayout>(layout)) + { + const auto structuredBufferType = as<IRHLSLStructuredBufferTypeBase>(type); + SLANG_ASSERT(structuredBufferType); + structuredBuffer(structuredBufferType, structuredBufferTypeLayout); + + go(go, structuredBufferType->getElementType(), structuredBufferTypeLayout->getElementTypeLayout()); + } + else if(const auto arrayTypeLayout = as<IRArrayTypeLayout>(layout)) + { + const auto arrayType = as<IRArrayTypeBase>(type); + SLANG_ASSERT(arrayType); + array(arrayType , arrayTypeLayout); + + go(go, arrayType->getElementType(), arrayTypeLayout->getElementTypeLayout()); + } + else if(const auto existentialTypeLayout = as<IRExistentialTypeLayout>(layout)) + { + // TODO: To resolve this we should + // - Record the interface width in each IRExistentialTypeLayout + // - To allow us to replace them with IRTupleTypeLayout when we lower existentials + // - To allow us to replace them with IRStructTypeLayout when we lower tuples + SLANG_UNEXPECTED("Existentials (or their layouts) have not been erased before SPIR-V emit"); + } + else + { + base((IRType*)type, (IRTypeLayout*)layout); + } + }; + go(go, type, layout); +} + +static Dictionary<IRType*, IRTypeLayout*> associateTypesWithLayouts(IRModule* module) +{ + List<TypeTypeLayout> worklist; + for(auto globalInst : module->getGlobalInsts()) + { + if(const auto varLayout = as<IRVarLayout>(globalInst)) + { + auto typeLayout = varLayout->getTypeLayout(); + List<IRInst*> vars; + traverseUsers(varLayout, [&](IRInst* varLayoutUser){ + if(const auto dec = as<IRLayoutDecoration>(varLayoutUser)) + { + if(const auto globalParam = as<IRGlobalParam>(dec->getParent())) + vars.add(globalParam); + else + { + // todo + } + } + else if(as<IREntryPointLayout>(varLayoutUser)) + { + // todo + } + else if(as<IRStructFieldLayoutAttr>(varLayoutUser)) + { + // todo + } + else if(as<IRParameterGroupTypeLayout>(varLayoutUser)) + { + // todo + } + else + SLANG_UNEXPECTED("Var layout was used somewhere unexpected"); + }); + if(vars.getCount() == 1) + { + auto type = vars[0]->getDataType(); + worklist.add({type, typeLayout}); + } + else if(vars.getCount() > 2) + { + SLANG_UNIMPLEMENTED_X("vars with different layouts"); + } + } + } + + Dictionary<IRType*, IRTypeLayout*> ret; + while(!worklist.getCount() == 0) + { + const auto ttl = worklist.getLast(); + worklist.removeLast(); + const auto add = [&](IRType* type, IRTypeLayout* typeLayout){ + const auto* otherTypeLayout = ret.tryGetValueOrAdd(type, typeLayout); + if(otherTypeLayout) + SLANG_ASSERT(*otherTypeLayout == typeLayout); + }; + zipPreorderTypeAndTypeLayout(add, add, add, add, ttl.type, ttl.layout); + } + + return ret; +} + +static void decorateTypesWithLayouts(IRModule* module, const Dictionary<IRType*, IRTypeLayout*>& assocs) +{ + IRBuilder builder(module); + for(const auto& [type, layout] : assocs) + { + builder.setInsertBefore(type); + // TODO: types with more than one decoration (needs deduplicating) + builder.addLayoutDecoration(type, layout); + } +} + +void placeTypeLayoutsOnTypes(IRModule* module, CodeGenContext* codeGenContext) +{ + SLANG_ASSERT(module); + SLANG_ASSERT(codeGenContext); + const auto assocs = associateTypesWithLayouts(module); + decorateTypesWithLayouts(module, assocs); +} +} |
