diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2020-12-04 13:03:29 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-04 10:03:29 -0800 |
| commit | 47ed0f68602a8ed0c425d2a4666969ad0db04ca6 (patch) | |
| tree | c104f182dbf1a2b9e12e8d383215749e11ab35dc /source/slang/slang-reflection.cpp | |
| parent | 277780ab7770453ed12e82df10d2a9d79ebf47dd (diff) | |
Projects in 'build' and Slang API separation (#1624)
* #include an absolute path didn't work - because paths were taken to always be relative.
* Move reflection to reflection-api.
* Slight reorg to pull out potentially Slang internal functions from the reflection API impls.
* Remove visual studio projects
* Fix for slang-binaries copy.
* Add the visual studio projects in build/visual-studio
* Remove miniz project.
* Differentiate the linePath from the filePath.
* Improve comment in premake5.lua + to kick of CI.
* Kick CI.
Diffstat (limited to 'source/slang/slang-reflection.cpp')
| -rw-r--r-- | source/slang/slang-reflection.cpp | 2508 |
1 files changed, 0 insertions, 2508 deletions
diff --git a/source/slang/slang-reflection.cpp b/source/slang/slang-reflection.cpp deleted file mode 100644 index 42355ca02..000000000 --- a/source/slang/slang-reflection.cpp +++ /dev/null @@ -1,2508 +0,0 @@ -// slang-reflection.cpp -#include "slang-reflection.h" - -#include "slang-compiler.h" -#include "slang-type-layout.h" -#include "slang-syntax.h" -#include <assert.h> - -// Don't signal errors for stuff we don't implement here, -// and instead just try to return things defensively -// -// Slang developers can switch this when debugging. -#define SLANG_REFLECTION_UNEXPECTED() do {} while(0) - -// Implementation to back public-facing reflection API - -using namespace Slang; - - -// Conversion routines to help with strongly-typed reflection API -static inline Session* convert(SlangSession* session) -{ - return (Session*)session; -} - -static inline UserDefinedAttribute* convert(SlangReflectionUserAttribute* attrib) -{ - return (UserDefinedAttribute*)attrib; -} -static inline SlangReflectionUserAttribute* convert(UserDefinedAttribute* attrib) -{ - return (SlangReflectionUserAttribute*)attrib; -} -static inline Type* convert(SlangReflectionType* type) -{ - return (Type*) type; -} - -static inline SlangReflectionType* convert(Type* type) -{ - return (SlangReflectionType*) type; -} - -static inline TypeLayout* convert(SlangReflectionTypeLayout* type) -{ - return (TypeLayout*) type; -} - -static inline SlangReflectionTypeLayout* convert(TypeLayout* type) -{ - return (SlangReflectionTypeLayout*) type; -} - -static inline SpecializationParamLayout* convert(SlangReflectionTypeParameter * typeParam) -{ - return (SpecializationParamLayout*) typeParam; -} - -static inline VarDeclBase* convert(SlangReflectionVariable* var) -{ - return (VarDeclBase*) var; -} - -static inline SlangReflectionVariable* convert(VarDeclBase* var) -{ - return (SlangReflectionVariable*) var; -} - -static inline VarLayout* convert(SlangReflectionVariableLayout* var) -{ - return (VarLayout*) var; -} - -static inline SlangReflectionVariableLayout* convert(VarLayout* var) -{ - return (SlangReflectionVariableLayout*) var; -} - -static inline EntryPointLayout* convert(SlangReflectionEntryPoint* entryPoint) -{ - return (EntryPointLayout*) entryPoint; -} - -static inline SlangReflectionEntryPoint* convert(EntryPointLayout* entryPoint) -{ - return (SlangReflectionEntryPoint*) entryPoint; -} - -static inline ProgramLayout* convert(SlangReflection* program) -{ - return (ProgramLayout*) program; -} - -static inline SlangReflection* convert(ProgramLayout* program) -{ - return (SlangReflection*) program; -} - -// user attaribute - -unsigned int getUserAttributeCount(Decl* decl) -{ - unsigned int count = 0; - for (auto x : decl->getModifiersOfType<UserDefinedAttribute>()) - { - SLANG_UNUSED(x); - count++; - } - return count; -} - -SlangReflectionUserAttribute* findUserAttributeByName(Session* session, Decl* decl, const char* name) -{ - auto nameObj = session->tryGetNameObj(name); - for (auto x : decl->getModifiersOfType<UserDefinedAttribute>()) - { - if (x->keywordName == nameObj) - return (SlangReflectionUserAttribute*)(x); - } - return nullptr; -} - -SlangReflectionUserAttribute* getUserAttributeByIndex(Decl* decl, unsigned int index) -{ - unsigned int id = 0; - for (auto x : decl->getModifiersOfType<UserDefinedAttribute>()) - { - if (id == index) - return convert(x); - id++; - } - return nullptr; -} - -SLANG_API char const* spReflectionUserAttribute_GetName(SlangReflectionUserAttribute* attrib) -{ - auto userAttr = convert(attrib); - if (!userAttr) return nullptr; - return userAttr->getKeywordName()->text.getBuffer(); -} -SLANG_API unsigned int spReflectionUserAttribute_GetArgumentCount(SlangReflectionUserAttribute* attrib) -{ - auto userAttr = convert(attrib); - if (!userAttr) return 0; - return (unsigned int)userAttr->args.getCount(); -} -SlangReflectionType* spReflectionUserAttribute_GetArgumentType(SlangReflectionUserAttribute* attrib, unsigned int index) -{ - auto userAttr = convert(attrib); - if (!userAttr) return nullptr; - return convert(userAttr->args[index]->type.type); -} -SLANG_API SlangResult spReflectionUserAttribute_GetArgumentValueInt(SlangReflectionUserAttribute* attrib, unsigned int index, int * rs) -{ - auto userAttr = convert(attrib); - if (!userAttr) return SLANG_ERROR_INVALID_PARAMETER; - if (index >= (unsigned int)userAttr->args.getCount()) return SLANG_ERROR_INVALID_PARAMETER; - NodeBase* val = nullptr; - if (userAttr->intArgVals.TryGetValue(index, val)) - { - *rs = (int)as<ConstantIntVal>(val)->value; - return 0; - } - return SLANG_ERROR_INVALID_PARAMETER; -} -SLANG_API SlangResult spReflectionUserAttribute_GetArgumentValueFloat(SlangReflectionUserAttribute* attrib, unsigned int index, float * rs) -{ - auto userAttr = convert(attrib); - if (!userAttr) return SLANG_ERROR_INVALID_PARAMETER; - if (index >= (unsigned int)userAttr->args.getCount()) return SLANG_ERROR_INVALID_PARAMETER; - if (auto cexpr = as<FloatingPointLiteralExpr>(userAttr->args[index])) - { - *rs = (float)cexpr->value; - return 0; - } - return SLANG_ERROR_INVALID_PARAMETER; -} -SLANG_API const char* spReflectionUserAttribute_GetArgumentValueString(SlangReflectionUserAttribute* attrib, unsigned int index, size_t* bufLen) -{ - auto userAttr = convert(attrib); - if (!userAttr) return nullptr; - if (index >= (unsigned int)userAttr->args.getCount()) return nullptr; - if (auto cexpr = as<StringLiteralExpr>(userAttr->args[index])) - { - if (bufLen) - *bufLen = cexpr->token.getContentLength(); - return cexpr->token.getContent().begin(); - } - return nullptr; -} - - - -// type Reflection - - -SLANG_API SlangTypeKind spReflectionType_GetKind(SlangReflectionType* inType) -{ - auto type = convert(inType); - if(!type) return SLANG_TYPE_KIND_NONE; - - // TODO(tfoley: Don't emit the same type more than once... - - if (auto basicType = as<BasicExpressionType>(type)) - { - return SLANG_TYPE_KIND_SCALAR; - } - else if (auto vectorType = as<VectorExpressionType>(type)) - { - return SLANG_TYPE_KIND_VECTOR; - } - else if (auto matrixType = as<MatrixExpressionType>(type)) - { - return SLANG_TYPE_KIND_MATRIX; - } - else if (auto parameterBlockType = as<ParameterBlockType>(type)) - { - return SLANG_TYPE_KIND_PARAMETER_BLOCK; - } - else if (auto constantBufferType = as<ConstantBufferType>(type)) - { - return SLANG_TYPE_KIND_CONSTANT_BUFFER; - } - else if( auto streamOutputType = as<HLSLStreamOutputType>(type) ) - { - return SLANG_TYPE_KIND_OUTPUT_STREAM; - } - else if (as<TextureBufferType>(type)) - { - return SLANG_TYPE_KIND_TEXTURE_BUFFER; - } - else if (as<GLSLShaderStorageBufferType>(type)) - { - return SLANG_TYPE_KIND_SHADER_STORAGE_BUFFER; - } - else if (auto samplerStateType = as<SamplerStateType>(type)) - { - return SLANG_TYPE_KIND_SAMPLER_STATE; - } - else if (auto textureType = as<TextureTypeBase>(type)) - { - return SLANG_TYPE_KIND_RESOURCE; - } - else if (auto feedbackType = as<FeedbackType>(type)) - { - return SLANG_TYPE_KIND_FEEDBACK; - } - // TODO: need a better way to handle this stuff... -#define CASE(TYPE) \ - else if(as<TYPE>(type)) do { \ - return SLANG_TYPE_KIND_RESOURCE; \ - } while(0) - - CASE(HLSLStructuredBufferType); - CASE(HLSLRWStructuredBufferType); - CASE(HLSLRasterizerOrderedStructuredBufferType); - CASE(HLSLAppendStructuredBufferType); - CASE(HLSLConsumeStructuredBufferType); - CASE(HLSLByteAddressBufferType); - CASE(HLSLRWByteAddressBufferType); - CASE(HLSLRasterizerOrderedByteAddressBufferType); - CASE(UntypedBufferResourceType); -#undef CASE - - else if (auto arrayType = as<ArrayExpressionType>(type)) - { - return SLANG_TYPE_KIND_ARRAY; - } - else if( auto declRefType = as<DeclRefType>(type) ) - { - const auto& declRef = declRefType->declRef; - if(declRef.is<StructDecl>() ) - { - return SLANG_TYPE_KIND_STRUCT; - } - else if (declRef.is<GlobalGenericParamDecl>()) - { - return SLANG_TYPE_KIND_GENERIC_TYPE_PARAMETER; - } - else if (declRef.is<InterfaceDecl>()) - { - return SLANG_TYPE_KIND_INTERFACE; - } - else if (declRef.is<FuncDecl>()) - { - // This is a reference to an entry point - return SLANG_TYPE_KIND_STRUCT; - } - } - else if( auto specializedType = as<ExistentialSpecializedType>(type) ) - { - return SLANG_TYPE_KIND_SPECIALIZED; - } - else if (auto errorType = as<ErrorType>(type)) - { - // This means we saw a type we didn't understand in the user's code - return SLANG_TYPE_KIND_NONE; - } - - SLANG_REFLECTION_UNEXPECTED(); - return SLANG_TYPE_KIND_NONE; -} - -SLANG_API unsigned int spReflectionType_GetFieldCount(SlangReflectionType* inType) -{ - auto type = convert(inType); - if(!type) return 0; - - // TODO: maybe filter based on kind - - if(auto declRefType = as<DeclRefType>(type)) - { - auto declRef = declRefType->declRef; - if( auto structDeclRef = declRef.as<StructDecl>()) - { - return (unsigned int)getFields(structDeclRef, MemberFilterStyle::Instance).getCount(); - } - } - - return 0; -} - -SLANG_API SlangReflectionVariable* spReflectionType_GetFieldByIndex(SlangReflectionType* inType, unsigned index) -{ - auto type = convert(inType); - if(!type) return nullptr; - - // TODO: maybe filter based on kind - - if(auto declRefType = as<DeclRefType>(type)) - { - auto declRef = declRefType->declRef; - if( auto structDeclRef = declRef.as<StructDecl>()) - { - auto fields = getFields(structDeclRef, MemberFilterStyle::Instance); - auto fieldDeclRef = fields[index]; - return (SlangReflectionVariable*) fieldDeclRef.getDecl(); - } - } - - return nullptr; -} - -SLANG_API size_t spReflectionType_GetElementCount(SlangReflectionType* inType) -{ - auto type = convert(inType); - if(!type) return 0; - - if(auto arrayType = as<ArrayExpressionType>(type)) - { - return arrayType->arrayLength ? (size_t) getIntVal(arrayType->arrayLength) : 0; - } - else if( auto vectorType = as<VectorExpressionType>(type)) - { - return (size_t) getIntVal(vectorType->elementCount); - } - - return 0; -} - -SLANG_API SlangReflectionType* spReflectionType_GetElementType(SlangReflectionType* inType) -{ - auto type = convert(inType); - if(!type) return nullptr; - - if(auto arrayType = as<ArrayExpressionType>(type)) - { - return (SlangReflectionType*) arrayType->baseType; - } - else if( auto parameterGroupType = as<ParameterGroupType>(type)) - { - return convert(parameterGroupType->elementType); - } - else if( auto vectorType = as<VectorExpressionType>(type)) - { - return convert(vectorType->elementType); - } - else if( auto matrixType = as<MatrixExpressionType>(type)) - { - return convert(matrixType->getElementType()); - } - - return nullptr; -} - -SLANG_API unsigned int spReflectionType_GetRowCount(SlangReflectionType* inType) -{ - auto type = convert(inType); - if(!type) return 0; - - if(auto matrixType = as<MatrixExpressionType>(type)) - { - return (unsigned int) getIntVal(matrixType->getRowCount()); - } - else if(auto vectorType = as<VectorExpressionType>(type)) - { - return 1; - } - else if( auto basicType = as<BasicExpressionType>(type) ) - { - return 1; - } - - return 0; -} - -SLANG_API unsigned int spReflectionType_GetColumnCount(SlangReflectionType* inType) -{ - auto type = convert(inType); - if(!type) return 0; - - if(auto matrixType = as<MatrixExpressionType>(type)) - { - return (unsigned int) getIntVal(matrixType->getColumnCount()); - } - else if(auto vectorType = as<VectorExpressionType>(type)) - { - return (unsigned int) getIntVal(vectorType->elementCount); - } - else if( auto basicType = as<BasicExpressionType>(type) ) - { - return 1; - } - - return 0; -} - -SLANG_API SlangScalarType spReflectionType_GetScalarType(SlangReflectionType* inType) -{ - auto type = convert(inType); - if(!type) return 0; - - if(auto matrixType = as<MatrixExpressionType>(type)) - { - type = matrixType->getElementType(); - } - else if(auto vectorType = as<VectorExpressionType>(type)) - { - type = vectorType->elementType; - } - - if(auto basicType = as<BasicExpressionType>(type)) - { - switch (basicType->baseType) - { -#define CASE(BASE, TAG) \ - case BaseType::BASE: return SLANG_SCALAR_TYPE_##TAG - - CASE(Void, VOID); - CASE(Bool, BOOL); - CASE(Int8, INT8); - CASE(Int16, INT16); - CASE(Int, INT32); - CASE(Int64, INT64); - CASE(UInt8, UINT8); - CASE(UInt16, UINT16); - CASE(UInt, UINT32); - CASE(UInt64, UINT64); - CASE(Half, FLOAT16); - CASE(Float, FLOAT32); - CASE(Double, FLOAT64); - -#undef CASE - - default: - SLANG_REFLECTION_UNEXPECTED(); - return SLANG_SCALAR_TYPE_NONE; - break; - } - } - - return SLANG_SCALAR_TYPE_NONE; -} - -SLANG_API unsigned int spReflectionType_GetUserAttributeCount(SlangReflectionType* inType) -{ - auto type = convert(inType); - if (!type) return 0; - if (auto declRefType = as<DeclRefType>(type)) - { - return getUserAttributeCount(declRefType->declRef.getDecl()); - } - return 0; -} -SLANG_API SlangReflectionUserAttribute* spReflectionType_GetUserAttribute(SlangReflectionType* inType, unsigned int index) -{ - auto type = convert(inType); - if (!type) return 0; - if (auto declRefType = as<DeclRefType>(type)) - { - return getUserAttributeByIndex(declRefType->declRef.getDecl(), index); - } - return 0; -} -SLANG_API SlangReflectionUserAttribute* spReflectionType_FindUserAttributeByName(SlangReflectionType* inType, char const* name) -{ - auto type = convert(inType); - if (!type) return 0; - if (auto declRefType = as<DeclRefType>(type)) - { - ASTBuilder* astBuilder = declRefType->getASTBuilder(); - auto globalSession = astBuilder->getGlobalSession(); - - return findUserAttributeByName(globalSession, declRefType->declRef.getDecl(), name); - } - return 0; -} - -SLANG_API SlangResourceShape spReflectionType_GetResourceShape(SlangReflectionType* inType) -{ - auto type = convert(inType); - if(!type) return 0; - - while(auto arrayType = as<ArrayExpressionType>(type)) - { - type = arrayType->baseType; - } - - if(auto textureType = as<TextureTypeBase>(type)) - { - return textureType->getShape(); - } - - // TODO: need a better way to handle this stuff... -#define CASE(TYPE, SHAPE, ACCESS) \ - else if(as<TYPE>(type)) do { \ - return SHAPE; \ - } while(0) - - CASE(HLSLStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_READ); - CASE(HLSLRWStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_READ_WRITE); - CASE(HLSLRasterizerOrderedStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_RASTER_ORDERED); - CASE(HLSLAppendStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_APPEND); - CASE(HLSLConsumeStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_CONSUME); - CASE(HLSLByteAddressBufferType, SLANG_BYTE_ADDRESS_BUFFER, SLANG_RESOURCE_ACCESS_READ); - CASE(HLSLRWByteAddressBufferType, SLANG_BYTE_ADDRESS_BUFFER, SLANG_RESOURCE_ACCESS_READ_WRITE); - CASE(HLSLRasterizerOrderedByteAddressBufferType, SLANG_BYTE_ADDRESS_BUFFER, SLANG_RESOURCE_ACCESS_RASTER_ORDERED); - CASE(RaytracingAccelerationStructureType, SLANG_ACCELERATION_STRUCTURE, SLANG_RESOURCE_ACCESS_READ); - CASE(UntypedBufferResourceType, SLANG_BYTE_ADDRESS_BUFFER, SLANG_RESOURCE_ACCESS_READ); -#undef CASE - - return SLANG_RESOURCE_NONE; -} - -SLANG_API SlangResourceAccess spReflectionType_GetResourceAccess(SlangReflectionType* inType) -{ - auto type = convert(inType); - if(!type) return 0; - - while(auto arrayType = as<ArrayExpressionType>(type)) - { - type = arrayType->baseType; - } - - if(auto textureType = as<TextureTypeBase>(type)) - { - return textureType->getAccess(); - } - - // TODO: need a better way to handle this stuff... -#define CASE(TYPE, SHAPE, ACCESS) \ - else if(as<TYPE>(type)) do { \ - return ACCESS; \ - } while(0) - - CASE(HLSLStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_READ); - CASE(HLSLRWStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_READ_WRITE); - CASE(HLSLRasterizerOrderedStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_RASTER_ORDERED); - CASE(HLSLAppendStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_APPEND); - CASE(HLSLConsumeStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_CONSUME); - CASE(HLSLByteAddressBufferType, SLANG_BYTE_ADDRESS_BUFFER, SLANG_RESOURCE_ACCESS_READ); - CASE(HLSLRWByteAddressBufferType, SLANG_BYTE_ADDRESS_BUFFER, SLANG_RESOURCE_ACCESS_READ_WRITE); - CASE(HLSLRasterizerOrderedByteAddressBufferType, SLANG_BYTE_ADDRESS_BUFFER, SLANG_RESOURCE_ACCESS_RASTER_ORDERED); - CASE(UntypedBufferResourceType, SLANG_BYTE_ADDRESS_BUFFER, SLANG_RESOURCE_ACCESS_READ); - - // This isn't entirely accurate, but I can live with it for now - CASE(GLSLShaderStorageBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_READ_WRITE); -#undef CASE - - return SLANG_RESOURCE_ACCESS_NONE; -} - -SLANG_API char const* spReflectionType_GetName(SlangReflectionType* inType) -{ - auto type = convert(inType); - - if( auto declRefType = as<DeclRefType>(type) ) - { - auto declRef = declRefType->declRef; - - // Don't return a name for auto-generated anonymous types - // that represent `cbuffer` members, etc. - auto decl = declRef.getDecl(); - if(decl->hasModifier<ImplicitParameterGroupElementTypeModifier>()) - return nullptr; - - return getText(declRef.getName()).begin(); - } - - return nullptr; -} - -SLANG_API SlangReflectionType * spReflection_FindTypeByName(SlangReflection * reflection, char const * name) -{ - auto programLayout = convert(reflection); - auto program = programLayout->getProgram(); - - // TODO: We should extend this API to support getting error messages - // when type lookup fails. - // - Slang::DiagnosticSink sink( - programLayout->getTargetReq()->getLinkage()->getSourceManager()); - - try - { - Type* result = program->getTypeFromString(name, &sink); - return (SlangReflectionType*)result; - } - catch( ... ) - { - return nullptr; - } -} - -SLANG_API SlangReflectionTypeLayout* spReflection_GetTypeLayout( - SlangReflection* reflection, - SlangReflectionType* inType, - SlangLayoutRules /*rules*/) -{ - auto context = convert(reflection); - auto type = convert(inType); - auto targetReq = context->getTargetReq(); - - auto typeLayout = targetReq->getTypeLayout(type); - return convert(typeLayout); -} - -SLANG_API SlangReflectionType* spReflectionType_GetResourceResultType(SlangReflectionType* inType) -{ - auto type = convert(inType); - if(!type) return nullptr; - - while(auto arrayType = as<ArrayExpressionType>(type)) - { - type = arrayType->baseType; - } - - if (auto textureType = as<TextureTypeBase>(type)) - { - return convert(textureType->elementType); - } - - // TODO: need a better way to handle this stuff... -#define CASE(TYPE, SHAPE, ACCESS) \ - else if(as<TYPE>(type)) do { \ - return convert(as<TYPE>(type)->elementType); \ - } while(0) - - // TODO: structured buffer needs to expose type layout! - - CASE(HLSLStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_READ); - CASE(HLSLRWStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_READ_WRITE); - CASE(HLSLRasterizerOrderedStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_RASTER_ORDERED); - CASE(HLSLAppendStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_APPEND); - CASE(HLSLConsumeStructuredBufferType, SLANG_STRUCTURED_BUFFER, SLANG_RESOURCE_ACCESS_CONSUME); -#undef CASE - - return nullptr; -} - -// type Layout Reflection - -SLANG_API SlangReflectionType* spReflectionTypeLayout_GetType(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return nullptr; - - return (SlangReflectionType*) typeLayout->type; -} - -SLANG_API SlangTypeKind spReflectionTypeLayout_getKind(SlangReflectionTypeLayout* inTypeLayout) -{ - if(!inTypeLayout) return SLANG_TYPE_KIND_NONE; - - if( auto type = spReflectionTypeLayout_GetType(inTypeLayout) ) - { - return spReflectionType_GetKind(type); - } - - auto typeLayout = convert(inTypeLayout); - if( as<StructTypeLayout>(typeLayout) ) - { - return SLANG_TYPE_KIND_STRUCT; - } - else if( as<ParameterGroupTypeLayout>(typeLayout) ) - { - return SLANG_TYPE_KIND_CONSTANT_BUFFER; - } - - return SLANG_TYPE_KIND_NONE; -} - -namespace -{ - static size_t getReflectionSize(LayoutSize size) - { - if(size.isFinite()) - return size.getFiniteValue(); - - return SLANG_UNBOUNDED_SIZE; - } -} - -SLANG_API size_t spReflectionTypeLayout_GetSize(SlangReflectionTypeLayout* inTypeLayout, SlangParameterCategory category) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto info = typeLayout->FindResourceInfo(LayoutResourceKind(category)); - if(!info) return 0; - - return getReflectionSize(info->count); -} - -SLANG_API int32_t spReflectionTypeLayout_getAlignment(SlangReflectionTypeLayout* inTypeLayout, SlangParameterCategory category) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - if( category == SLANG_PARAMETER_CATEGORY_UNIFORM ) - { - return int32_t(typeLayout->uniformAlignment); - } - else - { - return 1; - } -} - -SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetFieldByIndex(SlangReflectionTypeLayout* inTypeLayout, unsigned index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return nullptr; - - if(auto structTypeLayout = as<StructTypeLayout>(typeLayout)) - { - return (SlangReflectionVariableLayout*) structTypeLayout->fields[index].Ptr(); - } - - return nullptr; -} - -SLANG_API SlangInt spReflectionTypeLayout_findFieldIndexByName(SlangReflectionTypeLayout* inTypeLayout, const char* nameBegin, const char* nameEnd) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return -1; - - UnownedStringSlice name = nameEnd != nullptr ? UnownedStringSlice(nameBegin, nameEnd) : UnownedTerminatedStringSlice(nameBegin); - - if(auto structTypeLayout = as<StructTypeLayout>(typeLayout)) - { - Index fieldCount = structTypeLayout->fields.getCount(); - for(Index f = 0; f < fieldCount; ++f) - { - auto field = structTypeLayout->fields[f]; - if(getReflectionName(field->varDecl)->text.getUnownedSlice() == name) - return f; - } - } - - return -1; -} - -SLANG_API size_t spReflectionTypeLayout_GetElementStride(SlangReflectionTypeLayout* inTypeLayout, SlangParameterCategory category) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - if( auto arrayTypeLayout = as<ArrayTypeLayout>(typeLayout)) - { - switch (category) - { - // We store the stride explicitly for the uniform case - case SLANG_PARAMETER_CATEGORY_UNIFORM: - return arrayTypeLayout->uniformStride; - - // For most other cases (resource registers), the "stride" - // of an array is simply the number of resources (if any) - // consumed by its element type. - default: - { - auto elementTypeLayout = arrayTypeLayout->elementTypeLayout; - auto info = elementTypeLayout->FindResourceInfo(LayoutResourceKind(category)); - if(!info) return 0; - return getReflectionSize(info->count); - } - - // An important special case, though, is Vulkan descriptor-table slots, - // where an entire array will use a single `binding`, so that the - // effective stride is zero: - case SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT: - return 0; - } - } - - return 0; -} - -SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_GetElementTypeLayout(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return nullptr; - - if( auto arrayTypeLayout = as<ArrayTypeLayout>(typeLayout)) - { - return (SlangReflectionTypeLayout*) arrayTypeLayout->elementTypeLayout.Ptr(); - } - else if( auto constantBufferTypeLayout = as<ParameterGroupTypeLayout>(typeLayout)) - { - return convert(constantBufferTypeLayout->offsetElementTypeLayout.Ptr()); - } - else if( auto structuredBufferTypeLayout = as<StructuredBufferTypeLayout>(typeLayout)) - { - return convert(structuredBufferTypeLayout->elementTypeLayout.Ptr()); - } - else if( auto specializedTypeLayout = as<ExistentialSpecializedTypeLayout>(typeLayout) ) - { - return convert(specializedTypeLayout->baseTypeLayout.Ptr()); - } - - return nullptr; -} - -SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetElementVarLayout(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return nullptr; - - if( auto parameterGroupTypeLayout = as<ParameterGroupTypeLayout>(typeLayout)) - { - return convert(parameterGroupTypeLayout->elementVarLayout.Ptr()); - } - - return nullptr; -} - -SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getContainerVarLayout(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return nullptr; - - if( auto parameterGroupTypeLayout = as<ParameterGroupTypeLayout>(typeLayout)) - { - return convert(parameterGroupTypeLayout->containerVarLayout.Ptr()); - } - - return nullptr; -} - -static SlangParameterCategory getParameterCategory( - LayoutResourceKind kind) -{ - return SlangParameterCategory(kind); -} - -static SlangParameterCategory getParameterCategory( - TypeLayout* typeLayout) -{ - auto resourceInfoCount = typeLayout->resourceInfos.getCount(); - if(resourceInfoCount == 1) - { - return getParameterCategory(typeLayout->resourceInfos[0].kind); - } - else if(resourceInfoCount == 0) - { - // TODO: can this ever happen? - return SLANG_PARAMETER_CATEGORY_NONE; - } - return SLANG_PARAMETER_CATEGORY_MIXED; -} - -SLANG_API SlangParameterCategory spReflectionTypeLayout_GetParameterCategory(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return SLANG_PARAMETER_CATEGORY_NONE; - - return getParameterCategory(typeLayout); -} - -SLANG_API unsigned spReflectionTypeLayout_GetCategoryCount(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - return (unsigned) typeLayout->resourceInfos.getCount(); -} - -SLANG_API SlangParameterCategory spReflectionTypeLayout_GetCategoryByIndex(SlangReflectionTypeLayout* inTypeLayout, unsigned index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return SLANG_PARAMETER_CATEGORY_NONE; - - return typeLayout->resourceInfos[index].kind; -} - -SLANG_API SlangMatrixLayoutMode spReflectionTypeLayout_GetMatrixLayoutMode(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return SLANG_MATRIX_LAYOUT_MODE_UNKNOWN; - - if( auto matrixLayout = as<MatrixTypeLayout>(typeLayout) ) - { - return matrixLayout->mode; - } - else - { - return SLANG_MATRIX_LAYOUT_MODE_UNKNOWN; - } - -} - -SLANG_API int spReflectionTypeLayout_getGenericParamIndex(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return -1; - - if(auto genericParamTypeLayout = as<GenericParamTypeLayout>(typeLayout)) - { - return (int) genericParamTypeLayout->paramIndex; - } - else - { - return -1; - } -} - -SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getPendingDataTypeLayout(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return nullptr; - - auto pendingDataTypeLayout = typeLayout->pendingDataTypeLayout.Ptr(); - return convert(pendingDataTypeLayout); -} - -SLANG_API SlangReflectionVariableLayout* spReflectionVariableLayout_getPendingDataLayout(SlangReflectionVariableLayout* inVarLayout) -{ - auto varLayout = convert(inVarLayout); - if(!varLayout) return nullptr; - - auto pendingDataLayout = varLayout->pendingVarLayout.Ptr(); - return convert(pendingDataLayout); -} - -SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getSpecializedTypePendingDataVarLayout(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return nullptr; - - if( auto specializedTypeLayout = as<ExistentialSpecializedTypeLayout>(typeLayout) ) - { - auto pendingDataVarLayout = specializedTypeLayout->pendingDataVarLayout.Ptr(); - return convert(pendingDataVarLayout); - } - else - { - return nullptr; - } -} - -namespace Slang -{ - struct BindingRangePathLink - { - BindingRangePathLink( - BindingRangePathLink* parent, - VarLayout* var) - : parent(parent) - , var(var) - {} - - BindingRangePathLink* parent; - VarLayout* var; - }; - - - Int _calcIndexOffset(BindingRangePathLink* path, LayoutResourceKind kind) - { - Int result = 0; - for( auto link = path; link; link = link->parent ) - { - if( auto resInfo = link->var->FindResourceInfo(kind) ) - { - result += resInfo->index; - } - } - return result; - } - - Int _calcSpaceOffset(BindingRangePathLink* path, LayoutResourceKind kind) - { - Int result = 0; - for( auto link = path; link; link = link->parent ) - { - if( auto resInfo = link->var->FindResourceInfo(kind) ) - { - result += resInfo->space; - } - } - return result; - } - - SlangBindingType _calcResourceBindingType( - Type* type) - { - if( auto resourceType = as<ResourceType>(type) ) - { - auto shape = resourceType->getBaseShape(); - - auto access = resourceType->getAccess(); - auto mutableFlag = access != SLANG_RESOURCE_ACCESS_READ ? SLANG_BINDING_TYPE_MUTABLE_FLAG : 0; - - switch( shape ) - { - default: - return SLANG_BINDING_TYPE_TEXTURE | mutableFlag; - - case SLANG_TEXTURE_BUFFER: - return SLANG_BINDING_TYPE_TYPED_BUFFER | mutableFlag; - } - - } - else if( auto structuredBufferType = as<HLSLStructuredBufferTypeBase>(type) ) - { - if( as<HLSLStructuredBufferType>(type) ) - { - return SLANG_BINDING_TYPE_RAW_BUFFER; - } - else - { - return SLANG_BINDING_TYPE_MUTABLE_RAW_BUFFER; - } - } - else if( as<RaytracingAccelerationStructureType>(type) ) - { - return SLANG_BINDING_TYPE_RAY_TRACTING_ACCELERATION_STRUCTURE; - } - else if( auto untypedBufferType = as<UntypedBufferResourceType>(type) ) - { - if( as<HLSLByteAddressBufferType>(type) ) - { - return SLANG_BINDING_TYPE_RAW_BUFFER; - } - else - { - return SLANG_BINDING_TYPE_MUTABLE_RAW_BUFFER; - } - } - else if( as<ConstantBufferType>(type) ) - { - return SLANG_BINDING_TYPE_CONSTANT_BUFFER; - } - else - { - SLANG_UNEXPECTED("unhandled resource binding type"); - } - } - - SlangBindingType _calcResourceBindingType( - TypeLayout* typeLayout) - { - if(auto type = typeLayout->getType()) - { - return _calcResourceBindingType(type); - } - - if(as<ParameterGroupTypeLayout>(typeLayout)) - { - return SLANG_BINDING_TYPE_CONSTANT_BUFFER; - } - else - { - SLANG_UNEXPECTED("unhandled resource binding type"); - } - } - - - SlangBindingType _calcBindingType( - Slang::TypeLayout* typeLayout, - LayoutResourceKind kind) - { - switch( kind ) - { - default: - return SLANG_BINDING_TYPE_UNKNOWN; - - // Some cases of `LayoutResourceKind` can be mapped - // directly to a `BindingType` because there is only - // one case of types that have that resource kind. - - #define CASE(FROM, TO) \ - case LayoutResourceKind::FROM: return SLANG_BINDING_TYPE_##TO - - CASE(ConstantBuffer, CONSTANT_BUFFER); - CASE(SamplerState, SAMPLER); - CASE(VaryingInput, VARYING_INPUT); - CASE(VaryingOutput, VARYING_OUTPUT); - CASE(ExistentialObjectParam, EXISTENTIAL_VALUE); - CASE(PushConstantBuffer, PUSH_CONSTANT); - // TODO: register space - - #undef CASE - - case LayoutResourceKind::ShaderResource: - case LayoutResourceKind::UnorderedAccess: - case LayoutResourceKind::DescriptorTableSlot: - return _calcResourceBindingType(typeLayout); - } - } - - static DeclRefType* asInterfaceType(Type* type) - { - if(auto declRefType = as<DeclRefType>(type)) - { - if(declRefType->declRef.as<InterfaceDecl>()) - { - return declRefType; - } - } - return nullptr; - } - - struct ExtendedTypeLayoutContext - { - TypeLayout* m_typeLayout; - TypeLayout::ExtendedInfo* m_extendedInfo; - - Dictionary<Int, Int> m_mapSpaceToDescriptorSetIndex; - - Int _findOrAddDescriptorSet(Int space) - { - Int index = 0; - if(m_mapSpaceToDescriptorSetIndex.TryGetValue(space, index)) - return index; - - index = m_extendedInfo->m_descriptorSets.getCount(); - m_mapSpaceToDescriptorSetIndex.Add(space, index); - - RefPtr<TypeLayout::ExtendedInfo::DescriptorSetInfo> descriptorSet = new TypeLayout::ExtendedInfo::DescriptorSetInfo(); - m_extendedInfo->m_descriptorSets.add(descriptorSet); - - return index; - } - - void addRangesRec(TypeLayout* typeLayout, BindingRangePathLink* path, LayoutSize multiplier) - { - if( auto structTypeLayout = as<StructTypeLayout>(typeLayout) ) - { - // For a structure type, we need to recursively - // add the ranges for each field. - // - // Along the way we will make sure to properly update - // the offset information on the fields so that - // they properly show their binding-range offset - // within the parent type. - // - Index structBindingRangeIndex = m_extendedInfo->m_bindingRanges.getCount(); - for( auto fieldVarLayout : structTypeLayout->fields ) - { - Index fieldBindingRangeIndex = m_extendedInfo->m_bindingRanges.getCount(); - fieldVarLayout->bindingRangeOffset = fieldBindingRangeIndex - structBindingRangeIndex; - - auto fieldTypeLayout = fieldVarLayout->getTypeLayout(); - - - BindingRangePathLink fieldLink(path, fieldVarLayout); - addRangesRec(fieldTypeLayout, &fieldLink, multiplier); - } - return; - } - else if( auto arrayTypeLayout = as<ArrayTypeLayout>(typeLayout) ) - { - // For an array, we need to recursively add the - // element type of the array, but with an adjusted - // `multiplier` to account for the element count. - // - auto elementTypeLayout = arrayTypeLayout->elementTypeLayout; - LayoutSize elementCount = LayoutSize::infinite(); - if( auto arrayType = as<ArrayExpressionType>(arrayTypeLayout->type) ) - { - if( auto elementCountVal = arrayType->arrayLength ) - { - elementCount = LayoutSize::RawValue(getIntVal(elementCountVal)); - } - } - addRangesRec(elementTypeLayout, path, multiplier * elementCount); - return; - } - else if( auto parameterGroupTypeLayout = as<ParameterGroupTypeLayout>(typeLayout)) - { - // A parameter group (whether a `ConstantBuffer<>` or `ParameterBlock<>` - // introduces a separately-allocated "sub-object" in the application's - // layout for shader objects. - // - // We will represent the parameter group with a single sub-object - // binding range (and an associated sub-object range). - // - // We start out by looking at the resources consumed by the parameter group - // itself, to determine what kind of binding range to report it as. - // - Index bindingRangeIndex = m_extendedInfo->m_bindingRanges.getCount(); - SlangBindingType bindingType = SLANG_BINDING_TYPE_CONSTANT_BUFFER; - Index spaceOffset = -1; - LayoutResourceKind kind = LayoutResourceKind::None; - for(auto& resInfo : parameterGroupTypeLayout->resourceInfos) - { - kind = resInfo.kind; - switch(kind) - { - default: - continue; - - case LayoutResourceKind::ConstantBuffer: - case LayoutResourceKind::PushConstantBuffer: - case LayoutResourceKind::RegisterSpace: - case LayoutResourceKind::DescriptorTableSlot: - break; - } - - bindingType = _calcBindingType(typeLayout, kind); - spaceOffset = _calcSpaceOffset(path, kind); - break; - } - - TypeLayout::ExtendedInfo::BindingRangeInfo bindingRange; - bindingRange.leafTypeLayout = typeLayout; - bindingRange.bindingType = bindingType; - bindingRange.count = multiplier; - bindingRange.descriptorSetIndex = -1; - bindingRange.firstDescriptorRangeIndex = 0; - bindingRange.descriptorRangeCount = 0; - - if( kind == LayoutResourceKind::PushConstantBuffer ) - { - if(auto resInfo = parameterGroupTypeLayout->elementVarLayout->typeLayout->FindResourceInfo(LayoutResourceKind::Uniform)) - { - bindingRange.count *= resInfo->count; - } - } - - // Every parameter group will introduce a sub-object range, - // which will include bindings based on the type of data - // inside the sub-object. - // - TypeLayout::ExtendedInfo::SubObjectRangeInfo subObjectRange; - subObjectRange.bindingRangeIndex = bindingRangeIndex; - - // It is possible that the sub-object has descriptor ranges - // that will need to be exposed upward, into the parent. - // - if( spaceOffset != -1 ) - { - Int descriptorSetIndex = _findOrAddDescriptorSet(spaceOffset); - auto descriptorSet = m_extendedInfo->m_descriptorSets[descriptorSetIndex]; - auto firstDescriptorRangeIndex = descriptorSet->descriptorRanges.getCount(); - - // TODO: We need to recursively add descriptor ranges (but not binding - // ranges!) for anything in the element type that "leaks" into - // the surrounding context. - // - switch(kind) - { - case LayoutResourceKind::RegisterSpace: - case LayoutResourceKind::Uniform: - case LayoutResourceKind::None: - break; - - default: - { - // This means we are in the constant-buffer-like case - // (even if the user wrote `ParameterBlock<T>`), and any - // resource usage inside the element type should "leak" - // out to the parent scope. - // - // It *also* means we should add a suitable descriptor - // range if one is required for the "container" type. - // - for(auto resInfo : parameterGroupTypeLayout->containerVarLayout->typeLayout->resourceInfos) - { - switch( resInfo.kind ) - { - case LayoutResourceKind::RegisterSpace: - case LayoutResourceKind::Uniform: - continue; - - default: - break; - } - - TypeLayout::ExtendedInfo::DescriptorRangeInfo descriptorRange; - descriptorRange.kind = resInfo.kind; - descriptorRange.bindingType = _calcBindingType(typeLayout, resInfo.kind); - descriptorRange.count = multiplier; - descriptorRange.indexOffset = _calcIndexOffset(path, resInfo.kind); - - if( resInfo.kind == LayoutResourceKind::PushConstantBuffer ) - { - if(auto uniformResInfo = parameterGroupTypeLayout->elementVarLayout->typeLayout->FindResourceInfo(LayoutResourceKind::Uniform)) - { - descriptorRange.count *= uniformResInfo->count; - } - } - - descriptorSet->descriptorRanges.add(descriptorRange); - } - - // Now we need to recursively walk the element type and add all its - // descriptor ranges, so that they can be used for binding in - // the parent. - // - // We have this a bit by collecting both binding ranges and - // descriptor ranges, and then throwing away the binding ranges - // from the element type. - // - BindingRangePathLink elementPath(path, parameterGroupTypeLayout->elementVarLayout); - - Index bindingRangeCountBefore = m_extendedInfo->m_bindingRanges.getCount(); - Index subObjectRangeCountBefore = m_extendedInfo->m_subObjectRanges.getCount(); - - addRangesRec(parameterGroupTypeLayout->elementVarLayout->typeLayout, &elementPath, multiplier); - - m_extendedInfo->m_bindingRanges.setCount(bindingRangeCountBefore); - m_extendedInfo->m_subObjectRanges.setCount(subObjectRangeCountBefore); - } - break; - } - - auto descriptorRangeCount = descriptorSet->descriptorRanges.getCount() - firstDescriptorRangeIndex; - bindingRange.descriptorSetIndex = descriptorSetIndex; - bindingRange.firstDescriptorRangeIndex = firstDescriptorRangeIndex; - bindingRange.descriptorRangeCount = descriptorRangeCount; - } - - m_extendedInfo->m_bindingRanges.add(bindingRange); - m_extendedInfo->m_subObjectRanges.add(subObjectRange); - return; - } - else if(asInterfaceType(typeLayout->type)) - { - // An `interface` type should introduce a sub-object range, - // with no concrete descriptor ranges to store its value - // (since we don't know until runtime what type of - // value will be plugged in). - // - - LayoutResourceKind kind = LayoutResourceKind::ExistentialObjectParam; - auto count = multiplier; - auto spaceOffset = _calcSpaceOffset(path, kind); - - Int descriptorSetIndex = _findOrAddDescriptorSet(spaceOffset); - auto descriptorSet = m_extendedInfo->m_descriptorSets[descriptorSetIndex]; - - TypeLayout::ExtendedInfo::BindingRangeInfo bindingRange; - bindingRange.leafTypeLayout = typeLayout; - bindingRange.bindingType = SLANG_BINDING_TYPE_EXISTENTIAL_VALUE; - bindingRange.count = multiplier; - bindingRange.descriptorSetIndex = descriptorSetIndex; - bindingRange.firstDescriptorRangeIndex = descriptorSet->descriptorRanges.getCount(); - bindingRange.descriptorRangeCount = 1; - - TypeLayout::ExtendedInfo::SubObjectRangeInfo subObjectRange; - subObjectRange.bindingRangeIndex = m_extendedInfo->m_bindingRanges.getCount(); - - m_extendedInfo->m_bindingRanges.add(bindingRange); - m_extendedInfo->m_subObjectRanges.add(subObjectRange); - } - // TODO: We need to handle `interface` types here, because they are - // another case that introduces a "sub-object" for the purposes of - // application-side allocation. - // - // TODO: There are a few cases of "leaf" fields that might - // still result in multiple descriptors (or at least multiple - // `LayoutResourceKind`s) depending on the target. - // - // For eample, combined texture-sampler types should be treated - // as "leaf" fields for this code (since a portable engine would - // need to abstract over them), but would map to two descriptors - // on targets that don't actually support combining them. - else - { - Int resourceKindCount = typeLayout->resourceInfos.getCount(); - if(resourceKindCount == 0) - { - // This is a field that consumes no resources, and as - // such does not need a binding or descriptor ranges - // allocated for it. - // - return; - } - else if(resourceKindCount == 1) - { - auto& resInfo = typeLayout->resourceInfos[0]; - LayoutResourceKind kind = resInfo.kind; - - if(kind == LayoutResourceKind::Uniform) - { - // We do not consider uniform resource usage - // in the ranges we compute. - // - // TODO: We may need to revise that rule for types that - // represent resources, even when one or more targets - // map those resource types to ordinary/uniform data. - // - return; - } - - // This leaf field will map to a single binding range and, - // if it is appropriate, a single descriptor range. - // - auto bindingType = _calcBindingType(typeLayout, kind); - auto count = resInfo.count * multiplier; - auto indexOffset = _calcIndexOffset(path, kind); - auto spaceOffset = _calcSpaceOffset(path, kind); - - Int descriptorSetIndex = -1; - Int firstDescriptorIndex = 0; - RefPtr<TypeLayout::ExtendedInfo::DescriptorSetInfo> descriptorSet; - switch( kind ) - { - case LayoutResourceKind::RegisterSpace: - case LayoutResourceKind::VaryingInput: - case LayoutResourceKind::VaryingOutput: - case LayoutResourceKind::HitAttributes: - case LayoutResourceKind::RayPayload: - // Resource kinds that represent "varying" input/output - // do not manifest as entries in API descriptor tables. - // - // TODO: Neither do root constants, if we are being - // precise. This API really needs to carefully match - // the semantics of the target platform/API in terms - // of what things are descriptor-bound and which are - // not, so that a user can easily allocate the platform-specific - // descriptor sets using this info. - // - // (That said, we are purposefully *not* breaking apart - // samplers and SRV/UAV/CBV stuff for our D3D reflection - // of descriptor sets. It seems like the policy here - // really requires careful thought) - // - // TODO: Maybe the best answer is to leave decomposition - // of stuff into descriptor sets up to the application - // layer? This is especially true if a common case would - // be an application that doesn't support arbitrary manual - // binding of parameters to register/spaces. - // - break; - - default: - { - TypeLayout::ExtendedInfo::DescriptorRangeInfo descriptorRange; - descriptorRange.kind = kind; - descriptorRange.bindingType = bindingType; - descriptorRange.count = count; - descriptorRange.indexOffset = indexOffset; - - descriptorSetIndex = _findOrAddDescriptorSet(spaceOffset); - descriptorSet = m_extendedInfo->m_descriptorSets[descriptorSetIndex]; - - firstDescriptorIndex = descriptorSet->descriptorRanges.getCount(); - descriptorSet->descriptorRanges.add(descriptorRange); - } - break; - } - - - TypeLayout::ExtendedInfo::BindingRangeInfo bindingRange; - bindingRange.leafTypeLayout = typeLayout; - bindingRange.bindingType = _calcBindingType(typeLayout, kind); - bindingRange.count = count; - bindingRange.descriptorSetIndex = descriptorSetIndex; - bindingRange.firstDescriptorRangeIndex = firstDescriptorIndex; - bindingRange.descriptorRangeCount = 1; - - m_extendedInfo->m_bindingRanges.add(bindingRange); - } - else - { - // This type appears to be one that consumes multiple - // resource kinds, but was not handled by any of - // the special-case logic above. In such a case we - // are in trouble. - // - return; - } - } - } - }; - - TypeLayout::ExtendedInfo* getExtendedTypeLayout(TypeLayout* typeLayout) - { - if( !typeLayout->m_extendedInfo ) - { - RefPtr<TypeLayout::ExtendedInfo> extendedInfo = new TypeLayout::ExtendedInfo; - - ExtendedTypeLayoutContext context; - context.m_typeLayout = typeLayout; - context.m_extendedInfo = extendedInfo; - - context.addRangesRec(typeLayout, nullptr, 1); - - typeLayout->m_extendedInfo = extendedInfo; - } - return typeLayout->m_extendedInfo; - } -} - -SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeCount(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - return extTypeLayout->m_bindingRanges.getCount(); -} - -SLANG_API SlangBindingType spReflectionTypeLayout_getBindingRangeType(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return SLANG_BINDING_TYPE_UNKNOWN; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - if(index < 0) return 0; - if(index >= extTypeLayout->m_bindingRanges.getCount()) return 0; - auto& bindingRange = extTypeLayout->m_bindingRanges[index]; - - return bindingRange.bindingType; -} - -SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeBindingCount(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - if(index < 0) return 0; - if(index >= extTypeLayout->m_bindingRanges.getCount()) return 0; - auto& bindingRange = extTypeLayout->m_bindingRanges[index]; - - auto count = bindingRange.count; - return count.isFinite() ? SlangInt(count.getFiniteValue()) : -1; -} - -#if 0 -SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeIndexOffset(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - return Slang::_findBindingRange(typeLayout, index).indexOffset; -} - -SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeSpaceOffset(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - return Slang::_findBindingRange(typeLayout, index).spaceOffset; -} -#endif - -SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getBindingRangeLeafTypeLayout(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - if(index < 0) return 0; - if(index >= extTypeLayout->m_bindingRanges.getCount()) return 0; - auto& bindingRange = extTypeLayout->m_bindingRanges[index]; - - return convert(bindingRange.leafTypeLayout); -} - -SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeDescriptorSetIndex(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - if(index < 0) return 0; - if(index >= extTypeLayout->m_bindingRanges.getCount()) return 0; - auto& bindingRange = extTypeLayout->m_bindingRanges[index]; - - return bindingRange.descriptorSetIndex; -} - -SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeFirstDescriptorRangeIndex(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - if(index < 0) return 0; - if(index >= extTypeLayout->m_bindingRanges.getCount()) return 0; - auto& bindingRange = extTypeLayout->m_bindingRanges[index]; - - return bindingRange.firstDescriptorRangeIndex; -} - -SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetCount(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - - return extTypeLayout->m_descriptorSets.getCount(); -} - -SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetSpaceOffset(SlangReflectionTypeLayout* inTypeLayout, SlangInt setIndex) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - - if(setIndex < 0) return 0; - if(setIndex >= extTypeLayout->m_descriptorSets.getCount()) return 0; - auto descriptorSet = extTypeLayout->m_descriptorSets[setIndex]; - - return descriptorSet->spaceOffset; -} - -SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeCount(SlangReflectionTypeLayout* inTypeLayout, SlangInt setIndex) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - - if(setIndex < 0) return 0; - if(setIndex >= extTypeLayout->m_descriptorSets.getCount()) return 0; - auto descriptorSet = extTypeLayout->m_descriptorSets[setIndex]; - - return descriptorSet->descriptorRanges.getCount(); -} - -SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeIndexOffset(SlangReflectionTypeLayout* inTypeLayout, SlangInt setIndex, SlangInt rangeIndex) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - - if(setIndex < 0) return 0; - if(setIndex >= extTypeLayout->m_descriptorSets.getCount()) return 0; - auto descriptorSet = extTypeLayout->m_descriptorSets[setIndex]; - - if(rangeIndex < 0) return 0; - if(rangeIndex >= descriptorSet->descriptorRanges.getCount()) return 0; - auto& range = descriptorSet->descriptorRanges[rangeIndex]; - - return range.indexOffset; -} - -SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeDescriptorCount(SlangReflectionTypeLayout* inTypeLayout, SlangInt setIndex, SlangInt rangeIndex) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - - if(setIndex < 0) return 0; - if(setIndex >= extTypeLayout->m_descriptorSets.getCount()) return 0; - auto descriptorSet = extTypeLayout->m_descriptorSets[setIndex]; - - if(rangeIndex < 0) return 0; - if(rangeIndex >= descriptorSet->descriptorRanges.getCount()) return 0; - auto& range = descriptorSet->descriptorRanges[rangeIndex]; - - auto count = range.count; - return count.isFinite() ? count.getFiniteValue() : -1; -} - -SLANG_API SlangBindingType spReflectionTypeLayout_getDescriptorSetDescriptorRangeType(SlangReflectionTypeLayout* inTypeLayout, SlangInt setIndex, SlangInt rangeIndex) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - - if(setIndex < 0) return 0; - if(setIndex >= extTypeLayout->m_descriptorSets.getCount()) return 0; - auto descriptorSet = extTypeLayout->m_descriptorSets[setIndex]; - - if(rangeIndex < 0) return 0; - if(rangeIndex >= descriptorSet->descriptorRanges.getCount()) return 0; - auto& range = descriptorSet->descriptorRanges[rangeIndex]; - - return range.bindingType; -} - -SLANG_API SlangParameterCategory spReflectionTypeLayout_getDescriptorSetDescriptorRangeCategory(SlangReflectionTypeLayout* inTypeLayout, SlangInt setIndex, SlangInt rangeIndex) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - - if(setIndex < 0) return 0; - if(setIndex >= extTypeLayout->m_descriptorSets.getCount()) return 0; - auto descriptorSet = extTypeLayout->m_descriptorSets[setIndex]; - - if(rangeIndex < 0) return 0; - if(rangeIndex >= descriptorSet->descriptorRanges.getCount()) return 0; - auto& range = descriptorSet->descriptorRanges[rangeIndex]; - - return SlangParameterCategory(range.kind); -} - -SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeCount(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - - return extTypeLayout->m_subObjectRanges.getCount(); -} - -SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex(SlangReflectionTypeLayout* inTypeLayout, SlangInt subObjectRangeIndex) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); - - if(subObjectRangeIndex < 0) return 0; - if(subObjectRangeIndex >= extTypeLayout->m_subObjectRanges.getCount()) return 0; - - return extTypeLayout->m_subObjectRanges[subObjectRangeIndex].bindingRangeIndex; -} - - -#if 0 -SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeSubObjectRangeIndex(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - return Slang::_findBindingRange(typeLayout, index).subObjectRangeIndex; -} -#endif - - -SLANG_API SlangInt spReflectionTypeLayout_getFieldBindingRangeOffset(SlangReflectionTypeLayout* inTypeLayout, SlangInt fieldIndex) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - if( auto structTypeLayout = as<StructTypeLayout>(typeLayout) ) - { - getExtendedTypeLayout(structTypeLayout); - - return structTypeLayout->fields[fieldIndex]->bindingRangeOffset; - } - - return 0; -} - -#if 0 -SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeCount(SlangReflectionTypeLayout* inTypeLayout) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - return Slang::_calcSubObjectRangeCount(typeLayout); -} - -SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeObjectCount(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto count = Slang::_findSubObjectRange(typeLayout, index).count; - return count.isFinite() ? SlangInt(count.getFiniteValue()) : -1; -} - -SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - return Slang::_findSubObjectRange(typeLayout, index).bindingRangeIndex; -} - - -SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getSubObjectRangeTypeLayout(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - return convert(Slang::_findSubObjectRange(typeLayout, index).leafTypeLayout); -} - -SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeCount(SlangReflectionTypeLayout* inTypeLayout, SlangInt subObjectRangeIndex) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto subObjectRange = Slang::_findSubObjectRange(typeLayout, subObjectRangeIndex); - return Slang::_getSubObjectDescriptorRangeCount(subObjectRange); -} - -SLANG_API SlangBindingType spReflectionTypeLayout_getSubObjectRangeDescriptorRangeBindingType(SlangReflectionTypeLayout* inTypeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto subObjectRange = Slang::_findSubObjectRange(typeLayout, subObjectRangeIndex); - return Slang::_getSubObjectDescriptorRange(subObjectRange, bindingRangeIndexInSubObject).bindingType; -} - -SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeBindingCount(SlangReflectionTypeLayout* inTypeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto subObjectRange = Slang::_findSubObjectRange(typeLayout, subObjectRangeIndex); - auto count = Slang::_getSubObjectDescriptorRange(subObjectRange, bindingRangeIndexInSubObject).count; - return count.isFinite() ? count.getFiniteValue() : -1; -} - -SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeIndexOffset(SlangReflectionTypeLayout* inTypeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto subObjectRange = Slang::_findSubObjectRange(typeLayout, subObjectRangeIndex); - return Slang::_getSubObjectDescriptorRange(subObjectRange, bindingRangeIndexInSubObject).indexOffset; -} - -SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeSpaceOffset(SlangReflectionTypeLayout* inTypeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject) -{ - auto typeLayout = convert(inTypeLayout); - if(!typeLayout) return 0; - - auto subObjectRange = Slang::_findSubObjectRange(typeLayout, subObjectRangeIndex); - return Slang::_getSubObjectDescriptorRange(subObjectRange, bindingRangeIndexInSubObject).spaceOffset; -} -#endif - -// Variable Reflection - -SLANG_API char const* spReflectionVariable_GetName(SlangReflectionVariable* inVar) -{ - auto var = convert(inVar); - if(!var) return nullptr; - - // If the variable is one that has an "external" name that is supposed - // to be exposed for reflection, then report it here - if(auto reflectionNameMod = var->findModifier<ParameterGroupReflectionName>()) - return getText(reflectionNameMod->nameAndLoc.name).getBuffer(); - - return getText(var->getName()).getBuffer(); -} - -SLANG_API SlangReflectionType* spReflectionVariable_GetType(SlangReflectionVariable* inVar) -{ - auto var = convert(inVar); - if(!var) return nullptr; - - return convert(var->getType()); -} - -SLANG_API SlangReflectionModifier* spReflectionVariable_FindModifier(SlangReflectionVariable* inVar, SlangModifierID modifierID) -{ - auto var = convert(inVar); - if(!var) return nullptr; - - Modifier* modifier = nullptr; - switch( modifierID ) - { - case SLANG_MODIFIER_SHARED: - modifier = var->findModifier<HLSLEffectSharedModifier>(); - break; - - default: - return nullptr; - } - - return (SlangReflectionModifier*) modifier; -} - -SLANG_API unsigned int spReflectionVariable_GetUserAttributeCount(SlangReflectionVariable* inVar) -{ - auto varDecl = convert(inVar); - if (!varDecl) return 0; - return getUserAttributeCount(varDecl); -} -SLANG_API SlangReflectionUserAttribute* spReflectionVariable_GetUserAttribute(SlangReflectionVariable* inVar, unsigned int index) -{ - auto varDecl = convert(inVar); - if (!varDecl) return 0; - return getUserAttributeByIndex(varDecl, index); -} -SLANG_API SlangReflectionUserAttribute* spReflectionVariable_FindUserAttributeByName(SlangReflectionVariable* inVar, SlangSession* session, char const* name) -{ - auto varDecl = convert(inVar); - if (!varDecl) return 0; - return findUserAttributeByName(convert(session), varDecl, name); -} - -// Variable Layout Reflection - -SLANG_API SlangReflectionVariable* spReflectionVariableLayout_GetVariable(SlangReflectionVariableLayout* inVarLayout) -{ - auto varLayout = convert(inVarLayout); - if(!varLayout) return nullptr; - - return convert(varLayout->varDecl.getDecl()); -} - -SLANG_API SlangReflectionTypeLayout* spReflectionVariableLayout_GetTypeLayout(SlangReflectionVariableLayout* inVarLayout) -{ - auto varLayout = convert(inVarLayout); - if(!varLayout) return nullptr; - - return convert(varLayout->getTypeLayout()); -} - -namespace Slang -{ - // Attempt "do what I mean" remapping from the parameter category the user asked about, - // over to a parameter category that they might have meant. - static SlangParameterCategory maybeRemapParameterCategory( - TypeLayout* typeLayout, - SlangParameterCategory category) - { - // Do we have an entry for the category they asked about? Then use that. - if (typeLayout->FindResourceInfo(LayoutResourceKind(category))) - return category; - - // Do we have an entry for the `DescriptorTableSlot` category? - if (typeLayout->FindResourceInfo(LayoutResourceKind::DescriptorTableSlot)) - { - // Is the category they were asking about one that makes sense for the type - // of this variable? - Type* type = typeLayout->getType(); - while (auto arrayType = as<ArrayExpressionType>(type)) - type = arrayType->baseType; - switch (spReflectionType_GetKind(convert(type))) - { - case SLANG_TYPE_KIND_CONSTANT_BUFFER: - if(category == SLANG_PARAMETER_CATEGORY_CONSTANT_BUFFER) - return SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT; - break; - - case SLANG_TYPE_KIND_RESOURCE: - if(category == SLANG_PARAMETER_CATEGORY_SHADER_RESOURCE) - return SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT; - break; - - case SLANG_TYPE_KIND_SAMPLER_STATE: - if(category == SLANG_PARAMETER_CATEGORY_SAMPLER_STATE) - return SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT; - break; - - // TODO: implement more helpers here - - default: - break; - } - } - - return category; - } -} - -SLANG_API size_t spReflectionVariableLayout_GetOffset(SlangReflectionVariableLayout* inVarLayout, SlangParameterCategory category) -{ - auto varLayout = convert(inVarLayout); - if(!varLayout) return 0; - - auto info = varLayout->FindResourceInfo(LayoutResourceKind(category)); - - if (!info) - { - // No match with requested category? Try again with one they might have meant... - category = maybeRemapParameterCategory(varLayout->getTypeLayout(), category); - info = varLayout->FindResourceInfo(LayoutResourceKind(category)); - } - - if(!info) return 0; - - return info->index; -} - -SLANG_API size_t spReflectionVariableLayout_GetSpace(SlangReflectionVariableLayout* inVarLayout, SlangParameterCategory category) -{ - auto varLayout = convert(inVarLayout); - if(!varLayout) return 0; - - - auto info = varLayout->FindResourceInfo(LayoutResourceKind(category)); - if (!info) - { - // No match with requested category? Try again with one they might have meant... - category = maybeRemapParameterCategory(varLayout->getTypeLayout(), category); - info = varLayout->FindResourceInfo(LayoutResourceKind(category)); - } - - UInt space = 0; - - // First, deal with any offset applied to the specific resource kind specified - if (info) - { - space += info->space; - } - - // Note: this code used to try and take a variable with - // an offset for `LayoutResourceKind::RegisterSpace` and - // add it to the space returned, but that isn't going - // to be right in some cases. - // - // Imageine if we have: - // - // struct X { Texture2D y; } - // struct S { Texture2D t; ParmaeterBlock<X> x; } - // - // Texture2D gA; - // S gS; - // - // We expect `gS` to have an offset for `LayoutResourceKind::ShaderResourceView` - // of one (since its texture must come after `gA`), and an offset for - // `LayoutResourceKind::RegisterSpace` of one (since the default space will be - // space zero). It would be incorrect for us to imply that `gS.t` should - // be `t1, space1`, though, because the space offset of `gS` doesn't actually - // apply to `t`. - // - // For now we are punting on this issue and leaving it in the hands of the - // application to determine when a space offset from an "outer" variable should - // apply to the locations of things in an "inner" variable. - // - // There is no policy we can apply locally in this function that - // will Just Work, so the best we can do is try to not lie. - - return space; -} - -SLANG_API char const* spReflectionVariableLayout_GetSemanticName(SlangReflectionVariableLayout* inVarLayout) -{ - auto varLayout = convert(inVarLayout); - if(!varLayout) return 0; - - if (!(varLayout->flags & Slang::VarLayoutFlag::HasSemantic)) - return 0; - - return varLayout->semanticName.getBuffer(); -} - -SLANG_API size_t spReflectionVariableLayout_GetSemanticIndex(SlangReflectionVariableLayout* inVarLayout) -{ - auto varLayout = convert(inVarLayout); - if(!varLayout) return 0; - - if (!(varLayout->flags & Slang::VarLayoutFlag::HasSemantic)) - return 0; - - return varLayout->semanticIndex; -} - -SLANG_API SlangStage spReflectionVariableLayout_getStage( - SlangReflectionVariableLayout* inVarLayout) -{ - auto varLayout = convert(inVarLayout); - if(!varLayout) return SLANG_STAGE_NONE; - - // A parameter that is not a varying input or output is - // not considered to belong to a single stage. - // - // TODO: We might need to reconsider this for, e.g., entry - // point parameters, where they might be stage-specific even - // if they are uniform. - if (!varLayout->FindResourceInfo(Slang::LayoutResourceKind::VaryingInput) - && !varLayout->FindResourceInfo(Slang::LayoutResourceKind::VaryingOutput)) - { - return SLANG_STAGE_NONE; - } - - // TODO: We should find the stage for a variable layout by - // walking up the tree of layout information, until we find - // something that has a definitive stage attached to it (e.g., - // either an entry point or a GLSL translation unit). - // - // We don't currently have parent links in the reflection layout - // information, so doing that walk would be tricky right now, so - // it is easier to just bloat the representation and store yet another - // field on every variable layout. - return (SlangStage) varLayout->stage; -} - - -// Shader Parameter Reflection - -SLANG_API unsigned spReflectionParameter_GetBindingIndex(SlangReflectionParameter* inVarLayout) -{ - SlangReflectionVariableLayout* varLayout = (SlangReflectionVariableLayout*)inVarLayout; - return (unsigned) spReflectionVariableLayout_GetOffset( - varLayout, - spReflectionTypeLayout_GetParameterCategory( - spReflectionVariableLayout_GetTypeLayout(varLayout))); -} - -SLANG_API unsigned spReflectionParameter_GetBindingSpace(SlangReflectionParameter* inVarLayout) -{ - SlangReflectionVariableLayout* varLayout = (SlangReflectionVariableLayout*)inVarLayout; - return (unsigned) spReflectionVariableLayout_GetSpace( - varLayout, - spReflectionTypeLayout_GetParameterCategory( - spReflectionVariableLayout_GetTypeLayout(varLayout))); -} - -// Helpers for getting parameter count - -namespace Slang -{ - static unsigned getParameterCount(RefPtr<TypeLayout> typeLayout) - { - if(auto parameterGroupLayout = as<ParameterGroupTypeLayout>(typeLayout)) - { - typeLayout = parameterGroupLayout->offsetElementTypeLayout; - } - - if(auto structLayout = as<StructTypeLayout>(typeLayout)) - { - return (unsigned) structLayout->fields.getCount(); - } - - return 0; - } - - static VarLayout* getParameterByIndex(RefPtr<TypeLayout> typeLayout, unsigned index) - { - if(auto parameterGroupLayout = as<ParameterGroupTypeLayout>(typeLayout)) - { - typeLayout = parameterGroupLayout->offsetElementTypeLayout; - } - - if(auto structLayout = as<StructTypeLayout>(typeLayout)) - { - return structLayout->fields[index]; - } - - return 0; - } -} - -// Entry Point Reflection - -SLANG_API char const* spReflectionEntryPoint_getName( - SlangReflectionEntryPoint* inEntryPoint) -{ - auto entryPointLayout = convert(inEntryPoint); - return entryPointLayout ? getCstr(entryPointLayout->name) : nullptr; -} - -SLANG_API unsigned spReflectionEntryPoint_getParameterCount( - SlangReflectionEntryPoint* inEntryPoint) -{ - auto entryPointLayout = convert(inEntryPoint); - if(!entryPointLayout) return 0; - - return getParameterCount(entryPointLayout->parametersLayout->typeLayout); -} - -SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getParameterByIndex( - SlangReflectionEntryPoint* inEntryPoint, - unsigned index) -{ - auto entryPointLayout = convert(inEntryPoint); - if(!entryPointLayout) return 0; - - return convert(getParameterByIndex(entryPointLayout->parametersLayout->typeLayout, index)); -} - -SLANG_API SlangStage spReflectionEntryPoint_getStage(SlangReflectionEntryPoint* inEntryPoint) -{ - auto entryPointLayout = convert(inEntryPoint); - - if(!entryPointLayout) return SLANG_STAGE_NONE; - - return SlangStage(entryPointLayout->profile.getStage()); -} - -SLANG_API void spReflectionEntryPoint_getComputeThreadGroupSize( - SlangReflectionEntryPoint* inEntryPoint, - SlangUInt axisCount, - SlangUInt* outSizeAlongAxis) -{ - auto entryPointLayout = convert(inEntryPoint); - - if(!entryPointLayout) return; - if(!axisCount) return; - if(!outSizeAlongAxis) return; - - auto entryPointFunc = entryPointLayout->entryPoint; - if(!entryPointFunc) return; - - SlangUInt sizeAlongAxis[3] = { 1, 1, 1 }; - - // First look for the HLSL case, where we have an attribute attached to the entry point function - auto numThreadsAttribute = entryPointFunc.getDecl()->findModifier<NumThreadsAttribute>(); - if (numThreadsAttribute) - { - sizeAlongAxis[0] = numThreadsAttribute->x; - sizeAlongAxis[1] = numThreadsAttribute->y; - sizeAlongAxis[2] = numThreadsAttribute->z; - } - - // - - if(axisCount > 0) outSizeAlongAxis[0] = sizeAlongAxis[0]; - if(axisCount > 1) outSizeAlongAxis[1] = sizeAlongAxis[1]; - if(axisCount > 2) outSizeAlongAxis[2] = sizeAlongAxis[2]; - for( SlangUInt aa = 3; aa < axisCount; ++aa ) - { - outSizeAlongAxis[aa] = 1; - } -} - -SLANG_API int spReflectionEntryPoint_usesAnySampleRateInput( - SlangReflectionEntryPoint* inEntryPoint) -{ - auto entryPointLayout = convert(inEntryPoint); - if(!entryPointLayout) - return 0; - - if (entryPointLayout->profile.getStage() != Stage::Fragment) - return 0; - - return (entryPointLayout->flags & EntryPointLayout::Flag::usesAnySampleRateInput) != 0; -} - -SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getVarLayout( - SlangReflectionEntryPoint* inEntryPoint) -{ - auto entryPointLayout = convert(inEntryPoint); - if(!entryPointLayout) - return nullptr; - - return convert(entryPointLayout->parametersLayout); -} - -SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getResultVarLayout( - SlangReflectionEntryPoint* inEntryPoint) -{ - auto entryPointLayout = convert(inEntryPoint); - if(!entryPointLayout) - return nullptr; - - return convert(entryPointLayout->resultLayout); -} - - -static bool hasDefaultConstantBuffer(ScopeLayout* layout) -{ - auto typeLayout = layout->parametersLayout->getTypeLayout(); - return as<ParameterGroupTypeLayout>(typeLayout) != nullptr; -} - -SLANG_API int spReflectionEntryPoint_hasDefaultConstantBuffer( - SlangReflectionEntryPoint* inEntryPoint) -{ - auto entryPointLayout = convert(inEntryPoint); - if(!entryPointLayout) - return 0; - - return hasDefaultConstantBuffer(entryPointLayout); -} - - -// SlangReflectionTypeParameter -SLANG_API char const* spReflectionTypeParameter_GetName(SlangReflectionTypeParameter * inTypeParam) -{ - auto specializationParam = convert(inTypeParam); - if( auto genericParamLayout = as<GenericSpecializationParamLayout>(specializationParam) ) - { - return genericParamLayout->decl->getName()->text.getBuffer(); - } - // TODO: Add case for existential type parameter? They don't have as simple of a notion of "name" as the generic case... - return nullptr; -} - -SLANG_API unsigned spReflectionTypeParameter_GetIndex(SlangReflectionTypeParameter * inTypeParam) -{ - auto typeParam = convert(inTypeParam); - return (unsigned)(typeParam->index); -} - -SLANG_API unsigned int spReflectionTypeParameter_GetConstraintCount(SlangReflectionTypeParameter* inTypeParam) -{ - auto specializationParam = convert(inTypeParam); - if(auto genericParamLayout = as<GenericSpecializationParamLayout>(specializationParam)) - { - if( auto globalGenericParamDecl = as<GlobalGenericParamDecl>(genericParamLayout->decl) ) - { - auto constraints = globalGenericParamDecl->getMembersOfType<GenericTypeConstraintDecl>(); - return (unsigned int)constraints.getCount(); - } - // TODO: Add case for entry-point generic parameters. - } - // TODO: Add case for existential type parameters. - return 0; -} - -SLANG_API SlangReflectionType* spReflectionTypeParameter_GetConstraintByIndex(SlangReflectionTypeParameter * inTypeParam, unsigned index) -{ - auto specializationParam = convert(inTypeParam); - if(auto genericParamLayout = as<GenericSpecializationParamLayout>(specializationParam)) - { - if( auto globalGenericParamDecl = as<GlobalGenericParamDecl>(genericParamLayout->decl) ) - { - auto constraints = globalGenericParamDecl->getMembersOfType<GenericTypeConstraintDecl>(); - return (SlangReflectionType*)constraints[index]->sup.Ptr(); - } - // TODO: Add case for entry-point generic parameters. - } - // TODO: Add case for existential type parameters. - return 0; -} - -// Shader Reflection - -SLANG_API unsigned spReflection_GetParameterCount(SlangReflection* inProgram) -{ - auto program = convert(inProgram); - if(!program) return 0; - - auto globalStructLayout = getGlobalStructLayout(program); - if (!globalStructLayout) - return 0; - - return (unsigned) globalStructLayout->fields.getCount(); -} - -SLANG_API SlangReflectionParameter* spReflection_GetParameterByIndex(SlangReflection* inProgram, unsigned index) -{ - auto program = convert(inProgram); - if(!program) return nullptr; - - auto globalStructLayout = getGlobalStructLayout(program); - if (!globalStructLayout) - return 0; - - return convert(globalStructLayout->fields[index].Ptr()); -} - -SLANG_API SlangReflectionVariableLayout* spReflection_getGlobalParamsVarLayout(SlangReflection* inProgram) -{ - auto program = convert(inProgram); - if(!program) return nullptr; - - return convert(program->parametersLayout); -} - -SLANG_API unsigned int spReflection_GetTypeParameterCount(SlangReflection * reflection) -{ - auto program = convert(reflection); - return (unsigned int) program->specializationParams.getCount(); -} - -SLANG_API SlangReflectionTypeParameter* spReflection_GetTypeParameterByIndex(SlangReflection * reflection, unsigned int index) -{ - auto program = convert(reflection); - return (SlangReflectionTypeParameter*) program->specializationParams[index].Ptr(); -} - -SLANG_API SlangReflectionTypeParameter * spReflection_FindTypeParameter(SlangReflection * inProgram, char const * name) -{ - auto program = convert(inProgram); - if (!program) return nullptr; - for( auto& param : program->specializationParams ) - { - auto genericParamLayout = as<GenericSpecializationParamLayout>(param); - if(!genericParamLayout) - continue; - - if(getText(genericParamLayout->decl->getName()) != UnownedTerminatedStringSlice(name)) - continue; - - return (SlangReflectionTypeParameter*) genericParamLayout; - } - - return 0; -} - -SLANG_API SlangUInt spReflection_getEntryPointCount(SlangReflection* inProgram) -{ - auto program = convert(inProgram); - if(!program) return 0; - - return SlangUInt(program->entryPoints.getCount()); -} - -SLANG_API SlangReflectionEntryPoint* spReflection_getEntryPointByIndex(SlangReflection* inProgram, SlangUInt index) -{ - auto program = convert(inProgram); - if(!program) return 0; - - return convert(program->entryPoints[(int) index].Ptr()); -} - -SLANG_API SlangReflectionEntryPoint* spReflection_findEntryPointByName(SlangReflection* inProgram, char const* name) -{ - auto program = convert(inProgram); - if(!program) return 0; - - // TODO: improve on naive linear search - for(auto ep : program->entryPoints) - { - if(ep->entryPoint.getName()->text == name) - { - return convert(ep); - } - } - - return nullptr; -} - -SLANG_API SlangUInt spReflection_getGlobalConstantBufferBinding(SlangReflection* inProgram) -{ - auto program = convert(inProgram); - if (!program) return 0; - auto cb = program->parametersLayout->FindResourceInfo(LayoutResourceKind::ConstantBuffer); - if (!cb) return 0; - return cb->index; -} - -SLANG_API size_t spReflection_getGlobalConstantBufferSize(SlangReflection* inProgram) -{ - auto program = convert(inProgram); - if (!program) return 0; - auto structLayout = getGlobalStructLayout(program); - auto uniform = structLayout->FindResourceInfo(LayoutResourceKind::Uniform); - if (!uniform) return 0; - return getReflectionSize(uniform->count); -} - -SLANG_API SlangReflectionType* spReflection_specializeType( - SlangReflection* inProgramLayout, - SlangReflectionType* inType, - SlangInt specializationArgCount, - SlangReflectionType* const* specializationArgs, - ISlangBlob** outDiagnostics) -{ - auto programLayout = convert(inProgramLayout); - if(!programLayout) return nullptr; - - auto unspecializedType = convert(inType); - if(!unspecializedType) return nullptr; - - auto linkage = programLayout->getProgram()->getLinkage(); - - DiagnosticSink sink(linkage->getSourceManager()); - - auto specializedType = linkage->specializeType(unspecializedType, specializationArgCount, (Type* const*) specializationArgs, &sink); - - sink.getBlobIfNeeded(outDiagnostics); - - return convert(specializedType); -} - -SLANG_API SlangUInt spReflection_getHashedStringCount( - SlangReflection* reflection) -{ - auto programLayout = convert(reflection); - auto slices = programLayout->hashedStringLiteralPool.getAdded(); - return slices.getCount(); -} - -SLANG_API const char* spReflection_getHashedString( - SlangReflection* reflection, - SlangUInt index, - size_t* outCount) -{ - auto programLayout = convert(reflection); - - auto slices = programLayout->hashedStringLiteralPool.getAdded(); - auto slice = slices[Index(index)]; - - *outCount = slice.getLength(); - return slice.begin(); -} - -SLANG_API int spComputeStringHash(const char* chars, size_t count) -{ - return (int)getStableHashCode32(chars, count); -} - -SLANG_API SlangReflectionTypeLayout* spReflection_getGlobalParamsTypeLayout( - SlangReflection* reflection) -{ - auto programLayout = convert(reflection); - if(!programLayout) return nullptr; - - return convert(programLayout->parametersLayout->typeLayout); -} |
