diff options
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/core.meta.slang | 41 | ||||
| -rw-r--r-- | source/slang/core.meta.slang.h | 41 | ||||
| -rw-r--r-- | source/slang/lower-to-ir.cpp | 52 | ||||
| -rw-r--r-- | source/slang/mangle.cpp | 6 |
4 files changed, 111 insertions, 29 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index bd163b165..836af1a87 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -704,18 +704,34 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) // subscript operator sb << "__subscript(" << uintN << " location) -> T {\n"; - sb << "__target_intrinsic(glsl, \"texelFetch($P, " << ivecN << "($1)"; - - if( !isMultisample ) - { - sb << ", 0"; - } - else + // GLSL/SPIR-V distinguished sampled vs. non-sampled images + switch( access ) { - // TODO: how to handle this... - sb << ", 0"; + case SLANG_RESOURCE_ACCESS_NONE: + case SLANG_RESOURCE_ACCESS_READ: + sb << "__target_intrinsic(glsl, \"texelFetch($P, " << ivecN << "($1)"; + if( !isMultisample ) + { + sb << ", 0"; + } + else + { + // TODO: how to handle passing through sample index? + sb << ", 0"; + } + break; + + default: + sb << "__target_intrinsic(glsl, \"imageLoad($0, " << ivecN << "($1)"; + if( isMultisample ) + { + // TODO: how to handle passing through sample index? + sb << ", 0"; + } + break; } + sb << ")$z\") get;\n"; // Depending on the access level of the texture type, @@ -730,10 +746,11 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) default: sb << "__target_intrinsic(glsl, \"imageStore($0, " << ivecN << "($1), $2)\") set;\n"; - // TODO: really need a way to map access through `ref` accessor (e.g., when - // used with an atomic operation) over to GLSL equivalent. + // Note: HLSL doesn't support component-granularity access into typed UAVs, + // and also doesn't support atomic operations on them. As such, there should + // be no reason why a `ref` accessor is required here. // - sb << "ref;\n"; + // sb << "ref;\n"; break; } diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h index d3edba93d..d6c742321 100644 --- a/source/slang/core.meta.slang.h +++ b/source/slang/core.meta.slang.h @@ -719,18 +719,34 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) // subscript operator sb << "__subscript(" << uintN << " location) -> T {\n"; - sb << "__target_intrinsic(glsl, \"texelFetch($P, " << ivecN << "($1)"; - - if( !isMultisample ) - { - sb << ", 0"; - } - else + // GLSL/SPIR-V distinguished sampled vs. non-sampled images + switch( access ) { - // TODO: how to handle this... - sb << ", 0"; + case SLANG_RESOURCE_ACCESS_NONE: + case SLANG_RESOURCE_ACCESS_READ: + sb << "__target_intrinsic(glsl, \"texelFetch($P, " << ivecN << "($1)"; + if( !isMultisample ) + { + sb << ", 0"; + } + else + { + // TODO: how to handle passing through sample index? + sb << ", 0"; + } + break; + + default: + sb << "__target_intrinsic(glsl, \"imageLoad($0, " << ivecN << "($1)"; + if( isMultisample ) + { + // TODO: how to handle passing through sample index? + sb << ", 0"; + } + break; } + sb << ")$z\") get;\n"; // Depending on the access level of the texture type, @@ -745,10 +761,11 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) default: sb << "__target_intrinsic(glsl, \"imageStore($0, " << ivecN << "($1), $2)\") set;\n"; - // TODO: really need a way to map access through `ref` accessor (e.g., when - // used with an atomic operation) over to GLSL equivalent. + // Note: HLSL doesn't support component-granularity access into typed UAVs, + // and also doesn't support atomic operations on them. As such, there should + // be no reason why a `ref` accessor is required here. // - sb << "ref;\n"; + // sb << "ref;\n"; break; } diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 07cb508b8..280b89fb8 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -2990,10 +2990,39 @@ static LoweredValInfo moveIntoMutableTemp( return var; } +// When we try to turn a `LoweredValInfo` into an address of some temporary storage, +// we can either do it "aggressively" or not (what we'll call the "default" behavior, +// although it isn't strictly more common). +// +// The case that this is mostly there to address is when somebody writes an operation +// like: +// +// foo[a] = b; +// +// In that case, we might as well just use the `set` accessor if there is one, rather +// than complicate things. However, in more complex cases like: +// +// foo[a].x = b; +// +// there is no way to satisfy the semantics of the code the user wrote (in terms of +// only writing one vector component, and not a full vector) by using the `set` +// accessor, and we need to be "aggressive" in turning the lvalue `foo[a]` into +// an address. +// +// TODO: realistically IR lowering is too early to be binding to this choice, +// because different accessors might be supported on different targets. +// +enum class TryGetAddressMode +{ + Default, + Aggressive, +}; + /// Try to coerce `inVal` into a `LoweredValInfo::ptr()` with a simple address. LoweredValInfo tryGetAddress( IRGenContext* context, - LoweredValInfo const& inVal) + LoweredValInfo const& inVal, + TryGetAddressMode mode) { LoweredValInfo val = inVal; @@ -3011,6 +3040,19 @@ LoweredValInfo tryGetAddress( // as part of the subscript operation being referenced. // auto subscriptInfo = val.getBoundSubscriptInfo(); + + // We don't want to immediately bind to a `ref` accessor if there is + // a `set` accessor available, unless we are in an "aggressive" mode + // where we really want/need a pointer to be able to make progress. + // + if(mode != TryGetAddressMode::Aggressive + && getMembersOfType<SetterDecl>(subscriptInfo->declRef).Count()) + { + // There is a setter that we should consider using, + // so don't go and aggressively collapse things just yet. + return val; + } + auto refAccessors = getMembersOfType<RefAccessorDecl>(subscriptInfo->declRef); if(refAccessors.Count()) { @@ -3053,7 +3095,7 @@ LoweredValInfo tryGetAddress( if( auto fieldDeclRef = declRef.As<StructField>() ) { auto baseVal = boundMemberInfo->base; - auto basePtr = tryGetAddress(context, baseVal); + auto basePtr = tryGetAddress(context, baseVal, TryGetAddressMode::Aggressive); return extractField(context, boundMemberInfo->type, basePtr, fieldDeclRef); } @@ -3068,7 +3110,7 @@ LoweredValInfo tryGetAddress( UInt elementCount = originalSwizzleInfo->elementCount; - auto newBase = tryGetAddress(context, originalBase); + auto newBase = tryGetAddress(context, originalBase, TryGetAddressMode::Aggressive); RefPtr<SwizzledLValueInfo> newSwizzleInfo = new SwizzledLValueInfo(); context->shared->extValues.Add(newSwizzleInfo); @@ -3098,7 +3140,7 @@ IRInst* getAddress( LoweredValInfo const& inVal, SourceLoc diagnosticLocation) { - LoweredValInfo val = tryGetAddress(context, inVal); + LoweredValInfo val = tryGetAddress(context, inVal, TryGetAddressMode::Aggressive); if( val.flavor == LoweredValInfo::Flavor::Ptr ) { @@ -3122,7 +3164,7 @@ void assign( // a simple pointer, since that would make our life a lot easier // when handling complex cases. // - left = tryGetAddress(context, left); + left = tryGetAddress(context, left, TryGetAddressMode::Default); auto builder = context->irBuilder; diff --git a/source/slang/mangle.cpp b/source/slang/mangle.cpp index d3e2f833f..dc2738d8f 100644 --- a/source/slang/mangle.cpp +++ b/source/slang/mangle.cpp @@ -325,6 +325,12 @@ namespace Slang emitName(context, declRef.GetName()); + // Special case: accessors need some way to distinguish themselves + // so that a getter/setter/ref-er don't all compile to the same name. + if(declRef.As<GetterDecl>()) emitRaw(context, "Ag"); + if(declRef.As<SetterDecl>()) emitRaw(context, "As"); + if(declRef.As<RefAccessorDecl>()) emitRaw(context, "Ar"); + // Are we the "inner" declaration beneath a generic decl? if(parentGenericDeclRef && (parentGenericDeclRef.getDecl()->inner.Ptr() == declRef.getDecl())) { |
