diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/check.cpp | 11 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 401 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang | 72 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang.h | 72 | ||||
| -rw-r--r-- | source/slang/ir-inst-defs.h | 4 | ||||
| -rw-r--r-- | source/slang/ir.cpp | 1 | ||||
| -rw-r--r-- | source/slang/type-layout.cpp | 11 | ||||
| -rw-r--r-- | source/slang/type-layout.h | 7 | ||||
| -rw-r--r-- | source/slang/vm.cpp | 66 |
9 files changed, 212 insertions, 433 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp index e07bdf156..21e3b894b 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -7922,16 +7922,15 @@ namespace Slang RefPtr<Expr> expr = inExpr; for (;;) { - auto& type = expr->type; - if (auto pointerLikeType = type->As<PointerLikeType>()) + auto baseType = expr->type; + if (auto pointerLikeType = baseType->As<PointerLikeType>()) { - type = QualType(pointerLikeType->elementType); + auto elementType = QualType(pointerLikeType->elementType); + elementType.IsLeftValue = baseType.IsLeftValue; auto derefExpr = new DerefExpr(); derefExpr->base = expr; - derefExpr->type = QualType(pointerLikeType->elementType); - - // TODO(tfoley): deal with l-value-ness here + derefExpr->type = elementType; expr = derefExpr; continue; diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index fb9968232..ba1b2177a 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -2383,7 +2383,6 @@ struct EmitVisitor case kIROp_FieldAddress: case kIROp_getElementPtr: case kIROp_Specialize: - case kIROp_BufferElementRef: return true; } @@ -2536,25 +2535,6 @@ struct EmitVisitor return true; } - bool isDerefBaseImplicit( - EmitContext* /*context*/, - IRInst* inst) - { - auto type = inst->getDataType(); - - if(as<IRUniformParameterGroupType>(type) && !as<IRParameterBlockType>(type)) - { - // TODO: we need to be careful here, because - // HLSL shader model 6 allows these as explicit - // types. - return true; - } - - return false; - } - - - void emitIROperand( EmitContext* ctx, IRInst* inst, @@ -3645,13 +3625,16 @@ struct EmitVisitor IRFieldExtract* fieldExtract = (IRFieldExtract*) inst; - if (!isDerefBaseImplicit(ctx, fieldExtract->getBase())) - { - auto prec = kEOp_Postfix; - needClose = maybeEmitParens(outerPrec, prec); + auto prec = kEOp_Postfix; + needClose = maybeEmitParens(outerPrec, prec); - emitIROperand(ctx, fieldExtract->getBase(), mode, leftSide(outerPrec, prec)); - emit("."); + auto base = fieldExtract->getBase(); + emitIROperand(ctx, base, mode, leftSide(outerPrec, prec)); + emit("."); + if(getTarget(ctx) == CodeGenTarget::GLSL + && as<IRUniformParameterGroupType>(base->getDataType())) + { + emit("_data."); } emit(getIRName(fieldExtract->getField())); } @@ -3663,15 +3646,17 @@ struct EmitVisitor IRFieldAddress* ii = (IRFieldAddress*) inst; - if (!isDerefBaseImplicit(ctx, ii->getBase())) - { - auto prec = kEOp_Postfix; - needClose = maybeEmitParens(outerPrec, prec); + auto prec = kEOp_Postfix; + needClose = maybeEmitParens(outerPrec, prec); - emitIROperand(ctx, ii->getBase(), mode, leftSide(outerPrec, prec)); - emit("."); + auto base = ii->getBase(); + emitIROperand(ctx, base, mode, leftSide(outerPrec, prec)); + emit("."); + if(getTarget(ctx) == CodeGenTarget::GLSL + && as<IRUniformParameterGroupType>(base->getDataType())) + { + emit("_data."); } - emit(getIRName(ii->getField())); } break; @@ -3774,7 +3759,15 @@ struct EmitVisitor break; case kIROp_Load: - emitIROperand(ctx, inst->getOperand(0), mode, outerPrec); + { + auto base = inst->getOperand(0); + emitIROperand(ctx, base, mode, outerPrec); + if(getTarget(ctx) == CodeGenTarget::GLSL + && as<IRUniformParameterGroupType>(base->getDataType())) + { + emit("._data"); + } + } break; case kIROp_Store: @@ -3794,39 +3787,6 @@ struct EmitVisitor } break; - case kIROp_BufferLoad: - case kIROp_BufferElementRef: - { - auto prec = kEOp_Postfix; - needClose = maybeEmitParens(outerPrec, prec); - - emitIROperand(ctx, inst->getOperand(0), mode, leftSide(outerPrec, prec)); - emit("["); - emitIROperand(ctx, inst->getOperand(1), mode, kEOp_General); - emit("]"); - } - break; - - case kIROp_BufferStore: - { - auto precAssign = kEOp_Assign; - needClose = maybeEmitParens(outerPrec, precAssign); - - auto outerPrecSubscript = precAssign; - auto precSubscript = kEOp_Postfix; - bool needCloseSubscript = maybeEmitParens(outerPrecSubscript, precSubscript); - - emitIROperand(ctx, inst->getOperand(0), mode, leftSide(outerPrecSubscript, precSubscript)); - emit("["); - emitIROperand(ctx, inst->getOperand(1), mode, kEOp_General); - emit("]"); - maybeCloseParens(needCloseSubscript); - - emit(" = "); - emitIROperand(ctx, inst->getOperand(2), mode, rightSide(outerPrec, precAssign)); - } - break; - case kIROp_GroupMemoryBarrierWithGroupSync: emit("GroupMemoryBarrierWithGroupSync()"); break; @@ -5618,63 +5578,19 @@ struct EmitVisitor } } - void emitHLSLParameterBlock( - EmitContext* ctx, - IRGlobalVar* varDecl, - IRParameterBlockType* type) - { - emit("cbuffer "); - - // Generate a dummy name for the block - emit("_S"); - Emit(ctx->shared->uniqueIDCounter++); - - auto varLayout = getVarLayout(ctx, varDecl); - SLANG_RELEASE_ASSERT(varLayout); - - EmitVarChain blockChain(varLayout); - - EmitVarChain containerChain = blockChain; - EmitVarChain elementChain = blockChain; - - auto typeLayout = varLayout->typeLayout; - if( auto parameterGroupTypeLayout = typeLayout.As<ParameterGroupTypeLayout>() ) - { - containerChain = EmitVarChain(parameterGroupTypeLayout->containerVarLayout, &blockChain); - elementChain = EmitVarChain(parameterGroupTypeLayout->elementVarLayout, &blockChain); - - typeLayout = parameterGroupTypeLayout->elementVarLayout->getTypeLayout(); - } - - emitHLSLRegisterSemantic(LayoutResourceKind::ConstantBuffer, &containerChain); - - emit("\n{\n"); - indent(); - - auto elementType = type->getElementType(); - - - emitIRType(ctx, elementType, getIRName(varDecl)); - - emitHLSLParameterGroupFieldLayoutSemantics(&elementChain); - emit(";\n"); - - dedent(); - emit("}\n"); - } - void emitHLSLParameterGroup( EmitContext* ctx, IRGlobalVar* varDecl, IRUniformParameterGroupType* type) { - if(auto parameterBlockType = as<IRParameterBlockType>(type)) + if(as<IRTextureBufferType>(type)) { - emitHLSLParameterBlock(ctx, varDecl, parameterBlockType); - return; + emit("tbuffer "); + } + else + { + emit("cbuffer "); } - - emit("cbuffer "); emit(getIRName(varDecl)); auto varLayout = getVarLayout(ctx, varDecl); @@ -5701,111 +5617,37 @@ struct EmitVisitor auto elementType = type->getElementType(); - if(auto structType = as<IRStructType>(elementType)) - { - auto structTypeLayout = typeLayout.As<StructTypeLayout>(); - SLANG_RELEASE_ASSERT(structTypeLayout); - - UInt fieldIndex = 0; - for(auto ff : structType->getFields()) - { - // TODO: need a plan to deal with the case where the IR-level - // `struct` type might not match the high-level type, so that - // the numbering of fields is different. - // - // The right plan is probably to require that the lowering pass - // create a fresh layout for any type/variable that it splits - // in this fashion, so that the layout information it attaches - // can always be assumed to apply to the actual instruciton. - // - - auto fieldLayout = structTypeLayout->fields[fieldIndex++]; - - auto fieldKey = ff->getKey(); - auto fieldType = ff->getFieldType(); - - // Fields of `void` type aren't valid in HLSL/GLSL. - // - // TODO: legalization should get rid of any fields that have - // empty, or effectively empty types (e.g., emptry structs - // should be translated over to `void`). - if(as<IRVoidType>(fieldType)) - continue; - - emitIRVarModifiers(ctx, fieldLayout, fieldKey, fieldType); - - emitIRType(ctx, fieldType, getIRName(fieldKey)); - - emitHLSLParameterGroupFieldLayoutSemantics(fieldLayout, &elementChain); - - emit(";\n"); - } - } - else - { - // TODO: during legalization we should turn `ParameterGroup<X>` where `X` - // is not a `struct` type into `ParameterGroup<S>` where `S` is defined - // as something like `struct S { X _; };` - // - emit("/* unexpected */"); - } + emitIRType(ctx, elementType, getIRName(varDecl)); + emit(";\n"); dedent(); emit("}\n"); } - void emitGLSLParameterBlock( - EmitContext* ctx, - IRGlobalVar* varDecl, - IRParameterBlockType* type) + void emitArrayBrackets( + EmitContext* ctx, + IRType* type) { - auto varLayout = getVarLayout(ctx, varDecl); - SLANG_RELEASE_ASSERT(varLayout); - - EmitVarChain blockChain(varLayout); - - EmitVarChain containerChain = blockChain; - EmitVarChain elementChain = blockChain; + SLANG_UNUSED(ctx); - auto typeLayout = varLayout->typeLayout; - if( auto parameterGroupTypeLayout = typeLayout.As<ParameterGroupTypeLayout>() ) + if(auto arrayType = as<IRArrayType>(type)) { - containerChain = EmitVarChain(parameterGroupTypeLayout->containerVarLayout, &blockChain); - elementChain = EmitVarChain(parameterGroupTypeLayout->elementVarLayout, &blockChain); - - typeLayout = parameterGroupTypeLayout->elementVarLayout->getTypeLayout(); + emit("["); + EmitVal(arrayType->getElementCount(), kEOp_General); + emit("]"); + } + else if(auto unsizedArrayType = as<IRUnsizedArrayType>(type)) + { + emit("[]"); } - - emitGLSLLayoutQualifier(LayoutResourceKind::DescriptorTableSlot, &containerChain); - emit("layout(std140) uniform "); - - // Generate a dummy name for the block - emit("_S"); - Emit(ctx->shared->uniqueIDCounter++); - - emit("\n{\n"); - indent(); - - auto elementType = type->getElementType(); - - emitIRType(ctx, elementType, getIRName(varDecl)); - emit(";\n"); - - dedent(); - emit("};\n"); } + void emitGLSLParameterGroup( EmitContext* ctx, IRGlobalVar* varDecl, IRUniformParameterGroupType* type) { - if(auto parameterBlockType = as<IRParameterBlockType>(type)) - { - emitGLSLParameterBlock(ctx, varDecl, parameterBlockType); - return; - } - auto varLayout = getVarLayout(ctx, varDecl); SLANG_RELEASE_ASSERT(varLayout); @@ -5814,7 +5656,7 @@ struct EmitVisitor EmitVarChain containerChain = blockChain; EmitVarChain elementChain = blockChain; - auto typeLayout = varLayout->typeLayout; + auto typeLayout = varLayout->typeLayout->unwrapArray(); if( auto parameterGroupTypeLayout = typeLayout.As<ParameterGroupTypeLayout>() ) { containerChain = EmitVarChain(parameterGroupTypeLayout->containerVarLayout, &blockChain); @@ -5841,71 +5683,28 @@ struct EmitVisitor emit("layout(std140) uniform "); } - emit(getIRName(varDecl)); + // Generate a dummy name for the block + emit("_S"); + Emit(ctx->shared->uniqueIDCounter++); emit("\n{\n"); indent(); auto elementType = type->getElementType(); - if(auto structType = as<IRStructType>(elementType)) - { - auto structTypeLayout = typeLayout.As<StructTypeLayout>(); - SLANG_RELEASE_ASSERT(structTypeLayout); - - UInt fieldIndex = 0; - for(auto ff : structType->getFields()) - { - // TODO: need a plan to deal with the case where the IR-level - // `struct` type might not match the high-level type, so that - // the numbering of fields is different. - // - // The right plan is probably to require that the lowering pass - // create a fresh layout for any type/variable that it splits - // in this fashion, so that the layout information it attaches - // can always be assumed to apply to the actual instruciton. - // - - auto fieldLayout = structTypeLayout->fields[fieldIndex++]; - - auto fieldKey = ff->getKey(); - auto fieldType = ff->getFieldType(); - if(as<IRVoidType>(fieldType)) - continue; - - // Note: we will emit matrix-layout modifiers here, but - // we will refrain from emitting other modifiers that - // might not be appropriate to the context (e.g., we - // shouldn't go emitting `uniform` just because these - // things are uniform...). - // - // TODO: we need a more refined set of modifiers that - // we should allow on fields, because we might end - // up supporting layout that isn't the default for - // the given block type (e.g., something other than - // `std140` for a uniform block). - // - emitIRMatrixLayoutModifiers(ctx, fieldLayout); - - emitIRType(ctx, fieldType, getIRName(fieldKey)); + emitIRType(ctx, elementType, "_data"); + emit(";\n"); -// emitHLSLParameterGroupFieldLayoutSemantics(layout, fieldLayout); + dedent(); + emit("} "); - emit(";\n"); - } - } - else - { - emit("/* unexpected */"); - } + emit(getIRName(varDecl)); - // TODO: we should consider always giving parameter blocks - // names when outputting GLSL, since that shouldn't affect - // the semantics of things, and will reduce the risk of - // collisions in the global namespace... + // If the underlying variable was an array (or array of arrays, etc.) + // we need to emit all those array brackets here. + emitArrayBrackets(ctx, varDecl->getDataType()->getValueType()); - dedent(); - emit("};\n"); + emit(";\n"); } void emitIRParameterGroup( @@ -6025,19 +5824,14 @@ struct EmitVisitor auto elementType = structuredBufferType->getElementType(); - emitIRType(ctx, elementType, getIRName(varDecl) + "[]"); + emitIRType(ctx, elementType, "_data[]"); emit(";\n"); dedent(); - emit("}"); + emit("} "); - // TODO: we need to consider the case where the type of the variable is - // an *array* of structured buffers, in which case we need to declare - // the block as an array too. - // - // The main challenge here is that then the block will have a name, - // and also the field inside the block will have a name, so that when - // the user had written `a[i][j]` we now need to emit `a[i].someName[j]`. + emit(getIRName(varDecl)); + emitArrayBrackets(ctx, varDecl->getDataType()->getValueType()); emit(";\n"); } @@ -6084,20 +5878,13 @@ struct EmitVisitor emit("\n{\n"); indent(); - emit("uint "); - emit(getIRName(varDecl)); - emit("[];\n"); + emit("uint _data[];\n"); dedent(); - emit("}"); + emit("} "); - // TODO: we need to consider the case where the type of the variable is - // an *array* of structured buffers, in which case we need to declare - // the block as an array too. - // - // The main challenge here is that then the block will have a name, - // and also the field inside the block will have a name, so that when - // the user had written `a[i][j]` we now need to emit `a[i].someName[j]`. + emit(getIRName(varDecl)); + emitArrayBrackets(ctx, varDecl->getDataType()->getValueType()); emit(";\n"); } @@ -6129,6 +5916,16 @@ struct EmitVisitor Emit("}\n"); } + // When a global shader parameter represents a "parameter group" + // (either a constant buffer or a parameter block with non-resource + // data in it), we will prefer to emit it as an ordinary `cbuffer` + // declaration or `uniform` block, even when emitting HLSL for + // D3D profiles that support the explicit `ConstantBuffer<T>` type. + // + // Alternatively, we could make this choice based on profile, and + // prefer `ConstantBuffer<T>` on profiles that support it and/or when + // the input code used that syntax. + // if (auto paramBlockType = as<IRUniformParameterGroupType>(varType)) { emitIRParameterGroup( @@ -6140,8 +5937,31 @@ struct EmitVisitor if(getTarget(ctx) == CodeGenTarget::GLSL) { - // When outputting GLSL, we need to transform any declaration of - // a `*StructuredBuffer<T>` into an ordinary `buffer` declaration. + // There are a number of types that are (or can be) + // "first-class" in D3D HLSL, but are second-class in GLSL in + // that they require explicit global declarations for each value/object, + // and don't support declaration as ordinary variables. + // + // This includes constant buffers (`uniform` blocks) and well as + // structured and byte-address buffers (both mapping to `buffer` blocks). + // + // We intercept these types, and arrays thereof, to produce the required + // global declarations. This assumes that earlier "legalization" passes + // already performed the work of pulling fields with these types out of + // aggregates. + // + // Note: this also assumes that these types are not used as function + // parameters/results, local variables, etc. Additional legalization + // steps are required to guarantee these conditions. + // + if (auto paramBlockType = as<IRUniformParameterGroupType>(unwrapArray(varType))) + { + emitGLSLParameterGroup( + ctx, + varDecl, + paramBlockType); + return; + } if( auto structuredBufferType = as<IRHLSLStructuredBufferTypeBase>(unwrapArray(varType)) ) { emitIRStructuredBuffer_GLSL( @@ -6150,9 +5970,6 @@ struct EmitVisitor structuredBufferType); return; } - - // When outputting GLSL, we need to transform any declaration of - // a `*ByteAddressBuffer<T>` into an ordinary `buffer` declaration. if( auto byteAddressBufferType = as<IRByteAddressBufferTypeBase>(unwrapArray(varType)) ) { emitIRByteAddressBuffer_GLSL( @@ -6166,7 +5983,15 @@ struct EmitVisitor // when outputting GLSL (well, except in the case where they // actually *require* redeclaration...). // - // TODO: can we detect this more robustly? + // Note: these won't be variables the user declare explicitly + // in their code, but rather variables that we generated as + // part of legalizing the varying input/output signature of + // an entry point for GL/Vulkan. + // + // TODO: This could be handled more robustly by attaching an + // appropriate decoration to these variables to indicate their + // purpose. + // if(getText(varDecl->mangledName).StartsWith("gl_")) { // The variable represents an OpenGL system value, diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 950931fc2..98b50e574 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -18,26 +18,26 @@ __magic_type(HLSLByteAddressBufferType) __intrinsic_type($(kIROp_HLSLByteAddressBufferType))
struct ByteAddressBuffer
{
- __target_intrinsic(glsl, "$1 = $0.length()")
+ __target_intrinsic(glsl, "$1 = $0._data.length()")
void GetDimensions(
out uint dim);
- __target_intrinsic(glsl, "$0[$1]")
+ __target_intrinsic(glsl, "$0._data[$1]")
uint Load(int location);
uint Load(int location, out uint status);
- __target_intrinsic(glsl, "uvec2($0[$1], $0[$1+1])")
+ __target_intrinsic(glsl, "uvec2($0._data[$1], $0._data[$1+1])")
uint2 Load2(int location);
uint2 Load2(int location, out uint status);
- __target_intrinsic(glsl, "uvec3($0[$1], $0[$1+1], $0[$1+2])")
+ __target_intrinsic(glsl, "uvec3($0._data[$1], $0._data[$1+1], $0._data[$1+2])")
uint3 Load3(int location);
uint3 Load3(int location, out uint status);
- __target_intrinsic(glsl, "uvec4($0[$1], $0[$1+1], $0[$1+2], $0[$1+3])")
+ __target_intrinsic(glsl, "uvec4($0._data[$1], $0._data[$1+1], $0._data[$1+2], $0._data[$1+3])")
uint4 Load4(int location);
uint4 Load4(int location, out uint status);
@@ -55,7 +55,11 @@ struct StructuredBuffer T Load(int location);
T Load(int location, out uint status);
- __subscript(uint index) -> T { __intrinsic_op(bufferLoad) get; };
+ __subscript(uint index) -> T
+ {
+ __target_intrinsic(glsl, "$0._data[$1]")
+ get;
+ };
};
__generic<T>
@@ -105,133 +109,133 @@ struct $(item.name) // Note(tfoley): supports all operations from `ByteAddressBuffer`
// TODO(tfoley): can this be made a sub-type?
- __target_intrinsic(glsl, "$1 = $0.length()")
+ __target_intrinsic(glsl, "$1 = $0._data.length()")
void GetDimensions(
out uint dim);
- __target_intrinsic(glsl, "$0[$1]")
+ __target_intrinsic(glsl, "$0._data[$1]")
uint Load(int location);
uint Load(int location, out uint status);
- __target_intrinsic(glsl, "uvec2($0[$1], $0[$1+4])")
+ __target_intrinsic(glsl, "uvec2($0._data[$1], $0._data[$1+4])")
uint2 Load2(int location);
uint2 Load2(int location, out uint status);
- __target_intrinsic(glsl, "uvec3($0[$1], $0[$1+4], $0[$1+8])")
+ __target_intrinsic(glsl, "uvec3($0._data[$1], $0._data[$1+4], $0._data[$1+8])")
uint3 Load3(int location);
uint3 Load3(int location, out uint status);
- __target_intrinsic(glsl, "uvec4($0[$1], $0[$1+4], $0[$1+8], $0[$1+12])")
+ __target_intrinsic(glsl, "uvec4($0._data[$1], $0._data[$1+4], $0._data[$1+8], $0._data[$1+12])")
uint4 Load4(int location);
uint4 Load4(int location, out uint status);
// Added operations:
- __target_intrinsic(glsl, "($3 = atomicAdd($0[$1], $2))")
+ __target_intrinsic(glsl, "($3 = atomicAdd($0._data[$1], $2))")
void InterlockedAdd(
UINT dest,
UINT value,
out UINT original_value);
- __target_intrinsic(glsl, "atomicAdd($0[$1], $2)")
+ __target_intrinsic(glsl, "atomicAdd($0._data[$1], $2)")
void InterlockedAdd(
UINT dest,
UINT value);
- __target_intrinsic(glsl, "($3 = atomicAnd($0[$1], $2))")
+ __target_intrinsic(glsl, "($3 = atomicAnd($0._data[$1], $2))")
void InterlockedAnd(
UINT dest,
UINT value,
out UINT original_value);
- __target_intrinsic(glsl, "atomicAnd($0[$1], $2)")
+ __target_intrinsic(glsl, "atomicAnd($0._data[$1], $2)")
void InterlockedAnd(
UINT dest,
UINT value);
- __target_intrinsic(glsl, "($4 = atomicCompSwap($0[$1], $2, $3))")
+ __target_intrinsic(glsl, "($4 = atomicCompSwap($0._data[$1], $2, $3))")
void InterlockedCompareExchange(
UINT dest,
UINT compare_value,
UINT value,
out UINT original_value);
- __target_intrinsic(glsl, "atomicCompSwap($0[$1], $2, $3)")
+ __target_intrinsic(glsl, "atomicCompSwap($0._data[$1], $2, $3)")
void InterlockedCompareStore(
UINT dest,
UINT compare_value,
UINT value);
- __target_intrinsic(glsl, "($3 = atomicExchange($0[$1], $2))")
+ __target_intrinsic(glsl, "($3 = atomicExchange($0._data[$1], $2))")
void InterlockedExchange(
UINT dest,
UINT value,
out UINT original_value);
- __target_intrinsic(glsl, "($3 = atomicMax($0[$1], $2))")
+ __target_intrinsic(glsl, "($3 = atomicMax($0._data[$1], $2))")
void InterlockedMax(
UINT dest,
UINT value,
out UINT original_value);
- __target_intrinsic(glsl, "atomicMax($0[$1], $2)")
+ __target_intrinsic(glsl, "atomicMax($0._data[$1], $2)")
void InterlockedMax(
UINT dest,
UINT value);
- __target_intrinsic(glsl, "($3 = atomicMin($0[$1], $2))")
+ __target_intrinsic(glsl, "($3 = atomicMin($0._data[$1], $2))")
void InterlockedMin(
UINT dest,
UINT value,
out UINT original_value);
- __target_intrinsic(glsl, "atomicMin($0[$1], $2)")
+ __target_intrinsic(glsl, "atomicMin($0._data[$1], $2)")
void InterlockedMin(
UINT dest,
UINT value);
- __target_intrinsic(glsl, "($3 = atomicOr($0[$1], $2))")
+ __target_intrinsic(glsl, "($3 = atomicOr($0._data[$1], $2))")
void InterlockedOr(
UINT dest,
UINT value,
out UINT original_value);
- __target_intrinsic(glsl, "atomicOr($0[$1], $2)")
+ __target_intrinsic(glsl, "atomicOr($0._data[$1], $2)")
void InterlockedOr(
UINT dest,
UINT value);
- __target_intrinsic(glsl, "($3 = atomicXor($0[$1], $2))")
+ __target_intrinsic(glsl, "($3 = atomicXor($0._data[$1], $2))")
void InterlockedXor(
UINT dest,
UINT value,
out UINT original_value);
- __target_intrinsic(glsl, "atomicXor($0[$1], $2)")
+ __target_intrinsic(glsl, "atomicXor($0._data[$1], $2)")
void InterlockedXor(
UINT dest,
UINT value);
- __target_intrinsic(glsl, "$0[$1] = $2")
+ __target_intrinsic(glsl, "$0._data[$1] = $2")
void Store(
uint address,
uint value);
- __target_intrinsic(glsl, "$0[$1] = $2.x, $0[$1+4] = $2.y")
+ __target_intrinsic(glsl, "$0._data[$1] = $2.x, $0._data[$1+4] = $2.y")
void Store2(
uint address,
uint2 value);
- __target_intrinsic(glsl, "$0[$1] = $2.x, $0[$1+4] = $2.y, $0[$1+8] = $2.z")
+ __target_intrinsic(glsl, "$0._data[$1] = $2.x, $0._data[$1+4] = $2.y, $0._data[$1+8] = $2.z")
void Store3(
uint address,
uint3 value);
- __target_intrinsic(glsl, "$0[$1] = $2.x, $0[$1+4] = $2.y, $0[$1+8] = $2.z, $0[$1+12] = $2.w")
+ __target_intrinsic(glsl, "$0._data[$1] = $2.x, $0._data[$1+4] = $2.y, $0._data[$1+8] = $2.z, $0._data[$1+12] = $2.w")
void Store4(
uint address,
uint4 value);
@@ -270,11 +274,11 @@ struct $(item.name) T Load(int location);
T Load(int location, out uint status);
- __subscript(uint index) -> T
- {
- __intrinsic_op(bufferElementRef)
+ __subscript(uint index) -> T
+ {
+ __target_intrinsic(glsl, "$0._data[$1]")
ref;
- }
+ }
};
${{{{
diff --git a/source/slang/hlsl.meta.slang.h b/source/slang/hlsl.meta.slang.h index 8d908c13d..ea21a0fde 100644 --- a/source/slang/hlsl.meta.slang.h +++ b/source/slang/hlsl.meta.slang.h @@ -24,26 +24,26 @@ SLANG_SPLICE(kIROp_HLSLByteAddressBufferType SLANG_RAW(")\n") SLANG_RAW("struct ByteAddressBuffer\n") SLANG_RAW("{\n") -SLANG_RAW(" __target_intrinsic(glsl, \"$1 = $0.length()\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"$1 = $0._data.length()\")\n") SLANG_RAW(" void GetDimensions(\n") SLANG_RAW(" out uint dim);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"$0[$1]\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"$0._data[$1]\")\n") SLANG_RAW(" uint Load(int location);\n") SLANG_RAW("\n") SLANG_RAW(" uint Load(int location, out uint status);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"uvec2($0[$1], $0[$1+1])\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"uvec2($0._data[$1], $0._data[$1+1])\")\n") SLANG_RAW(" uint2 Load2(int location);\n") SLANG_RAW("\n") SLANG_RAW(" uint2 Load2(int location, out uint status);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"uvec3($0[$1], $0[$1+1], $0[$1+2])\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"uvec3($0._data[$1], $0._data[$1+1], $0._data[$1+2])\")\n") SLANG_RAW(" uint3 Load3(int location);\n") SLANG_RAW("\n") SLANG_RAW(" uint3 Load3(int location, out uint status);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"uvec4($0[$1], $0[$1+1], $0[$1+2], $0[$1+3])\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"uvec4($0._data[$1], $0._data[$1+1], $0._data[$1+2], $0._data[$1+3])\")\n") SLANG_RAW(" uint4 Load4(int location);\n") SLANG_RAW("\n") SLANG_RAW(" uint4 Load4(int location, out uint status);\n") @@ -64,7 +64,11 @@ SLANG_RAW("\n") SLANG_RAW(" T Load(int location);\n") SLANG_RAW(" T Load(int location, out uint status);\n") SLANG_RAW("\n") -SLANG_RAW(" __subscript(uint index) -> T { __intrinsic_op(bufferLoad) get; };\n") +SLANG_RAW(" __subscript(uint index) -> T\n") +SLANG_RAW(" {\n") +SLANG_RAW(" __target_intrinsic(glsl, \"$0._data[$1]\")\n") +SLANG_RAW(" get;\n") +SLANG_RAW(" };\n") SLANG_RAW("};\n") SLANG_RAW("\n") SLANG_RAW("__generic<T>\n") @@ -132,133 +136,133 @@ SLANG_RAW("{\n") SLANG_RAW(" // Note(tfoley): supports all operations from `ByteAddressBuffer`\n") SLANG_RAW(" // TODO(tfoley): can this be made a sub-type?\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"$1 = $0.length()\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"$1 = $0._data.length()\")\n") SLANG_RAW(" void GetDimensions(\n") SLANG_RAW(" out uint dim);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"$0[$1]\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"$0._data[$1]\")\n") SLANG_RAW(" uint Load(int location);\n") SLANG_RAW("\n") SLANG_RAW(" uint Load(int location, out uint status);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"uvec2($0[$1], $0[$1+4])\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"uvec2($0._data[$1], $0._data[$1+4])\")\n") SLANG_RAW(" uint2 Load2(int location);\n") SLANG_RAW("\n") SLANG_RAW(" uint2 Load2(int location, out uint status);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"uvec3($0[$1], $0[$1+4], $0[$1+8])\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"uvec3($0._data[$1], $0._data[$1+4], $0._data[$1+8])\")\n") SLANG_RAW(" uint3 Load3(int location);\n") SLANG_RAW("\n") SLANG_RAW(" uint3 Load3(int location, out uint status);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"uvec4($0[$1], $0[$1+4], $0[$1+8], $0[$1+12])\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"uvec4($0._data[$1], $0._data[$1+4], $0._data[$1+8], $0._data[$1+12])\")\n") SLANG_RAW(" uint4 Load4(int location);\n") SLANG_RAW("\n") SLANG_RAW(" uint4 Load4(int location, out uint status);\n") SLANG_RAW("\n") SLANG_RAW(" // Added operations:\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicAdd($0[$1], $2))\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicAdd($0._data[$1], $2))\")\n") SLANG_RAW(" void InterlockedAdd(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value,\n") SLANG_RAW(" out UINT original_value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"atomicAdd($0[$1], $2)\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"atomicAdd($0._data[$1], $2)\")\n") SLANG_RAW(" void InterlockedAdd(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicAnd($0[$1], $2))\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicAnd($0._data[$1], $2))\")\n") SLANG_RAW(" void InterlockedAnd(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value,\n") SLANG_RAW(" out UINT original_value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"atomicAnd($0[$1], $2)\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"atomicAnd($0._data[$1], $2)\")\n") SLANG_RAW(" void InterlockedAnd(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"($4 = atomicCompSwap($0[$1], $2, $3))\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"($4 = atomicCompSwap($0._data[$1], $2, $3))\")\n") SLANG_RAW(" void InterlockedCompareExchange(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT compare_value,\n") SLANG_RAW(" UINT value,\n") SLANG_RAW(" out UINT original_value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"atomicCompSwap($0[$1], $2, $3)\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"atomicCompSwap($0._data[$1], $2, $3)\")\n") SLANG_RAW(" void InterlockedCompareStore(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT compare_value,\n") SLANG_RAW(" UINT value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicExchange($0[$1], $2))\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicExchange($0._data[$1], $2))\")\n") SLANG_RAW(" void InterlockedExchange(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value,\n") SLANG_RAW(" out UINT original_value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicMax($0[$1], $2))\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicMax($0._data[$1], $2))\")\n") SLANG_RAW(" void InterlockedMax(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value,\n") SLANG_RAW(" out UINT original_value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"atomicMax($0[$1], $2)\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"atomicMax($0._data[$1], $2)\")\n") SLANG_RAW(" void InterlockedMax(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicMin($0[$1], $2))\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicMin($0._data[$1], $2))\")\n") SLANG_RAW(" void InterlockedMin(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value,\n") SLANG_RAW(" out UINT original_value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"atomicMin($0[$1], $2)\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"atomicMin($0._data[$1], $2)\")\n") SLANG_RAW(" void InterlockedMin(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicOr($0[$1], $2))\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicOr($0._data[$1], $2))\")\n") SLANG_RAW(" void InterlockedOr(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value,\n") SLANG_RAW(" out UINT original_value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"atomicOr($0[$1], $2)\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"atomicOr($0._data[$1], $2)\")\n") SLANG_RAW(" void InterlockedOr(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicXor($0[$1], $2))\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"($3 = atomicXor($0._data[$1], $2))\")\n") SLANG_RAW(" void InterlockedXor(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value,\n") SLANG_RAW(" out UINT original_value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"atomicXor($0[$1], $2)\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"atomicXor($0._data[$1], $2)\")\n") SLANG_RAW(" void InterlockedXor(\n") SLANG_RAW(" UINT dest,\n") SLANG_RAW(" UINT value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"$0[$1] = $2\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"$0._data[$1] = $2\")\n") SLANG_RAW(" void Store(\n") SLANG_RAW(" uint address,\n") SLANG_RAW(" uint value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"$0[$1] = $2.x, $0[$1+4] = $2.y\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"$0._data[$1] = $2.x, $0._data[$1+4] = $2.y\")\n") SLANG_RAW(" void Store2(\n") SLANG_RAW(" uint address,\n") SLANG_RAW(" uint2 value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"$0[$1] = $2.x, $0[$1+4] = $2.y, $0[$1+8] = $2.z\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"$0._data[$1] = $2.x, $0._data[$1+4] = $2.y, $0._data[$1+8] = $2.z\")\n") SLANG_RAW(" void Store3(\n") SLANG_RAW(" uint address,\n") SLANG_RAW(" uint3 value);\n") SLANG_RAW("\n") -SLANG_RAW(" __target_intrinsic(glsl, \"$0[$1] = $2.x, $0[$1+4] = $2.y, $0[$1+8] = $2.z, $0[$1+12] = $2.w\")\n") +SLANG_RAW(" __target_intrinsic(glsl, \"$0._data[$1] = $2.x, $0._data[$1+4] = $2.y, $0._data[$1+8] = $2.z, $0._data[$1+12] = $2.w\")\n") SLANG_RAW(" void Store4(\n") SLANG_RAW(" uint address,\n") SLANG_RAW(" uint4 value);\n") @@ -306,11 +310,11 @@ SLANG_RAW("\n") SLANG_RAW(" T Load(int location);\n") SLANG_RAW(" T Load(int location, out uint status);\n") SLANG_RAW("\n") -SLANG_RAW("\t__subscript(uint index) -> T\n") -SLANG_RAW("\t{\n") -SLANG_RAW(" __intrinsic_op(bufferElementRef)\n") +SLANG_RAW(" __subscript(uint index) -> T\n") +SLANG_RAW(" {\n") +SLANG_RAW(" __target_intrinsic(glsl, \"$0._data[$1]\")\n") SLANG_RAW(" ref;\n") -SLANG_RAW("\t}\n") +SLANG_RAW(" }\n") SLANG_RAW("};\n") SLANG_RAW("\n") diff --git a/source/slang/ir-inst-defs.h b/source/slang/ir-inst-defs.h index 8f997cbe2..09c11ed16 100644 --- a/source/slang/ir-inst-defs.h +++ b/source/slang/ir-inst-defs.h @@ -217,10 +217,6 @@ INST(Var, var, 0, 0) INST(Load, load, 1, 0) INST(Store, store, 2, 0) -INST(BufferLoad, bufferLoad, 2, 0) -INST(BufferStore, bufferStore, 3, 0) -INST(BufferElementRef, bufferElementRef, 2, 0) - INST(FieldExtract, get_field, 2, 0) INST(FieldAddress, get_field_addr, 2, 0) diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 599b02ea7..2f16f4ebc 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -3576,7 +3576,6 @@ namespace Slang case kIROp_makeArray: case kIROp_makeStruct: case kIROp_Load: // We are ignoring the possibility of loads from bad addresses, or `volatile` loads - case kIROp_BufferLoad: case kIROp_FieldExtract: case kIROp_FieldAddress: case kIROp_getElement: diff --git a/source/slang/type-layout.cpp b/source/slang/type-layout.cpp index 8fc48fe4f..2d21d7aef 100644 --- a/source/slang/type-layout.cpp +++ b/source/slang/type-layout.cpp @@ -2276,6 +2276,17 @@ RefPtr<TypeLayout> CreateTypeLayout( return typeLayout; } +RefPtr<TypeLayout> TypeLayout::unwrapArray() +{ + TypeLayout* typeLayout = this; + + while(auto arrayTypeLayout = dynamic_cast<ArrayTypeLayout*>(typeLayout)) + typeLayout = arrayTypeLayout->elementTypeLayout; + + return typeLayout; +} + + RefPtr<GlobalGenericParamDecl> GenericParamTypeLayout::getGlobalGenericParamDecl() { auto declRefType = type->AsDeclRefType(); diff --git a/source/slang/type-layout.h b/source/slang/type-layout.h index fa874cb80..6f6dad055 100644 --- a/source/slang/type-layout.h +++ b/source/slang/type-layout.h @@ -354,6 +354,13 @@ public: info.count = count; addResourceUsage(info); } + + /// "Unwrap" any layers of array-ness from this type layout. + /// + /// If this is an `ArrayTypeLayout`, returns the result of unwrapping the elemnt type layout. + /// Otherwise, returns this type layout. + /// + RefPtr<TypeLayout> unwrapArray(); }; typedef unsigned int VarLayoutFlags; diff --git a/source/slang/vm.cpp b/source/slang/vm.cpp index fa59a741b..0f79c763b 100644 --- a/source/slang/vm.cpp +++ b/source/slang/vm.cpp @@ -846,72 +846,6 @@ void resumeThread( } break; - case kIROp_BufferLoad: - { - VMType type = decodeType(frame, &ip); - UInt argCount = decodeUInt(&ip); - void* argPtrs[16] = { 0 }; - for( UInt aa = 0; aa < argCount; ++aa ) - { - void* argPtr = decodeOperandPtr<void>(frame, &ip); - argPtrs[aa] = argPtr; - } - - void* dest = decodeOperandPtr<void>(frame, &ip); - - char* bufferData = *(char**)argPtrs[0]; - uint32_t index = *(uint32_t*)argPtrs[1]; - - auto size = type.getSize(); - char* elementData = bufferData + index*size; - memcpy(dest, elementData, size); - } - break; - - case kIROp_BufferStore: - { - VMType resultType = decodeType(frame, &ip); - /*UInt argCount = */decodeUInt(&ip); - - char* bufferData = decodeOperand<char*>(frame, &ip); - uint32_t index = decodeOperand<uint32_t>(frame, &ip); - - auto srcPtrAndType = decodeOperandPtrAndType(frame, &ip); - void* srcPtr = srcPtrAndType.ptr; - VMType type = srcPtrAndType.type; - - auto size = type.getSize(); - char* elementData = bufferData + index*size; - memcpy(elementData, srcPtr, size); - } - break; - - case kIROp_BufferElementRef: - { - VMType ptrType = decodeType(frame, &ip); - VMType type = ((VMPtrTypeImpl*)ptrType.getImpl())->base; - - UInt argCount = decodeUInt(&ip); - void* argPtrs[16] = { 0 }; - for( UInt aa = 0; aa < argCount; ++aa ) - { - void* argPtr = decodeOperandPtr<void>(frame, &ip); - argPtrs[aa] = argPtr; - } - - void* dest = decodeOperandPtr<void>(frame, &ip); - - char* bufferData = *(char**)argPtrs[0]; - uint32_t index = *(uint32_t*)argPtrs[1]; - - auto size = type.getSize(); - char* elementData = bufferData + index*size; - - *(void**)dest = elementData; - } - break; - - case kIROp_Call: { VMType type = decodeType(frame, &ip); |
