From a67cb0609587c230746b52567ff5775cab215220 Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Sat, 3 Feb 2024 10:14:04 +0800 Subject: GLSL Passthrough support for SSBO types (#3446) * GLSL Passthrough support for SSBO types * GLSL Passthrough support for SSBO types * Correctly apply glsl local size layout to entry points during lowering * Test for glsl layout correctness * typo * Reflect GLSL SSBO as raw buffers * Functional test for glsl ssbo * Allow allow glsl for render tests * Functional test for ssbo passthrough * Functional test for ssbo passthrough with spirv-direct * fix windows build error --------- Co-authored-by: Yong He --- source/slang/slang-emit-glsl.cpp | 59 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) (limited to 'source/slang/slang-emit-glsl.cpp') diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index 0fc0c855a..3d3f9687e 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -9,6 +9,7 @@ #include "slang-legalize-types.h" #include "slang-ir-layout.h" +#include "slang/slang-ir.h" #include @@ -229,8 +230,7 @@ void GLSLSourceEmitter::_emitGLSLStructuredBuffer(IRGlobalParam* varDecl, IRHLSL m_writer->emit(";\n"); } - -void GLSLSourceEmitter::_emitGLSLByteAddressBuffer(IRGlobalParam* varDecl, IRByteAddressBufferTypeBase* byteAddressBufferType) +void GLSLSourceEmitter::emitSSBOHeader(IRGlobalParam* varDecl, IRType* bufferType) { // TODO: A lot of this logic is copy-pasted from `emitIRStructuredBuffer_GLSL`. // It might be worthwhile to share the common code to avoid regressions sneaking @@ -247,9 +247,9 @@ void GLSLSourceEmitter::_emitGLSLByteAddressBuffer(IRGlobalParam* varDecl, IRByt auto layout = getVarLayout(varDecl); if (layout) { - // We can use ShaderResource/DescriptorSlot interchangably here. + // We can use ShaderResource/DescriptorSlot interchangably here. // This is possible because vk-shift-* - bool isReadOnly = (as(byteAddressBufferType) != nullptr); + bool isReadOnly = (as(bufferType) != nullptr); const LayoutResourceKindFlags kinds = (isReadOnly ? LayoutResourceKindFlag::ShaderResource : LayoutResourceKindFlag::UnorderedAccess) | LayoutResourceKindFlag::DescriptorTableSlot; @@ -283,12 +283,17 @@ void GLSLSourceEmitter::_emitGLSLByteAddressBuffer(IRGlobalParam* varDecl, IRByt HLSLRasterizerOrderedByteAddressBufferType - Allows read/write access */ - if (as(byteAddressBufferType)) + if (as(bufferType)) { m_writer->emit("readonly "); } m_writer->emit("buffer "); +} + +void GLSLSourceEmitter::_emitGLSLByteAddressBuffer(IRGlobalParam* varDecl, IRByteAddressBufferTypeBase* byteAddressBufferType) +{ + emitSSBOHeader(varDecl, byteAddressBufferType); // Generate a dummy name for the block m_writer->emit("_S"); @@ -307,6 +312,21 @@ void GLSLSourceEmitter::_emitGLSLByteAddressBuffer(IRGlobalParam* varDecl, IRByt m_writer->emit(";\n"); } +void GLSLSourceEmitter::_emitGLSLSSBO(IRGlobalParam* varDecl, IRGLSLShaderStorageBufferType* ssboType) +{ + emitSSBOHeader(varDecl, ssboType); + + const auto structType = cast(ssboType->getOperand(0)); + m_writer->emit(getName(structType)); + m_writer->emit("_Block"); + emitStructDeclarationsBlock(structType, true); + + m_writer->emit(getName(varDecl)); + emitArrayBrackets(varDecl->getDataType()); + + m_writer->emit(";\n"); +} + void GLSLSourceEmitter::_emitGLSLParameterGroup(IRGlobalParam* varDecl, IRUniformParameterGroupType* type) { auto varLayout = getVarLayout(varDecl); @@ -1282,6 +1302,11 @@ bool GLSLSourceEmitter::tryEmitGlobalParamImpl(IRGlobalParam* varDecl, IRType* v _emitGLSLByteAddressBuffer(varDecl, byteAddressBufferType); return true; } + else if (const auto glslSSBOType = as(unwrapArray(varType))) + { + _emitGLSLSSBO(varDecl, glslSSBOType); + return true; + } // We want to skip the declaration of any system-value variables // when outputting GLSL (well, except in the case where they @@ -1603,6 +1628,25 @@ void GLSLSourceEmitter::emitBufferPointerTypeDefinition(IRInst* ptrType) m_writer->emit("};\n"); } +// Is this type only used by SSBO declarations, if so then we don't need to +// emit it and it'll be emitted inline there. +static bool isSSBOInternalStructType(IRInst* inst) +{ + if(!as(inst)) + return false; + + bool onlySSBOUses = true; + for(auto use = inst->firstUse; use; use = use->nextUse) + { + if(!as(use->user)) + { + onlySSBOUses = false; + break; + } + } + return onlySSBOUses; +} + void GLSLSourceEmitter::emitGlobalInstImpl(IRInst* inst) { switch (inst->getOp()) @@ -1610,6 +1654,11 @@ void GLSLSourceEmitter::emitGlobalInstImpl(IRInst* inst) case kIROp_HLSLConstBufferPointerType: emitBufferPointerTypeDefinition(inst); break; + // No need to use structs which are just taking part in a SSBO declaration + case kIROp_StructType: + if(isSSBOInternalStructType(inst)) + break; + [[fallthrough]]; default: Super::emitGlobalInstImpl(inst); break; -- cgit v1.2.3