From 35f8e092f2aa3ed5e3cf03387e712f798ff4850e Mon Sep 17 00:00:00 2001 From: Julius Ikkala Date: Thu, 21 Aug 2025 08:47:18 +0300 Subject: Introduce CDataLayout & -fvk-use-c-layout (#8136) Closes #8112. ~~The issue asks for a "C layout", but in this PR I use the term "CPU layout" because this naming was pre-existing in the codebase as `kCPULayoutRulesImpl_`. The primary purpose of this layout is to match CPU-side struct definitions with the shader side. I'm open to better naming suggestions, though.~~ Edit: switched back to using `CDataLayout` & `-fvk-use-c-layout`, as the CPU target depends on the object layout rules of existing CPU layout rules, but they're incompatible with actual shaders. So a new `kCLayoutRulesImpl_` was needed anyway. --------- Co-authored-by: Ellie Hermaszewska --- source/slang/hlsl.meta.slang | 7 + source/slang/slang-ast-builder.cpp | 5 + source/slang/slang-ast-builder.h | 1 + source/slang/slang-ast-type.h | 6 + source/slang/slang-compiler-options.cpp | 1 + source/slang/slang-compiler-options.h | 2 + source/slang/slang-emit-spirv.cpp | 20 ++- source/slang/slang-end-to-end-request.cpp | 5 + source/slang/slang-end-to-end-request.h | 2 + source/slang/slang-ir-entry-point-uniforms.cpp | 3 + source/slang/slang-ir-insts-stable-names.lua | 1 + source/slang/slang-ir-insts.lua | 1 + source/slang/slang-ir-layout.cpp | 105 +++++++++---- source/slang/slang-ir-layout.h | 7 + .../slang/slang-ir-lower-buffer-element-type.cpp | 29 +++- source/slang/slang-ir.h | 1 + source/slang/slang-options.cpp | 16 ++ source/slang/slang-type-layout.cpp | 163 +++++++++++++++++++++ 18 files changed, 339 insertions(+), 36 deletions(-) (limited to 'source/slang') diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 7f8488236..0dbca2479 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -57,6 +57,13 @@ __magic_type(ScalarDataLayoutType) struct ScalarDataLayout : IBufferDataLayout {}; +/// @category misc_types +__intrinsic_type($(kIROp_CBufferLayoutType)) +__magic_type(CDataLayoutType) +[require(spirv)] +struct CDataLayout : IBufferDataLayout +{}; + //@hidden: __generic __intrinsic_type($(kIROp_GLSLShaderStorageBufferType)) diff --git a/source/slang/slang-ast-builder.cpp b/source/slang/slang-ast-builder.cpp index d576ed0fb..a71abf570 100644 --- a/source/slang/slang-ast-builder.cpp +++ b/source/slang/slang-ast-builder.cpp @@ -489,6 +489,11 @@ Type* ASTBuilder::getScalarLayoutType() return getSpecializedBuiltinType({}, "ScalarDataLayoutType"); } +Type* ASTBuilder::getCLayoutType() +{ + return getSpecializedBuiltinType({}, "CDataLayoutType"); +} + // Construct the type `Out` OutType* ASTBuilder::getOutType(Type* valueType) { diff --git a/source/slang/slang-ast-builder.h b/source/slang/slang-ast-builder.h index 72f875f91..798e1ddc0 100644 --- a/source/slang/slang-ast-builder.h +++ b/source/slang/slang-ast-builder.h @@ -517,6 +517,7 @@ public: Type* getStd140LayoutType(); Type* getStd430LayoutType(); Type* getScalarLayoutType(); + Type* getCLayoutType(); Type* getInitializerListType() { return m_sharedASTBuilder->getInitializerListType(); } Type* getOverloadedType() { return m_sharedASTBuilder->getOverloadedType(); } diff --git a/source/slang/slang-ast-type.h b/source/slang/slang-ast-type.h index d262f1ad5..842af8b88 100644 --- a/source/slang/slang-ast-type.h +++ b/source/slang/slang-ast-type.h @@ -161,6 +161,12 @@ class ScalarDataLayoutType : public DataLayoutType FIDDLE(...) }; +FIDDLE() +class CDataLayoutType : public DataLayoutType +{ + FIDDLE(...) +}; + FIDDLE() class FeedbackType : public BuiltinType { diff --git a/source/slang/slang-compiler-options.cpp b/source/slang/slang-compiler-options.cpp index 843e0e7cb..fa2b99b98 100644 --- a/source/slang/slang-compiler-options.cpp +++ b/source/slang/slang-compiler-options.cpp @@ -143,6 +143,7 @@ void CompilerOptionSet::writeCommandLineArgs(Session* globalSession, StringBuild case CompilerOptionName::EmitSpirvDirectly: case CompilerOptionName::GLSLForceScalarLayout: case CompilerOptionName::ForceDXLayout: + case CompilerOptionName::ForceCLayout: case CompilerOptionName::MatrixLayoutRow: case CompilerOptionName::MatrixLayoutColumn: case CompilerOptionName::VulkanInvertY: diff --git a/source/slang/slang-compiler-options.h b/source/slang/slang-compiler-options.h index 5986c4e82..ec9383e08 100644 --- a/source/slang/slang-compiler-options.h +++ b/source/slang/slang-compiler-options.h @@ -348,6 +348,8 @@ struct CompilerOptionSet bool shouldUseDXLayout() { return getBoolOption(CompilerOptionName::ForceDXLayout); } + bool shouldUseCLayout() { return getBoolOption(CompilerOptionName::ForceCLayout); } + bool shouldDumpIntermediates() { return getBoolOption(CompilerOptionName::DumpIntermediates); } bool shouldDumpIR() { return getBoolOption(CompilerOptionName::DumpIr); } diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 6b42896d0..d6f4ac176 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -1847,10 +1847,22 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex IRSizeAndAlignment sizeAndAlignment; uint32_t stride; - getNaturalSizeAndAlignment( - m_targetProgram->getOptionSet(), - valueType, - &sizeAndAlignment); + if (auto layout = valueType->findDecoration()) + { + auto rule = IRTypeLayoutRules::get(layout->getLayoutName()); + getSizeAndAlignment( + m_targetProgram->getOptionSet(), + rule, + valueType, + &sizeAndAlignment); + } + else + { + getNaturalSizeAndAlignment( + m_targetProgram->getOptionSet(), + valueType, + &sizeAndAlignment); + } uint64_t valueSize = sizeAndAlignment.size; // Any unsized data type (e.g. struct or array) will have size of diff --git a/source/slang/slang-end-to-end-request.cpp b/source/slang/slang-end-to-end-request.cpp index 725fc1854..fc2d6d55e 100644 --- a/source/slang/slang-end-to-end-request.cpp +++ b/source/slang/slang-end-to-end-request.cpp @@ -894,6 +894,11 @@ void EndToEndCompileRequest::setTargetForceDXLayout(int targetIndex, bool value) getTargetOptionSet(targetIndex).set(CompilerOptionName::ForceDXLayout, value); } +void EndToEndCompileRequest::setTargetForceCLayout(int targetIndex, bool value) +{ + getTargetOptionSet(targetIndex).set(CompilerOptionName::ForceCLayout, value); +} + void EndToEndCompileRequest::setTargetFloatingPointMode( int targetIndex, SlangFloatingPointMode mode) diff --git a/source/slang/slang-end-to-end-request.h b/source/slang/slang-end-to-end-request.h index af04eac63..f8d666970 100644 --- a/source/slang/slang-end-to-end-request.h +++ b/source/slang/slang-end-to-end-request.h @@ -100,6 +100,8 @@ public: setTargetGenerateWholeProgram(int targetIndex, bool value) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setTargetEmbedDownstreamIR(int targetIndex, bool value) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceCLayout(int targetIndex, bool value) + SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setMatrixLayoutMode(SlangMatrixLayoutMode mode) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setDebugInfoLevel(SlangDebugInfoLevel level) diff --git a/source/slang/slang-ir-entry-point-uniforms.cpp b/source/slang/slang-ir-entry-point-uniforms.cpp index 586d64b4f..e75be9e24 100644 --- a/source/slang/slang-ir-entry-point-uniforms.cpp +++ b/source/slang/slang-ir-entry-point-uniforms.cpp @@ -557,6 +557,9 @@ struct CollectEntryPointUniformParams : PerEntryPointPass if (m_options.targetReq->getOptionSet().getBoolOption( CompilerOptionName::GLSLForceScalarLayout)) layoutType = builder.getType(kIROp_ScalarBufferLayoutType); + else if (m_options.targetReq->getOptionSet().getBoolOption( + CompilerOptionName::ForceCLayout)) + layoutType = builder.getType(kIROp_CBufferLayoutType); else if (isKhronosTarget(m_options.targetReq)) layoutType = builder.getType(kIROp_Std430BufferLayoutType); else diff --git a/source/slang/slang-ir-insts-stable-names.lua b/source/slang/slang-ir-insts-stable-names.lua index db2a8f8c8..589c4b130 100644 --- a/source/slang/slang-ir-insts-stable-names.lua +++ b/source/slang/slang-ir-insts-stable-names.lua @@ -669,4 +669,5 @@ return { ["SPIRVAsmOperand.__sampledType"] = 665, ["SPIRVAsmOperand.__imageType"] = 666, ["SPIRVAsmOperand.__sampledImageType"] = 667, + ["Type.CLayout"] = 668, } diff --git a/source/slang/slang-ir-insts.lua b/source/slang/slang-ir-insts.lua index 0325fcbfd..c1777c2cf 100644 --- a/source/slang/slang-ir-insts.lua +++ b/source/slang/slang-ir-insts.lua @@ -206,6 +206,7 @@ local insts = { { Std140Layout = { struct_name = "Std140BufferLayoutType", hoistable = true } }, { Std430Layout = { struct_name = "Std430BufferLayoutType", hoistable = true } }, { ScalarLayout = { struct_name = "ScalarBufferLayoutType", hoistable = true } }, + { CLayout = { struct_name = "CBufferLayoutType", hoistable = true } }, { SubpassInputType = { operands = { { "elementType", "IRType" }, { "isMultisampleInst" } }, hoistable = true } }, { TextureFootprintType = { min_operands = 1, hoistable = true } }, { TextureShape1DType = { hoistable = true } }, diff --git a/source/slang/slang-ir-layout.cpp b/source/slang/slang-ir-layout.cpp index ac0c79601..d3b86a1c6 100644 --- a/source/slang/slang-ir-layout.cpp +++ b/source/slang/slang-ir-layout.cpp @@ -83,9 +83,8 @@ IRIntegerValue getIntegerValueFromInst(IRInst* inst) return as(inst)->value.intVal; } -static Result _calcSizeAndAlignment( +Result IRTypeLayoutRules::calcSizeAndAlignment( CompilerOptionSet& optionSet, - IRTypeLayoutRules* rules, IRType* type, IRSizeAndAlignment* outSizeAndAlignment) { @@ -131,10 +130,6 @@ static Result _calcSizeAndAlignment( // We are currently handling `bool` following the HLSL // precednet of storing it in 4 bytes. // - // TODO: It would be good to try to make this follow - // per-platform conventions, or at least to be able - // to use a 1-byte encoding where available. - // BASE(Bool, 4); // The Slang `void` type is treated as a zero-byte @@ -142,7 +137,7 @@ static Result _calcSizeAndAlignment( // CASE(Void, 0, 1); -#undef CASE +#undef BASE #undef CASE @@ -163,7 +158,7 @@ static Result _calcSizeAndAlignment( IRSizeAndAlignment fieldTypeLayout; SLANG_RETURN_ON_FAIL( - getSizeAndAlignment(optionSet, rules, field->getFieldType(), &fieldTypeLayout)); + getSizeAndAlignment(optionSet, this, field->getFieldType(), &fieldTypeLayout)); seenFinalUnsizedArrayField = fieldTypeLayout.size == IRSizeAndAlignment::kIndeterminateSize; @@ -174,7 +169,7 @@ static Result _calcSizeAndAlignment( } else { - offset = rules->adjustOffset( + offset = adjustOffset( offset, fieldTypeLayout.size, lastFieldType, @@ -199,7 +194,7 @@ static Result _calcSizeAndAlignment( builder.addDecoration( field, kIROp_OffsetDecoration, - builder.getIntValue(intType, (IRIntegerValue)rules->ruleName), + builder.getIntValue(intType, (IRIntegerValue)ruleName), builder.getIntValue(intType, fieldOffset)); } if (!seenFinalUnsizedArrayField) @@ -208,7 +203,7 @@ static Result _calcSizeAndAlignment( lastFieldType = field->getFieldType(); lastFieldAlignment = fieldTypeLayout.alignment; } - *outSizeAndAlignment = rules->alignCompositeElement(structLayout); + *outSizeAndAlignment = alignCompositeElement(structLayout); return SLANG_OK; } break; @@ -219,7 +214,7 @@ static Result _calcSizeAndAlignment( return _calcArraySizeAndAlignment( optionSet, - rules, + this, arrayType->getElementType(), arrayType->getElementCount(), outSizeAndAlignment); @@ -229,11 +224,7 @@ static Result _calcSizeAndAlignment( case kIROp_AtomicType: { auto atomicType = cast(type); - _calcSizeAndAlignment( - optionSet, - rules, - atomicType->getElementType(), - outSizeAndAlignment); + calcSizeAndAlignment(optionSet, atomicType->getElementType(), outSizeAndAlignment); return SLANG_OK; } break; @@ -243,7 +234,7 @@ static Result _calcSizeAndAlignment( auto unsizedArrayType = cast(type); getSizeAndAlignment( optionSet, - rules, + this, unsizedArrayType->getElementType(), outSizeAndAlignment); outSizeAndAlignment->size = IRSizeAndAlignment::kIndeterminateSize; @@ -255,8 +246,8 @@ static Result _calcSizeAndAlignment( { auto vecType = cast(type); IRSizeAndAlignment elementTypeLayout; - getSizeAndAlignment(optionSet, rules, vecType->getElementType(), &elementTypeLayout); - *outSizeAndAlignment = rules->getVectorSizeAndAlignment( + getSizeAndAlignment(optionSet, this, vecType->getElementType(), &elementTypeLayout); + *outSizeAndAlignment = getVectorSizeAndAlignment( elementTypeLayout, getIntegerValueFromInst(vecType->getElementCount())); return SLANG_OK; @@ -267,7 +258,7 @@ static Result _calcSizeAndAlignment( auto anyValType = cast(type); outSizeAndAlignment->size = getIntVal(anyValType->getSize()); outSizeAndAlignment->alignment = 4; - *outSizeAndAlignment = rules->alignCompositeElement(*outSizeAndAlignment); + *outSizeAndAlignment = alignCompositeElement(*outSizeAndAlignment); return SLANG_OK; } break; @@ -282,8 +273,8 @@ static Result _calcSizeAndAlignment( auto elementType = tupleType->getOperand(i); IRSizeAndAlignment fieldTypeLayout; SLANG_RETURN_ON_FAIL( - getSizeAndAlignment(optionSet, rules, (IRType*)elementType, &fieldTypeLayout)); - resultLayout.size = rules->adjustOffset( + getSizeAndAlignment(optionSet, this, (IRType*)elementType, &fieldTypeLayout)); + resultLayout.size = adjustOffset( resultLayout.size, fieldTypeLayout.size, lastFieldType, @@ -296,7 +287,7 @@ static Result _calcSizeAndAlignment( lastFieldType = as(elementType); lastFieldAlignment = fieldTypeLayout.alignment; } - *outSizeAndAlignment = rules->alignCompositeElement(resultLayout); + *outSizeAndAlignment = alignCompositeElement(resultLayout); return SLANG_OK; } break; @@ -320,7 +311,7 @@ static Result _calcSizeAndAlignment( IRSizeAndAlignment resultLayout; resultLayout.size = size; resultLayout.alignment = 4; - *outSizeAndAlignment = rules->alignCompositeElement(resultLayout); + *outSizeAndAlignment = alignCompositeElement(resultLayout); return SLANG_OK; } break; @@ -334,7 +325,7 @@ static Result _calcSizeAndAlignment( builder.getVectorType(matType->getElementType(), matType->getRowCount()); return _calcArraySizeAndAlignment( optionSet, - rules, + this, colVector, matType->getColumnCount(), outSizeAndAlignment); @@ -345,7 +336,7 @@ static Result _calcSizeAndAlignment( builder.getVectorType(matType->getElementType(), matType->getColumnCount()); return _calcArraySizeAndAlignment( optionSet, - rules, + this, rowVector, matType->getRowCount(), outSizeAndAlignment); @@ -369,6 +360,7 @@ static Result _calcSizeAndAlignment( } break; case kIROp_ScalarBufferLayoutType: + case kIROp_CBufferLayoutType: case kIROp_Std140BufferLayoutType: case kIROp_Std430BufferLayoutType: case kIROp_DefaultBufferLayoutType: @@ -380,7 +372,7 @@ static Result _calcSizeAndAlignment( builder.setInsertBefore(type); auto uintType = builder.getUIntType(); auto uint2Type = builder.getVectorType(uintType, 2); - return getSizeAndAlignment(optionSet, rules, uint2Type, outSizeAndAlignment); + return getSizeAndAlignment(optionSet, this, uint2Type, outSizeAndAlignment); } case kIROp_AttributedType: { @@ -388,7 +380,7 @@ static Result _calcSizeAndAlignment( SLANG_ASSERT(attributedType->getAttr()->getOp() == kIROp_NoDiffAttr); return getSizeAndAlignment( optionSet, - rules, + this, attributedType->getBaseType(), outSizeAndAlignment); } @@ -396,7 +388,7 @@ static Result _calcSizeAndAlignment( { auto enumType = cast(type); auto tagType = enumType->getTagType(); - return _calcSizeAndAlignment(optionSet, rules, tagType, outSizeAndAlignment); + return calcSizeAndAlignment(optionSet, tagType, outSizeAndAlignment); } break; default: @@ -439,7 +431,7 @@ Result getSizeAndAlignment( } IRSizeAndAlignment sizeAndAlignment; - SLANG_RETURN_ON_FAIL(_calcSizeAndAlignment(optionSet, rules, type, &sizeAndAlignment)); + SLANG_RETURN_ON_FAIL(rules->calcSizeAndAlignment(optionSet, type, &sizeAndAlignment)); if (auto module = type->getModule()) { @@ -538,6 +530,49 @@ struct NaturalLayoutRules : IRTypeLayoutRules } }; +struct CLayoutRules : IRTypeLayoutRules +{ + CLayoutRules() { ruleName = IRTypeLayoutRuleName::C; } + + virtual Result calcSizeAndAlignment( + CompilerOptionSet& optionSet, + IRType* type, + IRSizeAndAlignment* outSizeAndAlignment) + { + if (type->getOp() == kIROp_BoolType) + { + *outSizeAndAlignment = IRSizeAndAlignment(1, 1); + return SLANG_OK; + } + return IRTypeLayoutRules::calcSizeAndAlignment(optionSet, type, outSizeAndAlignment); + } + + virtual IRIntegerValue adjustOffset( + IRIntegerValue offset, + IRIntegerValue elementSize, + IRType* lastFieldType, + IRIntegerValue lastFieldAlignment) + { + SLANG_UNUSED(elementSize); + SLANG_UNUSED(lastFieldType); + return align(offset, (int)lastFieldAlignment); + } + + virtual IRSizeAndAlignment alignCompositeElement(IRSizeAndAlignment elementSize) + { + IRSizeAndAlignment alignedSize = elementSize; + alignedSize.size = align(alignedSize.size, alignedSize.alignment); + return alignedSize; + } + + virtual IRSizeAndAlignment getVectorSizeAndAlignment( + IRSizeAndAlignment element, + IRIntegerValue count) + { + return IRSizeAndAlignment(element.size * count, element.alignment); + } +}; + struct ConstantBufferLayoutRules : IRTypeLayoutRules { ConstantBufferLayoutRules() { ruleName = IRTypeLayoutRuleName::D3DConstantBuffer; } @@ -713,6 +748,12 @@ IRTypeLayoutRules* IRTypeLayoutRules::getNatural() return &rules; } +IRTypeLayoutRules* IRTypeLayoutRules::getC() +{ + static CLayoutRules rules; + return &rules; +} + IRTypeLayoutRules* IRTypeLayoutRules::getConstantBuffer() { static ConstantBufferLayoutRules rules; @@ -729,6 +770,8 @@ IRTypeLayoutRules* IRTypeLayoutRules::get(IRTypeLayoutRuleName name) return getStd140(); case IRTypeLayoutRuleName::Natural: return getNatural(); + case IRTypeLayoutRuleName::C: + return getC(); case IRTypeLayoutRuleName::D3DConstantBuffer: return getConstantBuffer(); default: diff --git a/source/slang/slang-ir-layout.h b/source/slang/slang-ir-layout.h index 1918f31b6..a0f144c86 100644 --- a/source/slang/slang-ir-layout.h +++ b/source/slang/slang-ir-layout.h @@ -56,6 +56,12 @@ struct IRTypeLayoutRules public: IRTypeLayoutRuleName ruleName; + /// This function calculates the size and alignment of the given type. + virtual Result calcSizeAndAlignment( + CompilerOptionSet& optionSet, + IRType* type, + IRSizeAndAlignment* outSizeAndAlignment); + /// Align composite based on rule. Type is aligned assuming /// it is apart of a composite (array, struct, matrix, etc...) virtual IRSizeAndAlignment alignCompositeElement(IRSizeAndAlignment elementSize) = 0; @@ -79,6 +85,7 @@ public: static IRTypeLayoutRules* getStd430(); static IRTypeLayoutRules* getStd140(); static IRTypeLayoutRules* getNatural(); + static IRTypeLayoutRules* getC(); static IRTypeLayoutRules* getConstantBuffer(); static IRTypeLayoutRules* get(IRTypeLayoutRuleName name); }; diff --git a/source/slang/slang-ir-lower-buffer-element-type.cpp b/source/slang/slang-ir-lower-buffer-element-type.cpp index ed0a3b309..2f40c6cf9 100644 --- a/source/slang/slang-ir-lower-buffer-element-type.cpp +++ b/source/slang/slang-ir-lower-buffer-element-type.cpp @@ -426,6 +426,8 @@ struct LoweredElementTypeContext return "std430"; case IRTypeLayoutRuleName::Natural: return "natural"; + case IRTypeLayoutRuleName::C: + return "c"; default: return "default"; } @@ -797,7 +799,26 @@ struct LoweredElementTypeContext if (as(scalarType)) { // Bool is an abstract type in SPIRV, so we need to lower them into an int. - info.loweredType = builder.getIntType(); + + // Find an integer type of the correct size for the current layout rule. + IRSizeAndAlignment boolSizeAndAlignment; + if (getSizeAndAlignment( + target->getOptionSet(), + config.layoutRule, + scalarType, + &boolSizeAndAlignment) == SLANG_OK) + { + IntInfo ii; + ii.width = boolSizeAndAlignment.size * 8; + ii.isSigned = true; + info.loweredType = builder.getType(getIntTypeOpFromInfo(ii)); + } + else + { + // Just in case that fails for some reason, just use an int. + info.loweredType = builder.getIntType(); + } + if (vectorType) info.loweredType = builder.getVectorType( info.loweredType, @@ -1467,6 +1488,8 @@ IRTypeLayoutRules* getTypeLayoutRulesFromOp(IROp layoutTypeOp, IRTypeLayoutRules return IRTypeLayoutRules::getStd430(); case kIROp_ScalarBufferLayoutType: return IRTypeLayoutRules::getNatural(); + case kIROp_CBufferLayoutType: + return IRTypeLayoutRules::getC(); } return defaultLayout; } @@ -1482,6 +1505,10 @@ IRTypeLayoutRules* getTypeLayoutRuleForBuffer(TargetProgram* target, IRType* buf if (!target->shouldEmitSPIRVDirectly()) return IRTypeLayoutRules::getNatural(); + // If the user specified a C-compatible buffer layout, then do that. + if (target->getOptionSet().shouldUseCLayout()) + return IRTypeLayoutRules::getC(); + // If the user specified a scalar buffer layout, then just use that. if (target->getOptionSet().shouldUseScalarLayout()) return IRTypeLayoutRules::getNatural(); diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h index 1f6418036..ad14edf21 100644 --- a/source/slang/slang-ir.h +++ b/source/slang/slang-ir.h @@ -524,6 +524,7 @@ enum class IRTypeLayoutRuleName Std430, Std140, D3DConstantBuffer, + C, _Count, }; diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index b0eb1748d..2115a096f 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -663,6 +663,12 @@ void initCommandOptions(CommandOptions& options) "-fvk-use-dx-layout", nullptr, "Pack members using FXCs member packing rules when targeting GLSL or SPIRV."}, + {OptionKind::ForceCLayout, + "-fvk-use-c-layout", + nullptr, + "Make data accessed through ConstantBuffer, ParameterBlock, StructuredBuffer, " + "ByteAddressBuffer and general pointers follow the C/C++ structure layout rules " + "when targeting SPIRV."}, {OptionKind::VulkanBindShift, vkShiftNames.getBuffer(), "-fvk--shift ", @@ -2670,6 +2676,11 @@ SlangResult OptionsParser::_parse(int argc, char const* const* argv) getCurrentTarget()->optionSet.add(CompilerOptionName::ForceDXLayout, true); break; } + case OptionKind::ForceCLayout: + { + getCurrentTarget()->optionSet.add(CompilerOptionName::ForceCLayout, true); + break; + } case OptionKind::EnableEffectAnnotations: { m_compileRequest->setEnableEffectAnnotations(true); @@ -3707,6 +3718,11 @@ SlangResult OptionsParser::_parse(int argc, char const* const* argv) m_compileRequest->setTargetForceDXLayout(targetID, true); } + if (rawTarget.optionSet.shouldUseCLayout()) + { + m_compileRequest->setTargetForceCLayout(targetID, true); + } + if (rawTarget.optionSet.getBoolOption(CompilerOptionName::GenerateWholeProgram)) { m_compileRequest->setTargetGenerateWholeProgram(targetID, true); diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp index 275a178d0..3e2560755 100644 --- a/source/slang/slang-type-layout.cpp +++ b/source/slang/slang-type-layout.cpp @@ -1090,6 +1090,29 @@ struct CPULayoutRulesFamilyImpl : LayoutRulesFamilyImpl LayoutRulesImpl* getStructuredBufferRules(CompilerOptionSet& compilerOptions) override; }; +struct CLayoutRulesFamilyImpl : LayoutRulesFamilyImpl +{ + virtual LayoutRulesImpl* getAnyValueRules() override; + virtual LayoutRulesImpl* getConstantBufferRules( + CompilerOptionSet& compilerOptions, + Type* containerType) override; + virtual LayoutRulesImpl* getPushConstantBufferRules() override; + virtual LayoutRulesImpl* getTextureBufferRules(CompilerOptionSet& compilerOptions) override; + virtual LayoutRulesImpl* getVaryingInputRules() override; + virtual LayoutRulesImpl* getVaryingOutputRules() override; + virtual LayoutRulesImpl* getSpecializationConstantRules() override; + virtual LayoutRulesImpl* getShaderStorageBufferRules( + CompilerOptionSet& compilerOptions) override; + virtual LayoutRulesImpl* getParameterBlockRules(CompilerOptionSet& compilerOptions) override; + + LayoutRulesImpl* getRayPayloadParameterRules() override; + LayoutRulesImpl* getCallablePayloadParameterRules() override; + LayoutRulesImpl* getHitAttributesParameterRules() override; + + LayoutRulesImpl* getShaderRecordConstantBufferRules() override; + LayoutRulesImpl* getStructuredBufferRules(CompilerOptionSet& compilerOptions) override; +}; + struct CUDALayoutRulesFamilyImpl : LayoutRulesFamilyImpl { virtual LayoutRulesImpl* getAnyValueRules() override; @@ -1170,6 +1193,7 @@ struct WGSLLayoutRulesFamilyImpl : LayoutRulesFamilyImpl GLSLLayoutRulesFamilyImpl kGLSLLayoutRulesFamilyImpl; HLSLLayoutRulesFamilyImpl kHLSLLayoutRulesFamilyImpl; CPULayoutRulesFamilyImpl kCPULayoutRulesFamilyImpl; +CLayoutRulesFamilyImpl kCLayoutRulesFamilyImpl; CUDALayoutRulesFamilyImpl kCUDALayoutRulesFamilyImpl; MetalLayoutRulesFamilyImpl kMetalLayoutRulesFamilyImpl; MetalArgumentBufferTier2LayoutRulesFamilyImpl kMetalArgumentBufferTier2LayoutRulesFamilyImpl; @@ -1341,6 +1365,69 @@ LayoutRulesImpl kCPUAnyValueLayoutRulesImpl_ = { &kCPUObjectLayoutRulesImpl, }; +// C layout + +LayoutRulesImpl kCLayoutRulesImpl_ = { + &kCLayoutRulesFamilyImpl, + &kCPULayoutRulesImpl, + &kGLSLObjectLayoutRulesImpl, +}; + +LayoutRulesImpl kCAnyValueLayoutRulesImpl_ = { + &kCLayoutRulesFamilyImpl, + &kDefaultLayoutRulesImpl, + &kCPUObjectLayoutRulesImpl, +}; + +LayoutRulesImpl kCPushConstantRulesImpl_ = { + &kCLayoutRulesFamilyImpl, + &kCPULayoutRulesImpl, + &kGLSLPushConstantBufferObjectLayoutRulesImpl_, +}; + +LayoutRulesImpl kCVaryingInputLayoutRulesImpl_ = { + &kCLayoutRulesFamilyImpl, + &kGLSLVaryingOutputLayoutRulesImpl, + &kGLSLObjectLayoutRulesImpl, +}; + +LayoutRulesImpl kCVaryingOutputLayoutRulesImpl_ = { + &kCLayoutRulesFamilyImpl, + &kGLSLVaryingOutputLayoutRulesImpl, + &kGLSLObjectLayoutRulesImpl, +}; + +LayoutRulesImpl kCSpecializationConstantLayoutRulesImpl_ = { + &kCLayoutRulesFamilyImpl, + &kGLSLSpecializationConstantLayoutRulesImpl, + &kGLSLObjectLayoutRulesImpl, +}; + +LayoutRulesImpl kCShaderRecordLayoutRulesImpl_ = { + &kCLayoutRulesFamilyImpl, + &kCPULayoutRulesImpl, + &kGLSLShaderRecordConstantBufferObjectLayoutRulesImpl_, +}; + +LayoutRulesImpl kCRayPayloadParameterLayoutRulesImpl_ = { + &kCLayoutRulesFamilyImpl, + &kGLSLRayPayloadParameterLayoutRulesImpl, + &kGLSLObjectLayoutRulesImpl, +}; + +LayoutRulesImpl kCCallablePayloadParameterLayoutRulesImpl_ = { + &kCLayoutRulesFamilyImpl, + &kGLSLCallablePayloadParameterLayoutRulesImpl, + &kGLSLObjectLayoutRulesImpl, +}; + +LayoutRulesImpl kCHitAttributesParameterLayoutRulesImpl_ = { + &kCLayoutRulesFamilyImpl, + &kGLSLHitAttributesParameterLayoutRulesImpl, + &kGLSLObjectLayoutRulesImpl, +}; + + // CUDA static CUDAObjectLayoutRulesImpl kCUDAObjectLayoutRulesImpl; @@ -1534,6 +1621,8 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getConstantBufferRules( { if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; + else if (compilerOptions.shouldUseCLayout()) + return &kCLayoutRulesImpl_; else if (compilerOptions.shouldUseDXLayout()) return &kFXCConstantBufferLayoutRulesFamilyImpl; if (auto cbufferType = as(containerType)) @@ -1548,6 +1637,8 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getConstantBufferRules( return &kStd430LayoutRulesImpl_; case ASTNodeType::ScalarDataLayoutType: return &kScalarLayoutRulesImpl_; + case ASTNodeType::CDataLayoutType: + return &kCLayoutRulesImpl_; default: break; } @@ -1560,6 +1651,8 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getParameterBlockRules( { if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; + else if (compilerOptions.shouldUseCLayout()) + return &kCLayoutRulesImpl_; else if (compilerOptions.shouldUseDXLayout()) return &kFXCConstantBufferLayoutRulesFamilyImpl; @@ -1581,6 +1674,8 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getTextureBufferRules( { if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; + else if (compilerOptions.shouldUseCLayout()) + return &kCLayoutRulesImpl_; else if (compilerOptions.shouldUseDXLayout()) return &kFXCConstantBufferLayoutRulesFamilyImpl; @@ -1607,6 +1702,8 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getShaderStorageBufferRules( { if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; + else if (compilerOptions.shouldUseCLayout()) + return &kCLayoutRulesImpl_; else if (compilerOptions.shouldUseDXLayout()) return &kFXCShaderResourceLayoutRulesFamilyImpl; @@ -1633,6 +1730,8 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getStructuredBufferRules( { if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; + else if (compilerOptions.shouldUseCLayout()) + return &kCLayoutRulesImpl_; else if (compilerOptions.shouldUseDXLayout()) return &kFXCShaderResourceLayoutRulesFamilyImpl; @@ -1779,6 +1878,70 @@ LayoutRulesImpl* CPULayoutRulesFamilyImpl::getStructuredBufferRules(CompilerOpti return &kCPULayoutRulesImpl_; } +// C compatible layout family + +LayoutRulesImpl* CLayoutRulesFamilyImpl::getAnyValueRules() +{ + return &kCAnyValueLayoutRulesImpl_; +} + +LayoutRulesImpl* CLayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&, Type*) +{ + return &kCLayoutRulesImpl_; +} + +LayoutRulesImpl* CLayoutRulesFamilyImpl::getPushConstantBufferRules() +{ + return &kCPushConstantRulesImpl_; +} + +LayoutRulesImpl* CLayoutRulesFamilyImpl::getTextureBufferRules(CompilerOptionSet&) +{ + return &kCLayoutRulesImpl_; +} + +LayoutRulesImpl* CLayoutRulesFamilyImpl::getVaryingInputRules() +{ + return &kCVaryingInputLayoutRulesImpl_; +} +LayoutRulesImpl* CLayoutRulesFamilyImpl::getVaryingOutputRules() +{ + return &kCVaryingOutputLayoutRulesImpl_; +} +LayoutRulesImpl* CLayoutRulesFamilyImpl::getSpecializationConstantRules() +{ + return &kCSpecializationConstantLayoutRulesImpl_; +} +LayoutRulesImpl* CLayoutRulesFamilyImpl::getShaderStorageBufferRules(CompilerOptionSet&) +{ + return &kCLayoutRulesImpl_; +} +LayoutRulesImpl* CLayoutRulesFamilyImpl::getParameterBlockRules(CompilerOptionSet&) +{ + return &kCLayoutRulesImpl_; +} +LayoutRulesImpl* CLayoutRulesFamilyImpl::getRayPayloadParameterRules() +{ + return &kCRayPayloadParameterLayoutRulesImpl_; +} +LayoutRulesImpl* CLayoutRulesFamilyImpl::getCallablePayloadParameterRules() +{ + return &kCCallablePayloadParameterLayoutRulesImpl_; +} +LayoutRulesImpl* CLayoutRulesFamilyImpl::getHitAttributesParameterRules() +{ + return &kCHitAttributesParameterLayoutRulesImpl_; +} +LayoutRulesImpl* CLayoutRulesFamilyImpl::getShaderRecordConstantBufferRules() +{ + return &kCShaderRecordLayoutRulesImpl_; +} + +LayoutRulesImpl* CLayoutRulesFamilyImpl::getStructuredBufferRules(CompilerOptionSet&) +{ + return &kCLayoutRulesImpl_; +} + // CUDA Family LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getAnyValueRules() -- cgit v1.2.3