diff options
Diffstat (limited to 'tools/gfx/renderer-shared.cpp')
| -rw-r--r-- | tools/gfx/renderer-shared.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp index 78c0439fd..e423cd7b6 100644 --- a/tools/gfx/renderer-shared.cpp +++ b/tools/gfx/renderer-shared.cpp @@ -155,6 +155,65 @@ IShaderObject* gfx::ShaderObjectBase::getInterface(const Guid& guid) return nullptr; } +bool gfx::ShaderObjectBase::_doesValueFitInExistentialPayload( + slang::TypeLayoutReflection* concreteTypeLayout, + slang::TypeLayoutReflection* existentialTypeLayout) +{ + // Our task here is to figure out if a value of `concreteTypeLayout` + // can fit into an existential value using `existentialTypelayout`. + + // We can start by asking how many bytes the concrete type of the object consumes. + // + auto concreteValueSize = concreteTypeLayout->getSize(); + + // We can also compute how many bytes the existential-type value provides, + // but we need to remember that the *payload* part of that value comes after + // the header with RTTI and witness-table IDs, so the payload is 16 bytes + // smaller than the entire value. + // + auto existentialValueSize = existentialTypeLayout->getSize(); + auto existentialPayloadSize = existentialValueSize - 16; + + // If the concrete type consumes more ordinary bytes than we have in the payload, + // it cannot possibly fit. + // + if(concreteValueSize > existentialPayloadSize) + return false; + + // It is possible that the ordinary bytes of `concreteTypeLayout` can fit + // in the payload, but that type might also use storage other than ordinary + // bytes. In that case, the value would *not* fit, because all the non-ordinary + // data can't fit in the payload at all. + // + auto categoryCount = concreteTypeLayout->getCategoryCount(); + for(unsigned int i = 0; i < categoryCount; ++i) + { + auto category = concreteTypeLayout->getCategoryByIndex(i); + switch(category) + { + // We want to ignore any ordinary/uniform data usage, since that + // was already checked above. + // + case slang::ParameterCategory::Uniform: + break; + + // Any other kind of data consumed means the value cannot possibly fit. + default: + return false; + + // TODO: Are there any cases of resource usage that need to be ignored here? + // E.g., if the sub-object contains its own existential-type fields (which + // get reflected as consuming "existential value" storage) should that be + // ignored? + } + } + + // If we didn't reject the concrete type above for either its ordinary + // data or some use of non-ordinary data, then it seems like it must fit. + // + return true; +} + IShaderProgram* gfx::ShaderProgramBase::getInterface(const Guid& guid) { if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IShaderProgram) @@ -400,6 +459,11 @@ void ShaderObjectLayoutBase::initBase(RendererBase* renderer, slang::TypeLayoutR // this function will return a specialized type using the bound sub-objects' type as specialization argument. Result ShaderObjectBase::getSpecializedShaderObjectType(ExtendedShaderObjectType* outType) { + return _getSpecializedShaderObjectType(outType); +} + +Result ShaderObjectBase::_getSpecializedShaderObjectType(ExtendedShaderObjectType* outType) +{ if (shaderObjectType.slangType) *outType = shaderObjectType; ExtendedShaderObjectTypeList specializationArgs; |
