diff options
48 files changed, 3730 insertions, 192 deletions
diff --git a/slang-gfx.h b/slang-gfx.h index 0585de772..d705c8554 100644 --- a/slang-gfx.h +++ b/slang-gfx.h @@ -296,8 +296,12 @@ public: x(BC6H_UF16, 16, 16) \ x(BC6H_SF16, 16, 16) \ x(BC7_UNORM, 16, 16) \ - x(BC7_UNORM_SRGB, 16, 16) - + x(BC7_UNORM_SRGB, 16, 16) \ + \ + x(R64_UINT, 8, 1) \ + \ + x(R64_SINT, 8, 1) \ + \ // TODO: This should be generated from above // TODO: enum class should be explicitly uint32_t or whatever's appropriate /// Different formats of things like pixels or elements of vertices @@ -409,6 +413,10 @@ enum class Format BC7_UNORM, BC7_UNORM_SRGB, + R64_UINT, + + R64_SINT, + _Count, }; diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 1f4a2908d..583dd5923 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -2363,6 +2363,10 @@ int __naturalStrideOf() __intrinsic_op($(kIROp_TreatAsDynamicUniform)) T asDynamicUniform<T>(T v); +__generic<T> +__intrinsic_op($(kIROp_GetLegalizedSPIRVGlobalParamAddr)) +Ptr<T> __getLegalizedSPIRVGlobalParamAddr(T val); + // Binding Attributes __attributeTarget(DeclBase) diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang index 4101cc626..d7b646810 100644 --- a/source/slang/glsl.meta.slang +++ b/source/slang/glsl.meta.slang @@ -2821,6 +2821,466 @@ public vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod) return textureProjLod(sampler, coord, lod); } +//// gimageDim Implementation + +public static const int GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0; +public static const int GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 1; +public static const int GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 2; +public static const int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 3; +public static const int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 4; +public static const int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 5; + +__generic<T : __BuiltinType> +[ForceInline] void typeRequireChecks_image_atomic_tier1() +{ + __target_switch + { + case glsl: + { + if (__type_equals<T, float>()) + __requireGLSLExtension("GL_EXT_shader_atomic_float"); + } + case spirv: + if (__type_equals<T, float>()) + { + spirv_asm + { + OpExtension "SPV_EXT_shader_atomic_float_add"; + OpCapability AtomicFloat32AddEXT + }; + } + } +} + +__generic<T : __BuiltinType> +[ForceInline] void typeRequireChecks_image_atomic_tier2() +{ + __target_switch + { + case glsl: + { + if (__type_equals<T, float>()) + __requireGLSLExtension("GL_EXT_shader_atomic_float2"); + } + case spirv: + if (__type_equals<T, float>()) + { + spirv_asm + { + OpExtension "SPV_EXT_shader_atomic_float_min_max"; + OpCapability AtomicFloat32MinMaxEXT + }; + } + } +} + +__generic<T : __BuiltinType> +[ForceInline] void typeRequireChecks_image_atomic_int64() +{ + __target_switch + { + case spirv: + if (__type_equals<T, uint64_t>() + || __type_equals<T, int64_t>()) + { + spirv_asm + { + OpCapability Int64Atomics + }; + } + return; + } +} + +${{{{ +{ + struct ImageTypeInfo + { + const char *prefix; + const char *type; + bool isInt; + const char *SPVTypePrefix; + const char *SPVSubTypePrefix; + const char *SPVAtomicSuffix; + }; + static const ImageTypeInfo kTypeWithPrefix[] = + { + { "", "float", false, "F", "F", "EXT"}, + { "u", "uint", true, "I", "U", ""}, + { "i", "int", true, "I", "S", ""}, + { "u64", "uint64_t", true, "I", "U", ""}, + { "i64", "int64_t", true, "I", "S", ""}, + }; + struct ShapeTypeInfo + { + const char *suffix; + int imageSizeIVecDim; + int imageCoordIVecIndexerDim; + const char *shape; + int isArray; + int isMS; + bool isRect; + } + static const kShapeType[] = + { + { "1D", 1, 1,"__Shape1D", 0, 0, 0}, + + { "2D", 2, 2, "__Shape2D", 0, 0, 0}, + { "3D", 3, 3, "__Shape3D", 0, 0, 0}, + { "Cube", 2, 3, "__ShapeCube", 0, 0, 0}, + { "2DRect", 2, 2, "__Shape2D", 0, 0, 1}, + { "1DArray", 2, 2, "__Shape1D", 1, 0, 0}, + + { "2DArray", 3, 3, "__Shape2D", 1, 0, 0}, + { "CubeArray", 3, 3, "__ShapeCube", 1, 0, 0}, + { "Buffer", 1, 1, "__ShapeBuffer", 0, 0, 0}, + { "2DMS", 2, 2, "__Shape2D", 0, 1, 0}, + { "2DMSArray", 3, 3, "__Shape2D", 1, 1, 0}, + }; + for (const auto& targetType : kTypeWithPrefix) + for (const auto& targetShape : kShapeType) + { + // gimageDim is the format of image buffers, we + // need to resolve a type name from the format: + // targetType.prefix is the 'g' + // targetShape.suffix is the 'Dim' + StringBuilder fullTypeNameBuilder; + fullTypeNameBuilder << targetType.prefix << "image" << targetShape.suffix; + auto fullTypeName = fullTypeNameBuilder.toString(); + + // We need a string to resolve for the imageSize return type + // since each shape has a different return which may not be + // a vec + StringBuilder imageSizeIntOrIVecBuilder; + if (targetShape.imageSizeIVecDim == 1) + imageSizeIntOrIVecBuilder << "int"; + else + imageSizeIntOrIVecBuilder << "ivec" << targetShape.imageSizeIVecDim; + auto imageSizeIntOrIVec = imageSizeIntOrIVecBuilder.toString(); + + // Following OpenGL/Vulkan semantics, IMAGE_PARAMS string represents + // the changing list of parameters per gimageDim type + // https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf + StringBuilder IMAGE_PARAMSBuilder; + IMAGE_PARAMSBuilder << fullTypeName << " image,"; + int paramC = targetShape.imageCoordIVecIndexerDim; + if (paramC == 1) + IMAGE_PARAMSBuilder << "int"; + else + IMAGE_PARAMSBuilder << "ivec" << paramC; + IMAGE_PARAMSBuilder << " P"; + if (targetShape.isMS) + { + IMAGE_PARAMSBuilder << ", int sample"; + } + auto IMAGE_PARAMS = IMAGE_PARAMSBuilder.toString(); + + // SPIR-V requires a 'sample' parameter for all texture + // functions. We need to handle a dynamic creation of + // 'sample' if 'sample' parameter is not in IMAGE_PARAMS + StringBuilder SPV_PREFIX_IMAGE_PARAMSBuilder; + StringBuilder SPV_SUFFIX_IMAGE_PARAMSBuilder; + StringBuilder SPV_DEFAULT_SAMPLE_VAR_IF_MISSINGBuilder; + + SPV_PREFIX_IMAGE_PARAMSBuilder << "$image $P"; + SPV_SUFFIX_IMAGE_PARAMSBuilder; + if (targetShape.isMS) + { + SPV_SUFFIX_IMAGE_PARAMSBuilder << " Sample $sample"; + } + else + { + SPV_DEFAULT_SAMPLE_VAR_IF_MISSINGBuilder << "let sample = 0;"; + } + + auto SPV_PREFIX_IMAGE_PARAMS = SPV_PREFIX_IMAGE_PARAMSBuilder.toString(); + auto SPV_SUFFIX_IMAGE_PARAMS = SPV_SUFFIX_IMAGE_PARAMSBuilder.toString(); + auto SPV_DEFAULT_SAMPLE_VAR_IF_MISSING = SPV_DEFAULT_SAMPLE_VAR_IF_MISSINGBuilder.toString(); + }}}} + + __generic<let format:int=0> + public typealias $(fullTypeName) = __TextureImpl< + $(targetType.type), + $(targetShape.shape), + $(targetShape.isArray), // isArray + $(targetShape.isMS), // isMS + 0, // sampleCount + 1, // access + 0, // isShadow + 0, // isCombined + format + >; + +${{{{ + if(targetShape.isRect) + continue; +}}}} + + // readonly writeonly in GLSL means an object only allows information queries. + [require(spirv)] + [require(glsl)] + [__readNone] + [ForceInline] public $(imageSizeIntOrIVec) imageSize(readonly writeonly $(fullTypeName) image) + { + __target_switch + { + case glsl: __intrinsic_asm "imageSize($*0)"; + case spirv: + return spirv_asm + { + OpCapability ImageQuery; + result:$$$(imageSizeIntOrIVec) = OpImageQuerySize $image; + }; + } + } + [require(spirv)] + [require(glsl)] + [__NoSideEffect] + [ForceInline] public $(targetType.prefix)vec4 imageLoad(readonly $(IMAGE_PARAMS)) + { + __target_switch + { + case glsl: __intrinsic_asm "imageLoad($*0)"; + case spirv: + { + $(SPV_DEFAULT_SAMPLE_VAR_IF_MISSING) + return spirv_asm + { + result:$$$(targetType.prefix)vec4 = OpImageRead $(SPV_PREFIX_IMAGE_PARAMS) $(SPV_SUFFIX_IMAGE_PARAMS); + }; + } + } + } + [require(spirv)] + [require(glsl)] + [ForceInline] public void imageStore(writeonly $(IMAGE_PARAMS), $(targetType.prefix)vec4 data) + { + __target_switch + { + case glsl: __intrinsic_asm "imageStore($*0)"; + case spirv: + { + $(SPV_DEFAULT_SAMPLE_VAR_IF_MISSING) + return spirv_asm + { + OpImageWrite $(SPV_PREFIX_IMAGE_PARAMS) $data $(SPV_SUFFIX_IMAGE_PARAMS); + }; + } + } + } + +${{{{ + if (targetShape.isMS) + { +}}}} + // readonly writeonly in GLSL means an object only allows information queries. + [require(spirv)] + [require(glsl)] + [__readNone] + [ForceInline] public int imageSamples(readonly writeonly $(fullTypeName) image) + { + __target_switch + { + case glsl: __intrinsic_asm "imageSamples($*0)"; + case spirv: + return spirv_asm + { + OpCapability ImageQuery; + result:$$int = OpImageQuerySamples $image; + }; + } + } +${{{{ + } +}}}} + [require(spirv)] + [require(glsl)] + [ForceInline] public $(targetType.type) imageAtomicAdd($(IMAGE_PARAMS), $(targetType.type) data) + { + typeRequireChecks_image_atomic_tier1<$(targetType.type)>(); + __target_switch + { + case glsl: __intrinsic_asm "imageAtomicAdd($*0)"; + case spirv: + { + let imageP = __getLegalizedSPIRVGlobalParamAddr(image); + typeRequireChecks_image_atomic_int64<$(targetType.type)>(); + $(SPV_DEFAULT_SAMPLE_VAR_IF_MISSING) + return spirv_asm + { + OpCapability ImageQuery; + %ptrType = OpTypePointer Image $$$(targetType.type); + %ptr:%ptrType = OpImageTexelPointer $imageP $P $sample; + result:$$$(targetType.type) = OpAtomic$(targetType.SPVTypePrefix)Add$(targetType.SPVAtomicSuffix) %ptr Device None $data + }; + } + } + } + [require(spirv)] + [require(glsl)] + [ForceInline] public $(targetType.type) imageAtomicExchange($(IMAGE_PARAMS), $(targetType.type) data) + { + typeRequireChecks_image_atomic_tier1<$(targetType.type)>(); + __target_switch + { + case glsl: __intrinsic_asm "imageAtomicExchange($*0)"; + case spirv: + { + let imageP = __getLegalizedSPIRVGlobalParamAddr(image); + typeRequireChecks_image_atomic_int64<$(targetType.type)>(); + $(SPV_DEFAULT_SAMPLE_VAR_IF_MISSING) + return spirv_asm + { + OpCapability ImageQuery; + %ptrType = OpTypePointer Image $$$(targetType.type); + %ptr:%ptrType = OpImageTexelPointer $imageP $P $sample; + result:$$$(targetType.type) = OpAtomicExchange %ptr Device ImageMemory $data + }; + } + } + } + [require(spirv)] + [require(glsl)] + [ForceInline] public $(targetType.type) imageAtomicMin($(IMAGE_PARAMS), $(targetType.type) data) + { + typeRequireChecks_image_atomic_tier2<$(targetType.type)>(); + __target_switch + { + case glsl: __intrinsic_asm "imageAtomicMin($*0)"; + case spirv: + { + let imageP = __getLegalizedSPIRVGlobalParamAddr(image); + typeRequireChecks_image_atomic_int64<$(targetType.type)>(); + $(SPV_DEFAULT_SAMPLE_VAR_IF_MISSING) + return spirv_asm + { + OpCapability ImageQuery; + %ptrType = OpTypePointer Image $$$(targetType.type); + %ptr:%ptrType = OpImageTexelPointer $imageP $P $sample; + result:$$$(targetType.type) = OpAtomic$(targetType.SPVSubTypePrefix)Min$(targetType.SPVAtomicSuffix) %ptr Device ImageMemory $data + }; + } + } + } + [require(spirv)] + [require(glsl)] + [ForceInline] public $(targetType.type) imageAtomicMax($(IMAGE_PARAMS), $(targetType.type) data) + { + typeRequireChecks_image_atomic_tier2<$(targetType.type)>(); + __target_switch + { + case glsl: __intrinsic_asm "imageAtomicMax($*0)"; + case spirv: + { + let imageP = __getLegalizedSPIRVGlobalParamAddr(image); + typeRequireChecks_image_atomic_int64<$(targetType.type)>(); + $(SPV_DEFAULT_SAMPLE_VAR_IF_MISSING) + return spirv_asm + { + OpCapability ImageQuery; + %ptrType = OpTypePointer Image $$$(targetType.type); + %ptr:%ptrType = OpImageTexelPointer $imageP $P $sample; + result:$$$(targetType.type) = OpAtomic$(targetType.SPVSubTypePrefix)Max$(targetType.SPVAtomicSuffix) %ptr Device ImageMemory $data + }; + } + } + } +${{{{ + if (!targetType.isInt) + continue; +}}}} + [require(spirv)] + [require(glsl)] + [ForceInline] public $(targetType.type) imageAtomicAnd($(IMAGE_PARAMS), $(targetType.type) data) + { + __target_switch + { + case glsl: __intrinsic_asm "imageAtomicAnd($*0)"; + case spirv: + { + let imageP = __getLegalizedSPIRVGlobalParamAddr(image); + typeRequireChecks_image_atomic_int64<$(targetType.type)>(); + $(SPV_DEFAULT_SAMPLE_VAR_IF_MISSING) + return spirv_asm + { + OpCapability ImageQuery; + %ptrType = OpTypePointer Image $$$(targetType.type); + %ptr:%ptrType = OpImageTexelPointer $imageP $P $sample; + result:$$$(targetType.type) = OpAtomicAnd %ptr Device ImageMemory $data + }; + } + } + } + [require(spirv)] + [require(glsl)] + [ForceInline] public $(targetType.type) imageAtomicOr($(IMAGE_PARAMS), $(targetType.type) data) + { + __target_switch + { + case glsl: __intrinsic_asm "imageAtomicOr($*0)"; + case spirv: + { + let imageP = __getLegalizedSPIRVGlobalParamAddr(image); + typeRequireChecks_image_atomic_int64<$(targetType.type)>(); + $(SPV_DEFAULT_SAMPLE_VAR_IF_MISSING) + return spirv_asm + { + OpCapability ImageQuery; + %ptrType = OpTypePointer Image $$$(targetType.type); + %ptr:%ptrType = OpImageTexelPointer $imageP $P $sample; + result:$$$(targetType.type) = OpAtomicOr %ptr Device ImageMemory $data + }; + } + } + } + [require(spirv)] + [require(glsl)] + [ForceInline] public $(targetType.type) imageAtomicXor($(IMAGE_PARAMS), $(targetType.type) data) + { + __target_switch + { + case glsl: __intrinsic_asm "imageAtomicXor($*0)"; + case spirv: + { + let imageP = __getLegalizedSPIRVGlobalParamAddr(image); + typeRequireChecks_image_atomic_int64<$(targetType.type)>(); + $(SPV_DEFAULT_SAMPLE_VAR_IF_MISSING) + return spirv_asm + { + OpCapability ImageQuery; + %ptrType = OpTypePointer Image $$$(targetType.type); + %ptr:%ptrType = OpImageTexelPointer $imageP $P $sample; + result:$$$(targetType.type) = OpAtomicXor %ptr Device ImageMemory $data + }; + } + } + } + [require(spirv)] + [require(glsl)] + [ForceInline] public $(targetType.type) imageAtomicCompSwap($(IMAGE_PARAMS), $(targetType.type) compare, $(targetType.type) data) + { + __target_switch + { + case glsl: __intrinsic_asm "imageAtomicCompSwap($*0)"; + case spirv: + { + let imageP = __getLegalizedSPIRVGlobalParamAddr(image); + typeRequireChecks_image_atomic_int64<$(targetType.type)>(); + $(SPV_DEFAULT_SAMPLE_VAR_IF_MISSING) + return spirv_asm + { + OpCapability ImageQuery; + %ptrType = OpTypePointer Image $$$(targetType.type); + %ptr:%ptrType = OpImageTexelPointer $imageP $P $sample; + result:$$$(targetType.type) = OpAtomicCompareExchange %ptr Device ImageMemory ImageMemory $data $compare + }; + } + } + } +${{{{ + } +} +}}}} //// RayTracing diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index 87057b694..4ccca36ea 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -29,7 +29,6 @@ class PrefixModifier : public Modifier { SLANG_AST_CLASS(PrefixModifier)}; class PostfixModifier : public Modifier { SLANG_AST_CLASS(PostfixModifier)}; class ExportedModifier : public Modifier { SLANG_AST_CLASS(ExportedModifier)}; class ConstExprModifier : public Modifier { SLANG_AST_CLASS(ConstExprModifier)}; -class GloballyCoherentModifier : public Modifier { SLANG_AST_CLASS(GloballyCoherentModifier)}; class ExternCppModifier : public Modifier { SLANG_AST_CLASS(ExternCppModifier)}; class GLSLPrecisionModifier : public Modifier { SLANG_AST_CLASS(GLSLPrecisionModifier)}; class GLSLModuleModifier : public Modifier {SLANG_AST_CLASS(GLSLModuleModifier)}; @@ -1493,6 +1492,11 @@ class NoDiffModifier : public TypeModifier SLANG_AST_CLASS(NoDiffModifier) }; +class GloballyCoherentModifier : public SimpleModifier +{ + SLANG_AST_CLASS(GloballyCoherentModifier) +}; + // Some GLSL-specific modifiers class GLSLBufferModifier : public WrappingTypeModifier { @@ -1509,6 +1513,16 @@ class GLSLReadOnlyModifier : public SimpleModifier SLANG_AST_CLASS(GLSLReadOnlyModifier) }; +class GLSLVolatileModifier : public SimpleModifier +{ + SLANG_AST_CLASS(GLSLVolatileModifier) +}; + +class GLSLRestrictModifier : public SimpleModifier +{ + SLANG_AST_CLASS(GLSLRestrictModifier) +}; + class GLSLPatchModifier : public SimpleModifier { SLANG_AST_CLASS(GLSLPatchModifier) @@ -1531,4 +1545,35 @@ class DynamicUniformModifier : public Modifier SLANG_AST_CLASS(DynamicUniformModifier) }; +class MemoryQualifierCollectionModifier : public Modifier +{ + SLANG_AST_CLASS(MemoryQualifierCollectionModifier); + + List<Modifier*> memoryModifiers; + + uint32_t memoryQualifiers = 0; + +public: + struct Flags + { + enum MemoryQualifiersBit + { + kNone = 0b0, + kCoherent = 0b1, + kReadOnly = 0b10, + kWriteOnly = 0b100, + kVolatile = 0b1000, + kRestrict = 0b10000, + }; + }; + + void addQualifier(Modifier* mod, Flags::MemoryQualifiersBit type) + { + memoryModifiers.add(mod); + memoryQualifiers |= type; + } + uint32_t getMemoryQualifierBit() { return memoryQualifiers; } + List<Modifier*> getModifiers() { return memoryModifiers; } +}; + } // namespace Slang diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h index 4ad5fc432..e4e3be384 100644 --- a/source/slang/slang-ast-support-types.h +++ b/source/slang/slang-ast-support-types.h @@ -549,6 +549,8 @@ namespace Slang Type* type = nullptr; bool isLeftValue; + bool hasReadOnlyOnTarget = false; + bool isWriteOnly = false; QualType() : isLeftValue(false) diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 386a0bba1..c844fb82a 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -944,7 +944,27 @@ namespace Slang } } + // Ensures child of struct is set read-only or not + bool isWriteOnly = false; + { + for (auto mod : varDeclRef.getDecl()->modifiers) + { + if (as<GLSLReadOnlyModifier>(mod)) + { + isLValue = false; + qualType.hasReadOnlyOnTarget = true; + if (isLValue == false && isWriteOnly) break; + } + if (as<GLSLWriteOnlyModifier>(mod)) + { + isWriteOnly = true; + if (isLValue == false && isWriteOnly) break; + } + } + } + qualType.isLeftValue = isLValue; + qualType.isWriteOnly = isWriteOnly; return qualType; } else if( auto propertyDeclRef = declRef.as<PropertyDecl>() ) @@ -1846,6 +1866,8 @@ namespace Slang // initExpr = subVisitor.CheckTerm(initExpr); + if (initExpr->type.isWriteOnly) + getSink()->diagnose(initExpr, Diagnostics::readingFromWriteOnly); initExpr = coerce(CoercionSite::Initializer, varDecl->type.Ptr(), initExpr); varDecl->initExpr = initExpr; @@ -7023,6 +7045,16 @@ namespace Slang } } } + + // Only texture types are allowed to have memory qualifiers on parameters + if(!paramDecl->type || paramDecl->type->astNodeType != ASTNodeType::TextureType) + { + auto memoryQualifierCollection = paramDecl->findModifier<MemoryQualifierCollectionModifier>(); + if(!memoryQualifierCollection) + return; + for(auto mod : memoryQualifierCollection->getModifiers()) + getSink()->diagnose(paramDecl, Diagnostics::memoryQualifierNotAllowedOnANonImageTypeParameter, mod); + } } // This checks that the declaration is marked as "out" and changes the hlsl diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index dc7a2d35b..a31e17123 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -412,6 +412,11 @@ namespace Slang expr->declRef = declRef; expr->memberOperatorLoc = _getMemberOpLoc(originalExpr); + // If any member declares the following value is a + // write only, we must declare the parent as a write + // only to avoid modifying the child + expr->type.isWriteOnly = baseExpr->type.isWriteOnly || expr->type.isWriteOnly; + // When referring to a member through an expression, // the result is only an l-value if both the base // expression and the member agree that it should be. @@ -424,7 +429,7 @@ namespace Slang // One exception to this is if we're reading the contents // of a GLSL buffer interface block which isn't marked as // read_only - expr->type.isLeftValue = isMutableGLSLBufferBlockVarExpr(baseExpr); + expr->type.isLeftValue = isMutableGLSLBufferBlockVarExpr(baseExpr) && (expr->type.hasReadOnlyOnTarget == false); } else { @@ -2078,6 +2083,9 @@ namespace Slang Expr* SemanticsVisitor::checkAssignWithCheckedOperands(AssignExpr* expr) { + if (expr->right->type.isWriteOnly) + getSink()->diagnose(expr, Diagnostics::readingFromWriteOnly); + expr->left = maybeOpenRef(expr->left); auto type = expr->left->type; auto right = maybeOpenRef(expr->right); @@ -2177,6 +2185,44 @@ namespace Slang return _canLValueCoerceScalarType(a, b); } + + void SemanticsVisitor::compareMemoryQualifierOfParamToArgument( + ParamDecl* paramIn, + Expr* argIn) + { + auto arg = as<VarExpr>(argIn); + if (!paramIn || !arg) + return; + + auto argDeclRef = arg->declRef; + if (!argDeclRef) + return; + auto argDecl = argDeclRef.getDecl(); + auto argMemMods = argDecl->findModifier<MemoryQualifierCollectionModifier>(); + if(!argMemMods) + return; + uint32_t argQualifiers = argMemMods->getMemoryQualifierBit(); + + uint32_t paramQualifiers = 0; + auto paramMemMods = paramIn->findModifier<MemoryQualifierCollectionModifier>(); + if(paramMemMods) + paramQualifiers = paramMemMods->getMemoryQualifierBit(); + + if(argQualifiers & MemoryQualifierCollectionModifier::Flags::kCoherent + && !(paramQualifiers & MemoryQualifierCollectionModifier::Flags::kCoherent)) + getSink()->diagnose(arg, Diagnostics::argumentHasMoreMemoryQualifiersThanParam, "coherent"); + if(argQualifiers & MemoryQualifierCollectionModifier::Flags::kReadOnly + && !(paramQualifiers & MemoryQualifierCollectionModifier::Flags::kReadOnly)) + getSink()->diagnose(arg, Diagnostics::argumentHasMoreMemoryQualifiersThanParam, "readonly"); + if(argQualifiers & MemoryQualifierCollectionModifier::Flags::kWriteOnly + && !(paramQualifiers & MemoryQualifierCollectionModifier::Flags::kWriteOnly)) + getSink()->diagnose(arg, Diagnostics::argumentHasMoreMemoryQualifiersThanParam, "writeonly"); + if(argQualifiers & MemoryQualifierCollectionModifier::Flags::kVolatile + && !(paramQualifiers & MemoryQualifierCollectionModifier::Flags::kVolatile)) + getSink()->diagnose(arg, Diagnostics::argumentHasMoreMemoryQualifiersThanParam, "volatile"); + // dropping a `restrict` qualifier from arguments is allowed in GLSL with memory qualifiers + } + Expr* SemanticsVisitor::CheckInvokeExprWithCheckedOperands(InvokeExpr *expr) { auto rs = ResolveInvoke(expr); @@ -2194,10 +2240,25 @@ namespace Slang } } + auto funcDeclRefExpr = as<DeclRefExpr>(invoke->functionExpr); + FunctionDeclBase* funcDeclBase = nullptr; + if (funcDeclRefExpr) + funcDeclBase = as<FunctionDeclBase>(funcDeclRefExpr->declRef.getDecl()); + Index paramCount = funcType->getParamCount(); for (Index pp = 0; pp < paramCount; ++pp) { auto paramType = funcType->getParamType(pp); + Expr* argExpr = nullptr; + ParamDecl* paramDecl = nullptr; + if (pp < expr->arguments.getCount()) + { + argExpr = expr->arguments[pp]; + if(funcDeclBase) + paramDecl = funcDeclBase->getParameters()[pp]; + } + compareMemoryQualifierOfParamToArgument(paramDecl, argExpr); + if (as<OutTypeBase>(paramType) || as<RefType>(paramType)) { // `out`, `inout`, and `ref` parameters currently require @@ -2207,9 +2268,8 @@ namespace Slang // for an `inout` parameter to be converted in both // directions. // - if( pp < expr->arguments.getCount() ) + if( argExpr ) { - auto argExpr = expr->arguments[pp]; if( !argExpr->type.isLeftValue) { auto implicitCastExpr = as<ImplicitCastExpr>(argExpr); @@ -3280,6 +3340,8 @@ namespace Slang { auto elementType = QualType(pointerLikeType->getElementType()); elementType.isLeftValue = baseType.isLeftValue; + elementType.hasReadOnlyOnTarget = baseType.hasReadOnlyOnTarget; + elementType.isWriteOnly = baseType.isWriteOnly; auto derefExpr = m_astBuilder->create<DerefExpr>(); derefExpr->base = expr; diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h index 392d78c5a..278fc3265 100644 --- a/source/slang/slang-check-impl.h +++ b/source/slang/slang-check-impl.h @@ -2467,6 +2467,7 @@ namespace Slang Expr* CheckExpr(Expr* expr); + void compareMemoryQualifierOfParamToArgument(ParamDecl* paramIn, Expr* argIn); Expr* CheckInvokeExprWithCheckedOperands(InvokeExpr *expr); // Get the type to use when referencing a declaration QualType GetTypeForDeclRef(DeclRef<Decl> declRef, SourceLoc loc); diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp index 0b9688cb0..942afd559 100644 --- a/source/slang/slang-check-modifier.cpp +++ b/source/slang/slang-check-modifier.cpp @@ -1010,6 +1010,8 @@ namespace Slang case ASTNodeType::GLSLBufferModifier: case ASTNodeType::GLSLWriteOnlyModifier: case ASTNodeType::GLSLReadOnlyModifier: + case ASTNodeType::GLSLVolatileModifier: + case ASTNodeType::GLSLRestrictModifier: case ASTNodeType::GLSLPatchModifier: case ASTNodeType::RayPayloadAccessSemantic: case ASTNodeType::RayPayloadReadSemantic: @@ -1092,16 +1094,26 @@ namespace Slang case ASTNodeType::RefModifier: case ASTNodeType::ConstRefModifier: case ASTNodeType::GLSLBufferModifier: - case ASTNodeType::GLSLWriteOnlyModifier: - case ASTNodeType::GLSLReadOnlyModifier: case ASTNodeType::GLSLPatchModifier: case ASTNodeType::RayPayloadAccessSemantic: case ASTNodeType::RayPayloadReadSemantic: case ASTNodeType::RayPayloadWriteSemantic: return (as<VarDeclBase>(decl) && isGlobalDecl(decl)) || as<ParamDecl>(decl) || as<GLSLInterfaceBlockDecl>(decl); + case ASTNodeType::GLSLWriteOnlyModifier: + case ASTNodeType::GLSLReadOnlyModifier: + case ASTNodeType::GLSLVolatileModifier: + case ASTNodeType::GLSLRestrictModifier: + if(isGLSLInput) + return (as<VarDeclBase>(decl) && (isGlobalDecl(decl)) || as<ParamDecl>(decl) || as<GLSLInterfaceBlockDecl>(decl)) + || as<StructDecl>(getParentDecl(decl)) && isGlobalDecl(getParentDecl(decl)); + return (as<VarDeclBase>(decl) && (isGlobalDecl(decl)) || as<ParamDecl>(decl) || as<GLSLInterfaceBlockDecl>(decl)); + case ASTNodeType::GloballyCoherentModifier: case ASTNodeType::HLSLVolatileModifier: + if(isGLSLInput) + return as<VarDecl>(decl) && (isGlobalDecl(decl) || as<StructDecl>(getParentDecl(decl)) || as<GLSLInterfaceBlockDecl>(decl)) + || as<VarDeclBase>(decl) && isGlobalDecl(decl) || as<ParamDecl>(decl) || (as<StructDecl>(getParentDecl(decl)) && isGlobalDecl(getParentDecl(decl))); return as<VarDecl>(decl) && (isGlobalDecl(decl) || as<StructDecl>(getParentDecl(decl)) || as<GLSLInterfaceBlockDecl>(decl)); // Allowed only on parameters, struct fields and global variables. @@ -1216,6 +1228,40 @@ namespace Slang } } + MemoryQualifierCollectionModifier::Flags::MemoryQualifiersBit memoryQualifierBit = + MemoryQualifierCollectionModifier::Flags::kNone; + if(as<GloballyCoherentModifier>(m)) + memoryQualifierBit = MemoryQualifierCollectionModifier::Flags::kCoherent; + else if(as<GLSLReadOnlyModifier>(m)) + memoryQualifierBit = MemoryQualifierCollectionModifier::Flags::kReadOnly; + else if(as<GLSLWriteOnlyModifier>(m)) + memoryQualifierBit = MemoryQualifierCollectionModifier::Flags::kWriteOnly; + else if(as<GLSLVolatileModifier>(m)) + memoryQualifierBit = MemoryQualifierCollectionModifier::Flags::kVolatile; + else if(as<GLSLRestrictModifier>(m)) + memoryQualifierBit = MemoryQualifierCollectionModifier::Flags::kRestrict; + if(memoryQualifierBit != MemoryQualifierCollectionModifier::Flags::kNone) + { + bool newModifier = false; + MemoryQualifierCollectionModifier* memoryQualifiers = syntaxNode->findModifier<MemoryQualifierCollectionModifier>(); + if(!memoryQualifiers) + { + newModifier = true; + memoryQualifiers = getASTBuilder()->create<MemoryQualifierCollectionModifier>(); + } + memoryQualifiers->addQualifier(m, + memoryQualifierBit); + if (newModifier) + { + // insert in modifiers list the memoryQualifierCollection + Modifier* mod = m->next; + m->next = memoryQualifiers; + memoryQualifiers->next = mod; + return m; + } + return m; + } + if (auto hlslSemantic = as<HLSLSimpleSemantic>(m)) { if (hlslSemantic->name.getName() == getSession()->getCompletionRequestTokenName()) @@ -1519,6 +1565,7 @@ namespace Slang if (as<SharedModifiers>(modifier)) ignoreUnallowedModifier = true; + // may return a list of modifiers auto checkedModifier = checkModifier(modifier, syntaxNode, ignoreUnallowedModifier); if(checkedModifier) diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 757ce94ee..e1c929f7e 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -298,6 +298,7 @@ DIAGNOSTIC(30035, Error, componentOverloadTypeMismatch, "'$0': type of overloade DIAGNOSTIC(30041, Error, bitOperationNonIntegral, "bit operation: operand must be integral type.") DIAGNOSTIC(30043, Error, getStringHashRequiresStringLiteral, "getStringHash parameter can only accept a string literal") DIAGNOSTIC(30047, Error, argumentExpectedLValue, "argument passed to parameter '$0' must be l-value.") +DIAGNOSTIC(30048, Error, argumentHasMoreMemoryQualifiersThanParam, "argument passed in to parameter has a memory qualifier the parameter type is missing: '$0'") DIAGNOSTIC(30049, Note, thisIsImmutableByDefault, "a 'this' parameter is an immutable parameter by default in Slang; apply the `[mutating]` attribute to the function declaration to opt in to a mutable `this`") DIAGNOSTIC(30050, Error, mutatingMethodOnImmutableValue, "mutating method '$0' cannot be called on an immutable value") @@ -355,6 +356,8 @@ DIAGNOSTIC(30098, Error, nonStaticMemberFunctionNotAllowedAsDiffOperand, "non-st DIAGNOSTIC(30099, Error, sizeOfArgumentIsInvalid, "argument to sizeof is invalid") +DIAGNOSTIC(30101, Error, readingFromWriteOnly, "cannot read from writeonly, check modifiers.") + // Include DIAGNOSTIC(30500, Error, includedFileMissingImplementing, "missing 'implementing' declaration in the included source file '$0'.") DIAGNOSTIC(30501, Error, includedFileMissingImplementingDoYouMeanImport, "missing 'implementing' declaration in the included source file '$0'. The file declares that it defines module '$1', do you mean 'import' instead?") @@ -444,6 +447,7 @@ DIAGNOSTIC(31202, Error, duplicateModifier, "modifier '$0' is redundant or confl DIAGNOSTIC(31203, Error, cannotExportIncompleteType, "cannot export incomplete type '$0'") DIAGNOSTIC(31204, Error, incompleteTypeCannotBeUsedInBuffer, "incomplete type '$0' cannot be used in a buffer") DIAGNOSTIC(31205, Error, incompleteTypeCannotBeUsedInUniformParameter, "incomplete type '$0' cannot be used in a uniform parameter") +DIAGNOSTIC(31206, Error, memoryQualifierNotAllowedOnANonImageTypeParameter, "modifier $0 is not allowed on a non image type parameter.") // Enums diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index af53b545f..b60e0a4ac 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -3537,6 +3537,7 @@ void CLikeSourceEmitter::emitStructDeclarationsBlock(IRStructType* structType, b emitPackOffsetModifier(fieldKey, fieldType, packOffsetDecoration); } } + emitMemoryQualifiers(fieldKey); emitType(fieldType, getName(fieldKey)); emitSemantics(fieldKey, allowOffsetLayout); m_writer->emit(";\n"); diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h index 46cdf2145..fa99ae061 100644 --- a/source/slang/slang-emit-c-like.h +++ b/source/slang/slang-emit-c-like.h @@ -385,6 +385,7 @@ public: /// Emit type attributes that should appear after, e.g., a `struct` keyword void emitPostKeywordTypeAttributes(IRInst* inst) { emitPostKeywordTypeAttributesImpl(inst); } + virtual void emitMemoryQualifiers(IRInst* /*varInst*/) {}; void emitInterpolationModifiers(IRInst* varInst, IRType* valueType, IRVarLayout* layout); void emitMeshShaderModifiers(IRInst* varInst); virtual void emitPackOffsetModifier(IRInst* /*varInst*/, IRType* /*valueType*/, IRPackOffsetDecoration* /*decoration*/) {}; diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index 7e5c84533..bbd869eda 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -114,6 +114,38 @@ void GLSLSourceEmitter::_requireGLSLVersion(int version) } } +void GLSLSourceEmitter::_emitMemoryQualifierDecorations(IRInst* varDecl) +{ + for (auto decoration : varDecl->getDecorations()) + { + if (as<IRGloballyCoherentDecoration>(decoration)) + { + m_writer->emit("coherent "); + } + else if (as<IRGLSLVolatileDecoration>(decoration)) + { + m_writer->emit("volatile "); + } + else if (as<IRGLSLRestrictDecoration>(decoration)) + { + m_writer->emit("restrict "); + } + else if (as<IRGLSLReadOnlyDecoration>(decoration)) + { + m_writer->emit("readonly "); + } + else if (as<IRGLSLWriteOnlyDecoration>(decoration)) + { + m_writer->emit("writeonly "); + } + } +} + +void GLSLSourceEmitter::emitMemoryQualifiers(IRInst* varDecl) +{ + _emitMemoryQualifierDecorations(varDecl); +} + void GLSLSourceEmitter::_emitGLSLStructuredBuffer(IRGlobalParam* varDecl, IRHLSLStructuredBufferTypeBase* structuredBufferType) { // Shader storage buffer is an OpenGL 430 feature @@ -182,10 +214,7 @@ void GLSLSourceEmitter::_emitGLSLStructuredBuffer(IRGlobalParam* varDecl, IRHLSL HLSLAppendStructuredBufferType - Write HLSLConsumeStructuredBufferType - TODO (JS): Its possible that this can be readonly, but we currently don't support on GLSL */ - if (varDecl->findDecoration<IRGloballyCoherentDecoration>()) - { - m_writer->emit("coherent "); - } + _emitMemoryQualifierDecorations(varDecl); if (as<IRHLSLStructuredBufferType>(structuredBufferType)) { m_writer->emit("readonly "); @@ -288,10 +317,7 @@ void GLSLSourceEmitter::emitSSBOHeader(IRGlobalParam* varDecl, IRType* bufferTyp } m_writer->emit(") "); - if (varDecl->findDecoration<IRGloballyCoherentDecoration>()) - { - m_writer->emit("coherent "); - } + _emitMemoryQualifierDecorations(varDecl); /* If the output type is a buffer, and we can determine it is only readonly we can prefix before @@ -461,6 +487,11 @@ void GLSLSourceEmitter::_emitGLSLImageFormatModifier(IRInst* var, IRTextureType* } else { + auto formatInfo = getImageFormatInfo(format); + if (formatInfo.scalarType == SLANG_SCALAR_TYPE_UINT64 || formatInfo.scalarType == SLANG_SCALAR_TYPE_INT64) + { + _requireGLSLExtension(UnownedStringSlice::fromLiteral("GL_EXT_shader_image_int64")); + } // If there is an explicit format specified, then we // should emit a `layout` modifier using the GLSL name // for the format. diff --git a/source/slang/slang-emit-glsl.h b/source/slang/slang-emit-glsl.h index 1a95cd346..610a961d2 100644 --- a/source/slang/slang-emit-glsl.h +++ b/source/slang/slang-emit-glsl.h @@ -35,6 +35,7 @@ protected: virtual void emitInterpolationModifiersImpl(IRInst* varInst, IRType* valueType, IRVarLayout* layout) SLANG_OVERRIDE; virtual void emitPackOffsetModifier(IRInst* varInst, IRType* valueType, IRPackOffsetDecoration* decoration) SLANG_OVERRIDE; + virtual void emitMemoryQualifiers(IRInst* varInst) SLANG_OVERRIDE; virtual void emitMeshShaderModifiersImpl(IRInst* varInst) SLANG_OVERRIDE; virtual void emitSimpleTypeImpl(IRType* type) SLANG_OVERRIDE; virtual void emitVectorTypeNameImpl(IRType* elementType, IRIntegerValue elementCount) SLANG_OVERRIDE; @@ -56,6 +57,7 @@ protected: virtual void emitSimpleValueImpl(IRInst* inst) SLANG_OVERRIDE; virtual void emitLoopControlDecorationImpl(IRLoopControlDecoration* decl) SLANG_OVERRIDE; + void _emitMemoryQualifierDecorations(IRInst* varDecl); void _emitGLSLTextureOrTextureSamplerType(IRTextureTypeBase* type, char const* baseName); void _emitGLSLStructuredBuffer(IRGlobalParam* varDecl, IRHLSLStructuredBufferTypeBase* structuredBufferType); diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index c48f0e978..ddcd5ae4d 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -1765,6 +1765,40 @@ struct SPIRVEmitContext } } + void setImageFormatCapabilityAndExtension(SpvImageFormat format, SpvCapability_ setCapabilityMask) + { + switch (format) + { + case SpvImageFormatUnknown: + case SpvImageFormatRgba32f: + case SpvImageFormatRgba16f: + case SpvImageFormatR32f: + case SpvImageFormatRgba8: + case SpvImageFormatRgba8Snorm: + case SpvImageFormatRgba32i: + case SpvImageFormatRgba16i: + case SpvImageFormatRgba8i: + case SpvImageFormatR32i: + case SpvImageFormatRgba32ui: + case SpvImageFormatRgba16ui: + case SpvImageFormatRgba8ui: + case SpvImageFormatR32ui: + if(setCapabilityMask == SpvCapabilityShader) return; + requireSPIRVCapability(SpvCapabilityShader); + return; + case SpvImageFormatR64ui: + case SpvImageFormatR64i: + if(setCapabilityMask == SpvCapabilityInt64ImageEXT) return; + ensureExtensionDeclaration(UnownedStringSlice("SPV_EXT_shader_image_int64")); + requireSPIRVCapability(SpvCapabilityInt64ImageEXT); + return; + default: + if(setCapabilityMask == SpvCapabilityStorageImageExtendedFormats) return; + requireSPIRVCapability(SpvCapabilityStorageImageExtendedFormats); + return; + } + } + SpvInst* ensureTextureType(IRInst* assignee, IRTextureTypeBase* inst) { // Some untyped constants from OpTypeImage @@ -1895,6 +1929,8 @@ struct SPIRVEmitContext // // SPIR-V requires that the sampled/rw info on the image isn't unknown SLANG_ASSERT(sampled == sampledImage || sampled == readWriteImage); + if(isMultisampled) + requireSPIRVCapability(SpvCapabilityStorageImageMultisample); switch(dim) { case SpvDim1D: @@ -1933,9 +1969,7 @@ struct SPIRVEmitContext requireSPIRVCapability(SpvCapabilityStorageImageWriteWithoutFormat); } - auto formatCapability = getImageFormatCapability(format); - if (formatCapability != SpvCapabilityShader) - requireSPIRVCapability(formatCapability); + setImageFormatCapabilityAndExtension(format, SpvCapabilityShader); // // The op itself @@ -3266,6 +3300,30 @@ struct SPIRVEmitContext dstID, SpvDecorationCoherent); break; + case kIROp_GLSLVolatileDecoration: + emitOpDecorate(getSection(SpvLogicalSectionID::Annotations), + decoration, + dstID, + SpvDecorationVolatile); + break; + case kIROp_GLSLRestrictDecoration: + emitOpDecorate(getSection(SpvLogicalSectionID::Annotations), + decoration, + dstID, + SpvDecorationRestrict); + break; + case kIROp_GLSLReadOnlyDecoration: + emitOpDecorate(getSection(SpvLogicalSectionID::Annotations), + decoration, + dstID, + SpvDecorationNonWritable); + break; + case kIROp_GLSLWriteOnlyDecoration: + emitOpDecorate(getSection(SpvLogicalSectionID::Annotations), + decoration, + dstID, + SpvDecorationNonReadable); + break; // ... } diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 63f063154..254a411cd 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -660,6 +660,8 @@ INST(GetOptiXSbtDataPtr, getOptiXSbtDataPointer, 0, 0) INST(GetVulkanRayTracingPayloadLocation, GetVulkanRayTracingPayloadLocation, 1, 0) +INST(GetLegalizedSPIRVGlobalParamAddr, kIROp_GetLegalizedSPIRVGlobalParamAddr, 1, 0) + INST(MakeArrayList, makeArrayList, 0, 0) INST(MakeTensorView, makeTensorView, 0, 0) INST(AllocateTorchTensor, allocTorchTensor, 0, 0) @@ -856,6 +858,10 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) INST(GlobalInputDecoration, output, 0, 0) INST(GLSLLocationDecoration, glslLocation, 1, 0) INST(GLSLOffsetDecoration, glslOffset, 1, 0) + INST(GLSLVolatileDecoration, glslVolatile, 1, 0) + INST(GLSLRestrictDecoration, glslRestrict, 1, 0) + INST(GLSLReadOnlyDecoration, glslReadonly, 1, 0) + INST(GLSLWriteOnlyDecoration, glslWriteonly, 1, 0) INST(PayloadDecoration, payload, 0, 0) /* Mesh Shader outputs */ diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 36f9159a8..c884dd35f 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -354,6 +354,10 @@ IR_SIMPLE_DECORATION(ReadNoneDecoration) IR_SIMPLE_DECORATION(NoSideEffectDecoration) IR_SIMPLE_DECORATION(EarlyDepthStencilDecoration) IR_SIMPLE_DECORATION(GloballyCoherentDecoration) +IR_SIMPLE_DECORATION(GLSLVolatileDecoration) +IR_SIMPLE_DECORATION(GLSLRestrictDecoration) +IR_SIMPLE_DECORATION(GLSLReadOnlyDecoration) +IR_SIMPLE_DECORATION(GLSLWriteOnlyDecoration) IR_SIMPLE_DECORATION(PreciseDecoration) IR_SIMPLE_DECORATION(PublicDecoration) IR_SIMPLE_DECORATION(HLSLExportDecoration) diff --git a/source/slang/slang-ir-spirv-legalize.cpp b/source/slang/slang-ir-spirv-legalize.cpp index ca3729abc..68f1e02a2 100644 --- a/source/slang/slang-ir-spirv-legalize.cpp +++ b/source/slang/slang-ir-spirv-legalize.cpp @@ -217,7 +217,12 @@ struct SPIRVLegalizationContext : public SourceEmitterBase IRBuilder builder(user); builder.setInsertBefore(user); - if((as<IRGetElement>(user) || as<IRFieldExtract>(user)) && + if(user->getOp() == kIROp_GetLegalizedSPIRVGlobalParamAddr) + { + user->replaceUsesWith(use->get()); + user->removeAndDeallocate(); + } + else if((as<IRGetElement>(user) || as<IRFieldExtract>(user)) && use == user->getOperands()) { // If the use is the address operand of a getElement or FieldExtract, diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 3dd8da9f1..41638dc83 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -2217,6 +2217,22 @@ void addVarDecorations( { builder->addDynamicUniformDecoration(inst); } + else if (as<GLSLVolatileModifier>(mod)) + { + builder->addSimpleDecoration<IRGLSLVolatileDecoration>(inst); + } + else if (as<GLSLRestrictModifier>(mod)) + { + builder->addSimpleDecoration<IRGLSLRestrictDecoration>(inst); + } + else if (as<GLSLReadOnlyModifier>(mod)) + { + builder->addSimpleDecoration<IRGLSLReadOnlyDecoration>(inst); + } + else if (as<GLSLWriteOnlyModifier>(mod)) + { + builder->addSimpleDecoration<IRGLSLWriteOnlyDecoration>(inst); + } // TODO: what are other modifiers we need to propagate through? } if(auto t = composeGetters<IRMeshOutputType>(inst->getFullType(), &IROutTypeBase::getValueType)) diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index f7a0376ce..5b8a1af4f 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -7843,6 +7843,70 @@ namespace Slang parser->sink->diagnose(token, Diagnostics::invalidCUDASMVersion); return nullptr; } + static NodeBase* parseVolatileModifier(Parser* parser, void* /*userData*/) + { + ModifierListBuilder listBuilder; + + auto hlslMod = parser->astBuilder->create<HLSLVolatileModifier>(); + hlslMod->keywordName = getName(parser, "volatile"); + hlslMod->loc = parser->tokenReader.peekLoc(); + listBuilder.add(hlslMod); + + auto glslMod = parser->astBuilder->create<GLSLVolatileModifier>(); + glslMod->keywordName = getName(parser, "volatile"); + glslMod->loc = parser->tokenReader.peekLoc(); + listBuilder.add(glslMod); + + return listBuilder.getFirst(); + } + + static NodeBase* parseCoherentModifier(Parser* parser, void* /*userData*/) + { + ModifierListBuilder listBuilder; + + auto glslMod = parser->astBuilder->create<GloballyCoherentModifier>(); + glslMod->keywordName = getName(parser, "coherent"); + glslMod->loc = parser->tokenReader.peekLoc(); + listBuilder.add(glslMod); + + return listBuilder.getFirst(); + } + + static NodeBase* parseRestrictModifier(Parser* parser, void* /*userData*/) + { + ModifierListBuilder listBuilder; + + auto glslMod = parser->astBuilder->create<GLSLRestrictModifier>(); + glslMod->keywordName = getName(parser, "restrict"); + glslMod->loc = parser->tokenReader.peekLoc(); + listBuilder.add(glslMod); + + return listBuilder.getFirst(); + } + + static NodeBase* parseReadonlyModifier(Parser* parser, void* /*userData*/) + { + ModifierListBuilder listBuilder; + + auto glslMod = parser->astBuilder->create<GLSLReadOnlyModifier>(); + glslMod->keywordName = getName(parser, "readonly"); + glslMod->loc = parser->tokenReader.peekLoc(); + listBuilder.add(glslMod); + + return listBuilder.getFirst(); + } + + static NodeBase* parseWriteonlyModifier(Parser* parser, void* /*userData*/) + { + ModifierListBuilder listBuilder; + + auto glslMod = parser->astBuilder->create<GLSLWriteOnlyModifier>(); + glslMod->keywordName = getName(parser, "writeonly"); + glslMod->loc = parser->tokenReader.peekLoc(); + listBuilder.add(glslMod); + + return listBuilder.getFirst(); + } static NodeBase* parseLayoutModifier(Parser* parser, void* /*userData*/) { @@ -7850,6 +7914,8 @@ namespace Slang GLSLLayoutLocalSizeAttribute* numThreadsAttrib = nullptr; + ImageFormat format; + listBuilder.add(parser->astBuilder->create<GLSLLayoutModifierGroupBegin>()); parser->ReadToken(TokenType::LParent); @@ -7923,6 +7989,12 @@ namespace Slang } } } + else if(findImageFormatByName(nameText.getUnownedSlice(), &format)) + { + auto attr = parser->astBuilder->create<FormatAttribute>(); + attr->format = format; + listBuilder.add(attr); + } else { Modifier* modifier = nullptr; @@ -8208,7 +8280,11 @@ namespace Slang _makeParseModifier("groupshared", HLSLGroupSharedModifier::kReflectClassInfo), _makeParseModifier("static", HLSLStaticModifier::kReflectClassInfo), _makeParseModifier("uniform", HLSLUniformModifier::kReflectClassInfo), - _makeParseModifier("volatile", HLSLVolatileModifier::kReflectClassInfo), + _makeParseModifier("volatile", parseVolatileModifier), + _makeParseModifier("coherent", parseCoherentModifier), + _makeParseModifier("restrict", parseRestrictModifier), + _makeParseModifier("readonly", parseReadonlyModifier), + _makeParseModifier("writeonly", parseWriteonlyModifier), _makeParseModifier("export", HLSLExportModifier::kReflectClassInfo), _makeParseModifier("dynamic_uniform", DynamicUniformModifier::kReflectClassInfo), diff --git a/tests/glsl-intrinsic/image/i64imageDim.slang b/tests/glsl-intrinsic/image/i64imageDim.slang new file mode 100644 index 000000000..a6d38153e --- /dev/null +++ b/tests/glsl-intrinsic/image/i64imageDim.slang @@ -0,0 +1,476 @@ +//TEST:SIMPLE(filecheck=CHECK_GLSL): -allow-glsl -stage compute -entry computeMain -target glsl +//TEST:SIMPLE(filecheck=CHECK_SPV): -allow-glsl -stage compute -entry computeMain -target spirv -emit-spirv-directly +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl -emit-spirv-directly + +// As per vulkan specification: https://registry.khronos.org/vulkan/specs/1.3/html/chap34.html#formats-definition +// i64/u64 images do not require sampled image support; support is currently unlikley on hardware +//#define test_when_hardware_supports_i64_and_u64_sampled_textures +// i64/u64 images do not require texel buffers support; support is currently unlikley on hardware +//#define TEST_when_hardware_supports_i64_and_u64_buffers + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer +buffer MyBlockName2 +{ + uint data[1]; +} outputBuffer; + +layout(local_size_x = 1) in; + +//TEST_INPUT: set image_1d = RWTexture1D(format=R64_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=0,r64i) i64image1D image_1d; +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers +//COM:TEST_INPUT: set image_buffer = RWTextureBuffer(format=R64_INT, stride=8, data=[0 1 0 1 0 1 0 1]) +uniform layout(binding=1,r64i) i64imageBuffer image_buffer; +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers +//TEST_INPUT: set image_1dArray = RWTexture1D(format=R64_SINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=2,r64i) i64image1DArray image_1dArray; +//TEST_INPUT: set image_2d = RWTexture2D(format=R64_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=3,r64i) i64image2D image_2d; +//TEST_INPUT: set image_2dRect = RWTexture2D(format=R64_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=4,r64i) i64image2DRect image_2dRect; +//TEST_INPUT: set image_2dArray = RWTexture2D(format=R64_SINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=6,r64i) i64image2DArray image_2dArray; +//TEST_INPUT: set image_3d = RWTexture3D(format=R64_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=7,r64i) i64image3D image_3d; +//TEST_INPUT: set image_cube = RWTextureCube(format=R64_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=8,r64i) i64imageCube image_cube; +//TEST_INPUT: set image_cubeArray = RWTextureCube(format=R64_SINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=9,r64i) i64imageCubeArray image_cubeArray; +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures +//COM:TEST_INPUT: set image_2dMultiSample = RWTexture2D(format=R64_SINT, size=4, content=one, mipMaps = 1, sampleCount = two) +uniform layout(binding=5,r64i) i64image2DMS image_2dMultiSample; +//COM:TEST_INPUT: set image_2dMultiSampleArray = RWTexture2D(format=R64_SINT, size=4, content=one, mipMaps = 1, arrayLength=2, sampleCount = two) +uniform layout(binding=10,r64i) i64image2DMSArray image_2dMultiSampleArray; +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + +bool checkAllImageSize() +{ + return true + && imageSize(image_1d) == int(4) +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageSize(image_buffer) == int(4) +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageSize(image_1dArray) == ivec2(4, 2) + && imageSize(image_2d) == ivec2(4) + && imageSize(image_2dArray) == ivec3(4, 4, 2) + && imageSize(image_2dRect) == ivec2(4) + && imageSize(image_3d) == ivec3(4) + && imageSize(image_cube) == ivec2(4) + && imageSize(image_cubeArray) == ivec3(4, 4, 2) +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageSize(image_2dMultiSample) == ivec2(4) + && imageSize(image_2dMultiSampleArray) == ivec3(4, 4, 2) +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageLoad() +{ + return true + && imageLoad(image_1d, 0).x == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageLoad(image_buffer, 0).x == 1 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageLoad(image_1dArray, ivec2(0)).x == 1 + && imageLoad(image_2d, ivec2(0)).x == 1 + && imageLoad(image_2dRect, ivec2(0)).x == 1 + && imageLoad(image_2dArray, ivec3(0)).x == 1 + && imageLoad(image_3d, ivec3(0)).x == 1 + && imageLoad(image_cube, ivec3(0)).x == 1 + && imageLoad(image_cubeArray, ivec3(0)).x == 1 + && imageLoad(image_cubeArray, ivec3(0)).x == 1 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageLoad(image_2dMultiSample, ivec2(0), 1).x == 1 + && imageLoad(image_2dMultiSampleArray, ivec3(0), 1).x == 1 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool resetAllImageValues() +{ + imageStore(image_1d, 0,i64vec4(1)); +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + imageStore(image_buffer, 0,i64vec4(1)); +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + imageStore(image_1dArray, ivec2(0),i64vec4(1)); + imageStore(image_2d, ivec2(0),i64vec4(1)); + imageStore(image_2dRect, ivec2(0),i64vec4(1)); + imageStore(image_2dArray, ivec3(0),i64vec4(1)); + imageStore(image_3d, ivec3(0),i64vec4(1)); + imageStore(image_cube, ivec3(0),i64vec4(1)); + imageStore(image_cubeArray, ivec3(0),i64vec4(1)); +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + imageStore(image_2dMultiSample, ivec2(0), 1, i64vec4(1)); + imageStore(image_2dMultiSampleArray, ivec3(0), 1,i64vec4(1)); +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + return true; +} +int64_t load_image_1d() +{ + return imageLoad(image_1d, 0).x; +} +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers +int64_t load_image_buffer() +{ + return imageLoad(image_buffer, 0).x; +} +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers +int64_t load_image_1dArray() +{ + return imageLoad(image_1dArray, ivec2(0)).x; +} +int64_t load_image_2d() +{ + return imageLoad(image_2d, ivec2(0)).x; +} +int64_t load_image_2dRect() +{ + return imageLoad(image_2dRect, ivec2(0)).x; +} +int64_t load_image_2dArray() +{ + return imageLoad(image_2dArray, ivec3(0)).x; +} +int64_t load_image_3d() +{ + return imageLoad(image_3d, ivec3(0)).x; +} +int64_t load_image_cube() +{ + return imageLoad(image_cube, ivec3(0)).x; +} +int64_t load_image_cubeArray() +{ + return imageLoad(image_cubeArray, ivec3(0)).x; +} +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures +int64_t load_image_2dMultiSample() +{ + return imageLoad(image_2dMultiSample, ivec2(0), 1).x; +} +int64_t load_image_2dMultiSampleArray() +{ + return imageLoad(image_2dMultiSampleArray, ivec3(0), 1).x; +} +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + +// requires ImageLoad test to pass +bool checkAllImageStore() +{ + bool loadCheck = true; + + imageStore(image_1d, 0,i64vec4(0)); + loadCheck = loadCheck && load_image_1d() == 0; +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + imageStore(image_buffer, 0,i64vec4(0)); + loadCheck = loadCheck && load_image_buffer() == 0; +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + imageStore(image_1dArray, ivec2(0),i64vec4(0)); + loadCheck = loadCheck && load_image_1dArray() == 0; + imageStore(image_2d, ivec2(0),i64vec4(0)); + loadCheck = loadCheck && load_image_2d() == 0; + imageStore(image_2dRect, ivec2(0),i64vec4(0)); + loadCheck = loadCheck && load_image_2dRect() == 0; + imageStore(image_2dArray, ivec3(0),i64vec4(0)); + loadCheck = loadCheck && load_image_2dArray() == 0; + imageStore(image_3d, ivec3(0),i64vec4(0)); + loadCheck = loadCheck && load_image_3d() == 0; + imageStore(image_cube, ivec3(0),i64vec4(0)); + loadCheck = loadCheck && load_image_cube() == 0; + imageStore(image_cubeArray, ivec3(0),i64vec4(0)); + loadCheck = loadCheck && load_image_cubeArray() == 0; +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + imageStore(image_2dMultiSample, ivec2(0), 1, i64vec4(0)); + loadCheck = loadCheck && load_image_2dMultiSample() == 0; + imageStore(image_2dMultiSampleArray, ivec3(0), 1,i64vec4(0)); + loadCheck = loadCheck && load_image_2dMultiSampleArray() == 0; +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + resetAllImageValues(); + return loadCheck; +} +bool checkAllImageSamples() +{ + resetAllImageValues(); + return true +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageSamples(image_2dMultiSample) == 2 + && imageSamples(image_2dMultiSampleArray) == 2 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicAdd() +{ + resetAllImageValues(); + return true + && imageAtomicAdd(image_1d, 0, 0) == 1 + && load_image_1d() == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicAdd(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicAdd(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 1 + && imageAtomicAdd(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicAdd(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicAdd(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 1 + && imageAtomicAdd(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicAdd(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicAdd(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicAdd(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicAdd(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicExchange() +{ + resetAllImageValues(); + return true + && imageAtomicExchange(image_1d, 0, 0) == 1 + && load_image_1d() == 0 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicExchange(image_buffer, 0, 2) == 1 + && load_image_buffer() == 2 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicExchange(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 0 + && imageAtomicExchange(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 2 + && imageAtomicExchange(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicExchange(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 0 + && imageAtomicExchange(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 2 + && imageAtomicExchange(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 2 + && imageAtomicExchange(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 2 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicExchange(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicExchange(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicMin() +{ + resetAllImageValues(); + return true + && imageAtomicMin(image_1d, 0, 0) == 1 + && load_image_1d() == 0 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicMin(image_buffer, 0, 2) == 1 + && load_image_buffer() == 1 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicMin(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 0 + && imageAtomicMin(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 1 + && imageAtomicMin(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 1 + && imageAtomicMin(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 0 + && imageAtomicMin(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 1 + && imageAtomicMin(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 1 + && imageAtomicMin(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 1 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicMin(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 1 + && imageAtomicMin(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 1 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicMax() +{ + resetAllImageValues(); + return true + && imageAtomicMax(image_1d, 0, 0) == 1 + && load_image_1d() == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicMax(image_buffer, 0, 2) == 1 + && load_image_buffer() == 2 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicMax(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 1 + && imageAtomicMax(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 2 + && imageAtomicMax(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicMax(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 1 + && imageAtomicMax(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 2 + && imageAtomicMax(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 2 + && imageAtomicMax(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 2 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicMax(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicMax(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicAnd() +{ + resetAllImageValues(); + return true + && imageAtomicAnd(image_1d, 0, 1) == 1 + && load_image_1d() == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicAnd(image_buffer, 0, 2) == 1 + && load_image_buffer() == 0 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicAnd(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 1 + && imageAtomicAnd(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 0 + && imageAtomicAnd(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 0 + && imageAtomicAnd(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 1 + && imageAtomicAnd(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 0 + && imageAtomicAnd(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 0 + && imageAtomicAnd(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 0 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicAnd(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 0 + && imageAtomicAnd(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 0 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicOr() +{ + resetAllImageValues(); + return true + && imageAtomicOr(image_1d, 0, 1) == 1 + && load_image_1d() == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicOr(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicOr(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 1 + && imageAtomicOr(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicOr(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicOr(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 1 + && imageAtomicOr(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicOr(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicOr(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicOr(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicOr(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicXor() +{ + resetAllImageValues(); + return true + && imageAtomicXor(image_1d, 0, 1) == 1 + && load_image_1d() == 0 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicXor(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicXor(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 0 + && imageAtomicXor(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicXor(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicXor(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 0 + && imageAtomicXor(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicXor(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicXor(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicXor(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicXor(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicCompSwap() +{ + resetAllImageValues(); + return true + && imageAtomicCompSwap(image_1d, 0, 0, 2) == 1 + && load_image_1d() == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicCompSwap(image_buffer, 0, 1, 2) == 1 + && load_image_buffer() == 2 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicCompSwap(image_1dArray, ivec2(0), 0, 2) == 1 + && load_image_1dArray() == 1 + && imageAtomicCompSwap(image_2d, ivec2(0), 1, 2) == 1 + && load_image_2d() == 2 + && imageAtomicCompSwap(image_2dRect, ivec2(0), 1, 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicCompSwap(image_2dArray, ivec3(0), 0, 2) == 1 + && load_image_2dArray() == 1 + && imageAtomicCompSwap(image_3d, ivec3(0), 1, 2) == 1 + && load_image_3d() == 2 + && imageAtomicCompSwap(image_cube, ivec3(0), 1, 2) == 1 + && load_image_cube() == 2 + && imageAtomicCompSwap(image_cubeArray, ivec3(0), 1, 2) == 1 + && load_image_cubeArray() == 2 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicCompSwap(image_2dMultiSample, ivec2(0), 1, 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicCompSwap(image_2dMultiSampleArray, ivec3(0), 1, 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} + +// CHECK_GLSL: void main( +// CHECK_SPV: OpEntryPoint +void computeMain() +{ + outputBuffer.data[0] = true + && checkAllImageSize() + && checkAllImageLoad() + && checkAllImageStore() + && checkAllImageSamples() + && checkAllImageAtomicAdd() + && checkAllImageAtomicExchange() + && checkAllImageAtomicMin() + && checkAllImageAtomicMax() + && checkAllImageAtomicAnd() + && checkAllImageAtomicOr() + && checkAllImageAtomicXor() + && checkAllImageAtomicCompSwap() + ; + // BUF: 1 +} diff --git a/tests/glsl-intrinsic/image/iimageDim.slang b/tests/glsl-intrinsic/image/iimageDim.slang new file mode 100644 index 000000000..cb9756d56 --- /dev/null +++ b/tests/glsl-intrinsic/image/iimageDim.slang @@ -0,0 +1,411 @@ +//TEST:SIMPLE(filecheck=CHECK_GLSL): -allow-glsl -stage compute -entry computeMain -target glsl +//TEST:SIMPLE(filecheck=CHECK_SPV): -allow-glsl -stage compute -entry computeMain -target spirv -emit-spirv-directly +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl -emit-spirv-directly + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer +buffer MyBlockName2 +{ + uint data[1]; +} outputBuffer; + +layout(local_size_x = 1) in; + +//TEST_INPUT: set image_1d = RWTexture1D(format=R32_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=0,r32i) iimage1D image_1d; +//TEST_INPUT: set image_buffer = RWTextureBuffer(format=R32_SINT, stride=8, data=[1 1 1 1]) +uniform layout(binding=1,r32i) iimageBuffer image_buffer; +//TEST_INPUT: set image_1dArray = RWTexture1D(format=R32_SINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=2,r32i) iimage1DArray image_1dArray; +//TEST_INPUT: set image_2d = RWTexture2D(format=R32_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=3,r32i) iimage2D image_2d; +//TEST_INPUT: set image_2dRect = RWTexture2D(format=R32_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=4,r32i) iimage2DRect image_2dRect; +//TEST_INPUT: set image_2dMultiSample = RWTexture2D(format=R32_SINT, size=4, content=one, mipMaps = 1, sampleCount = two) +uniform layout(binding=5,r32i) iimage2DMS image_2dMultiSample; +//TEST_INPUT: set image_2dArray = RWTexture2D(format=R32_SINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=6,r32i) iimage2DArray image_2dArray; +//TEST_INPUT: set image_3d = RWTexture3D(format=R32_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=7,r32i) iimage3D image_3d; +//TEST_INPUT: set image_cube = RWTextureCube(format=R32_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=8,r32i) iimageCube image_cube; +//TEST_INPUT: set image_cubeArray = RWTextureCube(format=R32_SINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=9,r32i) iimageCubeArray image_cubeArray; +//TEST_INPUT: set image_2dMultiSampleArray = RWTexture2D(format=R32_SINT, size=4, content=one, mipMaps = 1, arrayLength=2, sampleCount = two) +uniform layout(binding=10,r32i) iimage2DMSArray image_2dMultiSampleArray; + +bool checkAllImageSize() +{ + return true + && imageSize(image_1d) == int(4) + && imageSize(image_buffer) == int(4) + && imageSize(image_1dArray) == ivec2(4, 2) + && imageSize(image_2d) == ivec2(4) + && imageSize(image_2dArray) == ivec3(4, 4, 2) + && imageSize(image_2dRect) == ivec2(4) + && imageSize(image_2dMultiSample) == ivec2(4) + && imageSize(image_3d) == ivec3(4) + && imageSize(image_cube) == ivec2(4) + && imageSize(image_cubeArray) == ivec3(4, 4, 2) + && imageSize(image_2dMultiSampleArray) == ivec3(4, 4, 2) + ; +} +bool checkAllImageLoad() +{ + return true + && imageLoad(image_1d, 0).x == 1 + && imageLoad(image_buffer, 0).x == 1 + && imageLoad(image_1dArray, ivec2(0)).x == 1 + && imageLoad(image_2d, ivec2(0)).x == 1 + && imageLoad(image_2dRect, ivec2(0)).x == 1 + && imageLoad(image_2dMultiSample, ivec2(0), 1).x == 1 + && imageLoad(image_2dArray, ivec3(0)).x == 1 + && imageLoad(image_3d, ivec3(0)).x == 1 + && imageLoad(image_cube, ivec3(0)).x == 1 + && imageLoad(image_cubeArray, ivec3(0)).x == 1 + && imageLoad(image_cubeArray, ivec3(0)).x == 1 + && imageLoad(image_2dMultiSampleArray, ivec3(0), 1).x == 1 + ; +} +bool resetAllImageValues() +{ + imageStore(image_1d, 0, ivec4(1)); + imageStore(image_buffer, 0, ivec4(1)); + imageStore(image_1dArray, ivec2(0), ivec4(1)); + imageStore(image_2d, ivec2(0), ivec4(1)); + imageStore(image_2dRect, ivec2(0), ivec4(1)); + imageStore(image_2dMultiSample, ivec2(0), 1, ivec4(1)); + imageStore(image_2dArray, ivec3(0), ivec4(1)); + imageStore(image_3d, ivec3(0), ivec4(1)); + imageStore(image_cube, ivec3(0), ivec4(1)); + imageStore(image_cubeArray, ivec3(0), ivec4(1)); + imageStore(image_2dMultiSampleArray, ivec3(0), 1, ivec4(1)); + return true; +} +int load_image_1d() +{ + return imageLoad(image_1d, 0).x; +} +int load_image_buffer() +{ + return imageLoad(image_buffer, 0).x; +} +int load_image_1dArray() +{ + return imageLoad(image_1dArray, ivec2(0)).x; +} +int load_image_2d() +{ + return imageLoad(image_2d, ivec2(0)).x; +} +int load_image_2dRect() +{ + return imageLoad(image_2dRect, ivec2(0)).x; +} +int load_image_2dMultiSample() +{ + return imageLoad(image_2dMultiSample, ivec2(0), 1).x; +} +int load_image_2dArray() +{ + return imageLoad(image_2dArray, ivec3(0)).x; +} +int load_image_3d() +{ + return imageLoad(image_3d, ivec3(0)).x; +} +int load_image_cube() +{ + return imageLoad(image_cube, ivec3(0)).x; +} +int load_image_cubeArray() +{ + return imageLoad(image_cubeArray, ivec3(0)).x; +} +int load_image_2dMultiSampleArray() +{ + return imageLoad(image_2dMultiSampleArray, ivec3(0), 1).x; +} +// requires ImageLoad test to pass +bool checkAllImageStore() +{ + bool loadCheck = true; + + imageStore(image_1d, 0, ivec4(0)); + loadCheck = loadCheck && load_image_1d() == 0; + imageStore(image_buffer, 0, ivec4(0)); + loadCheck = loadCheck && load_image_buffer() == 0; + imageStore(image_1dArray, ivec2(0), ivec4(0)); + loadCheck = loadCheck && load_image_1dArray() == 0; + imageStore(image_2d, ivec2(0), ivec4(0)); + loadCheck = loadCheck && load_image_2d() == 0; + imageStore(image_2dRect, ivec2(0), ivec4(0)); + loadCheck = loadCheck && load_image_2dRect() == 0; + imageStore(image_2dMultiSample, ivec2(0), 1, ivec4(0)); + loadCheck = loadCheck && load_image_2dMultiSample() == 0; + imageStore(image_2dArray, ivec3(0), ivec4(0)); + loadCheck = loadCheck && load_image_2dArray() == 0; + imageStore(image_3d, ivec3(0), ivec4(0)); + loadCheck = loadCheck && load_image_3d() == 0; + imageStore(image_cube, ivec3(0), ivec4(0)); + loadCheck = loadCheck && load_image_cube() == 0; + imageStore(image_cubeArray, ivec3(0), ivec4(0)); + loadCheck = loadCheck && load_image_cubeArray() == 0; + imageStore(image_2dMultiSampleArray, ivec3(0), 1, ivec4(0)); + loadCheck = loadCheck && load_image_2dMultiSampleArray() == 0; + resetAllImageValues(); + return loadCheck; +} +bool checkAllImageSamples() +{ + resetAllImageValues(); + return true + && imageSamples(image_2dMultiSample) == 2 + && imageSamples(image_2dMultiSampleArray) == 2 + ; +} +bool checkAllImageAtomicAdd() +{ + resetAllImageValues(); + return true + && imageAtomicAdd(image_1d, 0, 0) == 1 + && load_image_1d() == 1 + && imageAtomicAdd(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 + && imageAtomicAdd(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 1 + && imageAtomicAdd(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicAdd(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicAdd(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicAdd(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 1 + && imageAtomicAdd(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicAdd(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicAdd(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 + && imageAtomicAdd(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 + ; +} +bool checkAllImageAtomicExchange() +{ + resetAllImageValues(); + return true + && imageAtomicExchange(image_1d, 0, 0) == 1 + && load_image_1d() == 0 + && imageAtomicExchange(image_buffer, 0, 2) == 1 + && load_image_buffer() == 2 + && imageAtomicExchange(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 0 + && imageAtomicExchange(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 2 + && imageAtomicExchange(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicExchange(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicExchange(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 0 + && imageAtomicExchange(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 2 + && imageAtomicExchange(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 2 + && imageAtomicExchange(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 2 + && imageAtomicExchange(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 + ; +} +bool checkAllImageAtomicMin() +{ + resetAllImageValues(); + return true + && imageAtomicMin(image_1d, 0, 0) == 1 + && load_image_1d() == 0 + && imageAtomicMin(image_buffer, 0, 2) == 1 + && load_image_buffer() == 1 + && imageAtomicMin(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 0 + && imageAtomicMin(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 1 + && imageAtomicMin(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 1 + && imageAtomicMin(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 1 + && imageAtomicMin(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 0 + && imageAtomicMin(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 1 + && imageAtomicMin(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 1 + && imageAtomicMin(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 1 + && imageAtomicMin(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 1 + ; +} +bool checkAllImageAtomicMax() +{ + resetAllImageValues(); + return true + && imageAtomicMax(image_1d, 0, 0) == 1 + && load_image_1d() == 1 + && imageAtomicMax(image_buffer, 0, 2) == 1 + && load_image_buffer() == 2 + && imageAtomicMax(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 1 + && imageAtomicMax(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 2 + && imageAtomicMax(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicMax(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicMax(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 1 + && imageAtomicMax(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 2 + && imageAtomicMax(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 2 + && imageAtomicMax(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 2 + && imageAtomicMax(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 + ; +} +bool checkAllImageAtomicAnd() +{ + resetAllImageValues(); + return true + && imageAtomicAnd(image_1d, 0, 1) == 1 + && load_image_1d() == 1 + && imageAtomicAnd(image_buffer, 0, 2) == 1 + && load_image_buffer() == 0 + && imageAtomicAnd(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 1 + && imageAtomicAnd(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 0 + && imageAtomicAnd(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 0 + && imageAtomicAnd(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 0 + && imageAtomicAnd(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 1 + && imageAtomicAnd(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 0 + && imageAtomicAnd(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 0 + && imageAtomicAnd(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 0 + && imageAtomicAnd(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 0 + ; +} +bool checkAllImageAtomicOr() +{ + resetAllImageValues(); + return true + && imageAtomicOr(image_1d, 0, 1) == 1 + && load_image_1d() == 1 + && imageAtomicOr(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 + && imageAtomicOr(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 1 + && imageAtomicOr(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicOr(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicOr(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicOr(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 1 + && imageAtomicOr(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicOr(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicOr(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 + && imageAtomicOr(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 + ; +} +bool checkAllImageAtomicXor() +{ + resetAllImageValues(); + return true + && imageAtomicXor(image_1d, 0, 1) == 1 + && load_image_1d() == 0 + && imageAtomicXor(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 + && imageAtomicXor(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 0 + && imageAtomicXor(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicXor(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicXor(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicXor(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 0 + && imageAtomicXor(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicXor(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicXor(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 + && imageAtomicXor(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 + ; +} +bool checkAllImageAtomicCompSwap() +{ + resetAllImageValues(); + return true + && imageAtomicCompSwap(image_1d, 0, 0, 2) == 1 + && load_image_1d() == 1 + && imageAtomicCompSwap(image_buffer, 0, 1, 2) == 1 + && load_image_buffer() == 2 + && imageAtomicCompSwap(image_1dArray, ivec2(0), 0, 2) == 1 + && load_image_1dArray() == 1 + && imageAtomicCompSwap(image_2d, ivec2(0), 1, 2) == 1 + && load_image_2d() == 2 + && imageAtomicCompSwap(image_2dRect, ivec2(0), 1, 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicCompSwap(image_2dMultiSample, ivec2(0), 1, 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicCompSwap(image_2dArray, ivec3(0), 0, 2) == 1 + && load_image_2dArray() == 1 + && imageAtomicCompSwap(image_3d, ivec3(0), 1, 2) == 1 + && load_image_3d() == 2 + && imageAtomicCompSwap(image_cube, ivec3(0), 1, 2) == 1 + && load_image_cube() == 2 + && imageAtomicCompSwap(image_cubeArray, ivec3(0), 1, 2) == 1 + && load_image_cubeArray() == 2 + && imageAtomicCompSwap(image_2dMultiSampleArray, ivec3(0), 1, 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 + ; +} + +// CHECK_GLSL: void main( +// CHECK_SPV: OpEntryPoint +void computeMain() +{ + outputBuffer.data[0] = true + && checkAllImageSize() + && checkAllImageLoad() + && checkAllImageStore() + && checkAllImageSamples() + && checkAllImageAtomicAdd() + && checkAllImageAtomicExchange() + && checkAllImageAtomicMin() + && checkAllImageAtomicMax() + && checkAllImageAtomicAnd() + && checkAllImageAtomicOr() + && checkAllImageAtomicXor() + && checkAllImageAtomicCompSwap() + ; + // BUF: 1 +} diff --git a/tests/glsl-intrinsic/image/iimageDimTiny.slang b/tests/glsl-intrinsic/image/iimageDimTiny.slang new file mode 100644 index 000000000..28dca1bc3 --- /dev/null +++ b/tests/glsl-intrinsic/image/iimageDimTiny.slang @@ -0,0 +1,34 @@ +//TEST:SIMPLE(filecheck=CHECK_GLSL): -allow-glsl -stage compute -entry computeMain -target glsl +//TEST:SIMPLE(filecheck=CHECK_SPV): -allow-glsl -stage compute -entry computeMain -target spirv -emit-spirv-directly +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl -emit-spirv-directly + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer +buffer MyBlockName2 +{ + uint data[1]; +} outputBuffer; + +layout(local_size_x = 1) in; + +//TEST_INPUT: set image_1d = RWTexture1D(format=R32_SINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=0,r32i) iimage1D image_1d; + +bool checkAllImageAtomicAdd() +{ + imageStore(image_1d, 0, ivec4(1)); + return true + && imageAtomicAdd(image_1d, 0, 0) == 1 + && imageLoad(image_1d, 0).x == 1 + ; +} + +// CHECK_GLSL: void main( +// CHECK_SPV: OpEntryPoint +void computeMain() +{ + outputBuffer.data[0] = true + && checkAllImageAtomicAdd() + ; + // BUF: 1 +} diff --git a/tests/glsl-intrinsic/image/imageAsParamWithMemoryQualifiers.slang b/tests/glsl-intrinsic/image/imageAsParamWithMemoryQualifiers.slang new file mode 100644 index 000000000..4766cb66f --- /dev/null +++ b/tests/glsl-intrinsic/image/imageAsParamWithMemoryQualifiers.slang @@ -0,0 +1,43 @@ +//TEST:SIMPLE(filecheck=CHECK_GLSL): -allow-glsl -stage compute -entry computeMain -target glsl +//TEST:SIMPLE(filecheck=CHECK_SPV): -allow-glsl -stage compute -entry computeMain -target spirv -emit-spirv-directly +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl -emit-spirv-directly + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer +buffer MyBlockName2 +{ + uint data[1]; +} outputBuffer; + +layout(local_size_x = 4) in; + +//TEST_INPUT: set someImage = RWTexture2D(format=R16G16B16A16_FLOAT, size=1, content=one, mipMaps = 1) +uniform layout(binding=0,rgba16f) writeonly readonly image2D someImage; + +//TEST_INPUT: set someImage2 = RWTexture2D(format=R16G16B16A16_FLOAT, size=1, content=one, mipMaps = 1) +uniform layout(binding=1,rgba16f) writeonly image2D someImage2; + +bool checkAllImageSizesParamSameQualifiers(writeonly readonly image2D val) +{ + return true + && imageSize(val) == ivec2(1) + ; +} +bool checkAllImageSizesParamMoreQualifiers(readonly writeonly image2D val) +{ + return true + && imageSize(val) == ivec2(1) + ; +} + +// CHECK_GLSL: void main( +// CHECK_SPV: OpEntryPoint +void computeMain() +{ + outputBuffer.data[0] = true + && checkAllImageSizesParamSameQualifiers(someImage) + && checkAllImageSizesParamMoreQualifiers(someImage2) + ; + // BUF: 1 + +}
\ No newline at end of file diff --git a/tests/glsl-intrinsic/image/imageAsParamWithMemoryQualifiersError.slang b/tests/glsl-intrinsic/image/imageAsParamWithMemoryQualifiersError.slang new file mode 100644 index 000000000..cab9be395 --- /dev/null +++ b/tests/glsl-intrinsic/image/imageAsParamWithMemoryQualifiersError.slang @@ -0,0 +1,27 @@ +//TEST:SIMPLE(filecheck=CHECK): -allow-glsl -stage compute -entry computeMain -target glsl +//TEST:SIMPLE(filecheck=CHECK): -allow-glsl -stage compute -entry computeMain -target spirv -emit-spirv-directly +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer +buffer MyBlockName2 +{ + uint data[1]; +} outputBuffer; + +layout(local_size_x = 4) in; + +//TEST_INPUT: set someImage = RWTexture2D(format=R16G16B16A16_FLOAT, size=1, content=one, mipMaps = 1) +uniform layout(binding=0,rgba16f) readonly image2D someImage; + +// CHECK: error 30048 +bool checkAllImageSizes(writeonly image2D val) +{ + return true + && imageSize(val) == ivec2(1) + ; +} + +void computeMain() +{ + outputBuffer.data[0] = true + && checkAllImageSizes(someImage); + ; +}
\ No newline at end of file diff --git a/tests/glsl-intrinsic/image/imageDim.slang b/tests/glsl-intrinsic/image/imageDim.slang new file mode 100644 index 000000000..4699bc2ac --- /dev/null +++ b/tests/glsl-intrinsic/image/imageDim.slang @@ -0,0 +1,303 @@ +//TEST:SIMPLE(filecheck=CHECK_GLSL): -allow-glsl -stage compute -entry computeMain -target glsl +//TEST:SIMPLE(filecheck=CHECK_SPV): -allow-glsl -stage compute -entry computeMain -target spirv -emit-spirv-directly +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl -emit-spirv-directly + +// shader_atomic_float2 is currently a very new extension; most hardware lacks +// this extension and will fail this test if attempting to use atomic_float2 +// operations. +// #define TEST_when_shader_atomic_float2_is_available + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer +buffer MyBlockName2 +{ + uint data[1]; +} outputBuffer; + +layout(local_size_x = 1) in; + +//TEST_INPUT: set image_1d = RWTexture1D(format=R32_FLOAT, size=4, content=one, mipMaps = 1) +uniform layout(binding=0,r32f) image1D image_1d; +//TEST_INPUT: set image_buffer = RWTextureBuffer(format=R32_FLOAT, stride=4, data=[1.0f 1.0f 1.0f 1.0f]) +uniform layout(binding=1,r32f) imageBuffer image_buffer; +//TEST_INPUT: set image_1dArray = RWTexture1D(format=R32_FLOAT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=2,r32f) image1DArray image_1dArray; +//TEST_INPUT: set image_2d = RWTexture2D(format=R32_FLOAT, size=4, content=one, mipMaps = 1) +uniform layout(binding=3,r32f) image2D image_2d; +//TEST_INPUT: set image_2dRect = RWTexture2D(format=R32_FLOAT, size=4, content=one, mipMaps = 1) +uniform layout(binding=4,r32f) image2DRect image_2dRect; +//TEST_INPUT: set image_2dMultiSample = RWTexture2D(format=R32_FLOAT, size=4, content=one, mipMaps = 1, sampleCount = two) +uniform layout(binding=5,r32f) image2DMS image_2dMultiSample; +//TEST_INPUT: set image_2dArray = RWTexture2D(format=R32_FLOAT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=6,r32f) image2DArray image_2dArray; +//TEST_INPUT: set image_3d = RWTexture3D(format=R32_FLOAT, size=4, content=one, mipMaps = 1) +uniform layout(binding=7,r32f) image3D image_3d; +//TEST_INPUT: set image_cube = RWTextureCube(format=R32_FLOAT, size=4, content=one, mipMaps = 1) +uniform layout(binding=8,r32f) imageCube image_cube; +//TEST_INPUT: set image_cubeArray = RWTextureCube(format=R32_FLOAT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=9,r32f) imageCubeArray image_cubeArray; +//TEST_INPUT: set image_2dMultiSampleArray = RWTexture2D(format=R32_FLOAT, size=4, content=one, mipMaps = 1, arrayLength=2, sampleCount = two) +uniform layout(binding=10,r32f) image2DMSArray image_2dMultiSampleArray; + +bool checkAllImageSize() +{ + return true + && imageSize(image_1d) == int(4) + && imageSize(image_buffer) == int(4) + && imageSize(image_1dArray) == ivec2(4, 2) + && imageSize(image_2d) == ivec2(4) + && imageSize(image_2dArray) == ivec3(4, 4, 2) + && imageSize(image_2dRect) == ivec2(4) + && imageSize(image_2dMultiSample) == ivec2(4) + && imageSize(image_3d) == ivec3(4) + && imageSize(image_cube) == ivec2(4) + && imageSize(image_cubeArray) == ivec3(4, 4, 2) + && imageSize(image_2dMultiSampleArray) == ivec3(4, 4, 2) + ; +} +bool checkAllImageLoad() +{ + return true + && imageLoad(image_1d, 0).x == 1 + && imageLoad(image_buffer, 0).x == 1 + && imageLoad(image_1dArray, ivec2(0)).x == 1 + && imageLoad(image_2d, ivec2(0)).x == 1 + && imageLoad(image_2dRect, ivec2(0)).x == 1 + && imageLoad(image_2dMultiSample, ivec2(0), 1).x == 1 + && imageLoad(image_2dArray, ivec3(0)).x == 1 + && imageLoad(image_3d, ivec3(0)).x == 1 + && imageLoad(image_cube, ivec3(0)).x == 1 + && imageLoad(image_cubeArray, ivec3(0)).x == 1 + && imageLoad(image_cubeArray, ivec3(0)).x == 1 + && imageLoad(image_2dMultiSampleArray, ivec3(0), 1).x == 1 + ; +} +bool resetAllImageValues() +{ + imageStore(image_1d, 0, vec4(1)); + imageStore(image_buffer, 0, vec4(1)); + imageStore(image_1dArray, ivec2(0), vec4(1)); + imageStore(image_2d, ivec2(0), vec4(1)); + imageStore(image_2dRect, ivec2(0), vec4(1)); + imageStore(image_2dMultiSample, ivec2(0), 1, vec4(1)); + imageStore(image_2dArray, ivec3(0), vec4(1)); + imageStore(image_3d, ivec3(0), vec4(1)); + imageStore(image_cube, ivec3(0), vec4(1)); + imageStore(image_cubeArray, ivec3(0), vec4(1)); + imageStore(image_2dMultiSampleArray, ivec3(0), 1, vec4(1)); + return true; +} +float load_image_1d() +{ + return imageLoad(image_1d, 0).x; +} +float load_image_buffer() +{ + return imageLoad(image_buffer, 0).x; +} +float load_image_1dArray() +{ + return imageLoad(image_1dArray, ivec2(0)).x; +} +float load_image_2d() +{ + return imageLoad(image_2d, ivec2(0)).x; +} +float load_image_2dRect() +{ + return imageLoad(image_2dRect, ivec2(0)).x; +} +float load_image_2dMultiSample() +{ + return imageLoad(image_2dMultiSample, ivec2(0), 1).x; +} +float load_image_2dArray() +{ + return imageLoad(image_2dArray, ivec3(0)).x; +} +float load_image_3d() +{ + return imageLoad(image_3d, ivec3(0)).x; +} +float load_image_cube() +{ + return imageLoad(image_cube, ivec3(0)).x; +} +float load_image_cubeArray() +{ + return imageLoad(image_cubeArray, ivec3(0)).x; +} +float load_image_2dMultiSampleArray() +{ + return imageLoad(image_2dMultiSampleArray, ivec3(0), 1).x; +} +// requires ImageLoad test to pass +bool checkAllImageStore() +{ + bool loadCheck = true; + imageStore(image_1d, 0, vec4(0)); + loadCheck = loadCheck && load_image_1d() == 0; + imageStore(image_buffer, 0, vec4(0)); + loadCheck = loadCheck && load_image_buffer() == 0; + imageStore(image_1dArray, ivec2(0), vec4(0)); + loadCheck = loadCheck && load_image_1dArray() == 0; + imageStore(image_2d, ivec2(0), vec4(0)); + loadCheck = loadCheck && load_image_2d() == 0; + imageStore(image_2dRect, ivec2(0), vec4(0)); + loadCheck = loadCheck && load_image_2dRect() == 0; + imageStore(image_2dMultiSample, ivec2(0), 1, vec4(0)); + loadCheck = loadCheck && load_image_2dMultiSample() == 0; + imageStore(image_2dArray, ivec3(0), vec4(0)); + loadCheck = loadCheck && load_image_2dArray() == 0; + imageStore(image_3d, ivec3(0), vec4(0)); + loadCheck = loadCheck && load_image_3d() == 0; + imageStore(image_cube, ivec3(0), vec4(0)); + loadCheck = loadCheck && load_image_cube() == 0; + imageStore(image_cubeArray, ivec3(0), vec4(0)); + loadCheck = loadCheck && load_image_cubeArray() == 0; + imageStore(image_2dMultiSampleArray, ivec3(0), 1, vec4(0)); + loadCheck = loadCheck && load_image_2dMultiSampleArray() == 0; + resetAllImageValues(); + return loadCheck; +} +bool checkAllImageSamples() +{ + resetAllImageValues(); + return true + && imageSamples(image_2dMultiSample) == 2 + && imageSamples(image_2dMultiSampleArray) == 2 + ; +} +bool checkAllImageAtomicAdd() +{ + resetAllImageValues(); + return true + && imageAtomicAdd(image_1d, 0, 0.0f) == 1 + && load_image_1d() == 1 + && imageAtomicAdd(image_buffer, 0, 2.0f) == 1 + && load_image_buffer() == 3 + && imageAtomicAdd(image_1dArray, ivec2(0), 0.0f) == 1 + && load_image_1dArray() == 1 + && imageAtomicAdd(image_2d, ivec2(0), 2.0f) == 1 + && load_image_2d() == 3 + && imageAtomicAdd(image_2dRect, ivec2(0), 2.0f) == 1 + && load_image_2dRect() == 3 + && imageAtomicAdd(image_2dMultiSample, ivec2(0), 1, 2.0f) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicAdd(image_2dArray, ivec3(0), 0.0f) == 1 + && load_image_2dArray() == 1 + && imageAtomicAdd(image_3d, ivec3(0), 2.0f) == 1 + && load_image_3d() == 3 + && imageAtomicAdd(image_cube, ivec3(0), 2.0f) == 1 + && load_image_cube() == 3 + && imageAtomicAdd(image_cubeArray, ivec3(0), 2.0f) == 1 + && load_image_cubeArray() == 3 + && imageAtomicAdd(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 + ; +} +bool checkAllImageAtomicExchange() +{ + resetAllImageValues(); + return true + && imageAtomicExchange(image_1d, 0, 0.0f) == 1 + && load_image_1d() == 0 + && imageAtomicExchange(image_buffer, 0, 2.0f) == 1 + && load_image_buffer() == 2 + && imageAtomicExchange(image_1dArray, ivec2(0), 0.0f) == 1 + && load_image_1dArray() == 0 + && imageAtomicExchange(image_2d, ivec2(0), 2.0f) == 1 + && load_image_2d() == 2 + && imageAtomicExchange(image_2dRect, ivec2(0), 2.0f) == 1 + && load_image_2dRect() == 2 + && imageAtomicExchange(image_2dMultiSample, ivec2(0), 1, 2.0f) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicExchange(image_2dArray, ivec3(0), 0.0f) == 1 + && load_image_2dArray() == 0 + && imageAtomicExchange(image_3d, ivec3(0), 2.0f) == 1 + && load_image_3d() == 2 + && imageAtomicExchange(image_cube, ivec3(0), 2.0f) == 1 + && load_image_cube() == 2 + && imageAtomicExchange(image_cubeArray, ivec3(0), 2.0f) == 1 + && load_image_cubeArray() == 2 + && imageAtomicExchange(image_2dMultiSampleArray, ivec3(0), 1, 2.0f) == 1 + && load_image_2dMultiSampleArray() == 2 + ; +} +#ifdef TEST_when_shader_atomic_float2_is_available +bool checkAllImageAtomicMin() +{ + resetAllImageValues(); + return true + && imageAtomicMin(image_1d, 0, 0.0f) == 1 + && load_image_1d() == 0 + && imageAtomicMin(image_buffer, 0, 2.0f) == 1 + && load_image_buffer() == 1 + && imageAtomicMin(image_1dArray, ivec2(0), 0.0f) == 1 + && load_image_1dArray() == 0 + && imageAtomicMin(image_2d, ivec2(0), 2.0f) == 1 + && load_image_2d() == 1 + && imageAtomicMin(image_2dRect, ivec2(0), 2.0f) == 1 + && load_image_2dRect() == 1 + && imageAtomicMin(image_2dMultiSample, ivec2(0), 1, 2.0f) == 1 + && load_image_2dMultiSample() == 1 + && imageAtomicMin(image_2dArray, ivec3(0), 0.0f) == 1 + && load_image_2dArray() == 0 + && imageAtomicMin(image_3d, ivec3(0), 2.0f) == 1 + && load_image_3d() == 1 + && imageAtomicMin(image_cube, ivec3(0), 2.0f) == 1 + && load_image_cube() == 1 + && imageAtomicMin(image_cubeArray, ivec3(0), 2.0f) == 1 + && load_image_cubeArray() == 1 + && imageAtomicMin(image_2dMultiSampleArray, ivec3(0), 1, 2.0f) == 1 + && load_image_2dMultiSampleArray() == 1 + ; +} +bool checkAllImageAtomicMax() +{ + resetAllImageValues(); + return true + && imageAtomicMax(image_1d, 0, 0) == 1 + && load_image_1d() == 1 + && imageAtomicMax(image_buffer, 0, 2) == 1 + && load_image_buffer() == 2 + && imageAtomicMax(image_1dArray, ivec2(0), 0.0f) == 1 + && load_image_1dArray() == 1 + && imageAtomicMax(image_2d, ivec2(0), 2.0f) == 1 + && load_image_2d() == 2 + && imageAtomicMax(image_2dRect, ivec2(0), 2.0f) == 1 + && load_image_2dRect() == 2 + && imageAtomicMax(image_2dMultiSample, ivec2(0), 1, 2.0f) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicMax(image_2dArray, ivec3(0), 0.0f) == 1 + && load_image_2dArray() == 1 + && imageAtomicMax(image_3d, ivec3(0), 2.0f) == 1 + && load_image_3d() == 2 + && imageAtomicMax(image_cube, ivec3(0), 2.0f) == 1 + && load_image_cube() == 2 + && imageAtomicMax(image_cubeArray, ivec3(0), 2.0f) == 1 + && load_image_cubeArray() == 2 + && imageAtomicMax(image_2dMultiSampleArray, ivec3(0), 1, 2.0f) == 1 + && load_image_2dMultiSampleArray() == 2 + ; +} +#endif // #ifdef TEST_when_shader_atomic_float2_is_available + +// CHECK_GLSL: void main( +// CHECK_SPV: OpEntryPoint +void computeMain() +{ + outputBuffer.data[0] = true + && checkAllImageSize() + && checkAllImageLoad() + && checkAllImageStore() + && checkAllImageSamples() + && checkAllImageAtomicAdd() + && checkAllImageAtomicExchange() +#ifdef TEST_when_shader_atomic_float2_is_available + && checkAllImageAtomicMin() + && checkAllImageAtomicMax() +#endif // #ifdef TEST_when_shader_atomic_float2_is_available + ; + // BUF: 1 +}
\ No newline at end of file diff --git a/tests/glsl-intrinsic/image/nonImageAsParamWithMemoryQualifierError.slang b/tests/glsl-intrinsic/image/nonImageAsParamWithMemoryQualifierError.slang new file mode 100644 index 000000000..1248020d4 --- /dev/null +++ b/tests/glsl-intrinsic/image/nonImageAsParamWithMemoryQualifierError.slang @@ -0,0 +1,26 @@ +//TEST:SIMPLE(filecheck=CHECK): -allow-glsl -stage compute -entry computeMain -target glsl +//TEST:SIMPLE(filecheck=CHECK): -allow-glsl -stage compute -entry computeMain -target spirv -emit-spirv-directly +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer + +// restrict modifier is allowed to be dropped as a parameter +buffer MyBlockName2 +{ + restrict uint data[1]; +} outputBuffer; + +layout(local_size_x = 4) in; + +// CHECK: error 31206 +bool checkAllImageSizes(writeonly uint val) +{ + return true + && val == 0 + ; +} + +void computeMain() +{ + outputBuffer.data[0] = true + && checkAllImageSizes(outputBuffer.data[0]) + ; +}
\ No newline at end of file diff --git a/tests/glsl-intrinsic/image/u64imageDim.slang b/tests/glsl-intrinsic/image/u64imageDim.slang new file mode 100644 index 000000000..ebcfd0796 --- /dev/null +++ b/tests/glsl-intrinsic/image/u64imageDim.slang @@ -0,0 +1,476 @@ +//TEST:SIMPLE(filecheck=CHECK_GLSL): -allow-glsl -stage compute -entry computeMain -target glsl +//TEST:SIMPLE(filecheck=CHECK_SPV): -allow-glsl -stage compute -entry computeMain -target spirv -emit-spirv-directly +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl -emit-spirv-directly + +// As per vulkan specification: https://registry.khronos.org/vulkan/specs/1.3/html/chap34.html#formats-definition +// i64/u64 images do not require sampled image support; support is currently unlikley on hardware +//#define test_when_hardware_supports_i64_and_u64_sampled_textures +// i64/u64 images do not require texel buffers support; support is currently unlikley on hardware +//#define TEST_when_hardware_supports_i64_and_u64_buffers + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer +buffer MyBlockName2 +{ + uint data[1]; +} outputBuffer; + +layout(local_size_x = 1) in; + +//TEST_INPUT: set image_1d = RWTexture1D(format=R64_UINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=0,r64ui) u64image1D image_1d; +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers +//COM:TEST_INPUT: set image_buffer = RWTextureBuffer(format=R64_UINT, stride=8, data=[0 1 0 1 0 1 0 1]) +uniform layout(binding=1,r64ui) u64imageBuffer image_buffer; +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers +//TEST_INPUT: set image_1dArray = RWTexture1D(format=R64_UINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=2,r64ui) u64image1DArray image_1dArray; +//TEST_INPUT: set image_2d = RWTexture2D(format=R64_UINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=3,r64ui) u64image2D image_2d; +//TEST_INPUT: set image_2dRect = RWTexture2D(format=R64_UINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=4,r64ui) u64image2DRect image_2dRect; +//TEST_INPUT: set image_2dArray = RWTexture2D(format=R64_UINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=6,r64ui) u64image2DArray image_2dArray; +//TEST_INPUT: set image_3d = RWTexture3D(format=R64_UINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=7,r64ui) u64image3D image_3d; +//TEST_INPUT: set image_cube = RWTextureCube(format=R64_UINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=8,r64ui) u64imageCube image_cube; +//TEST_INPUT: set image_cubeArray = RWTextureCube(format=R64_UINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=9,r64ui) u64imageCubeArray image_cubeArray; +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures +//COM:TEST_INPUT: set image_2dMultiSample = RWTexture2D(format=R64_UINT, size=4, content=one, mipMaps = 1, sampleCount = two) +uniform layout(binding=5,r64ui) u64image2DMS image_2dMultiSample; +//COM:TEST_INPUT: set image_2dMultiSampleArray = RWTexture2D(format=R64_UINT, size=4, content=one, mipMaps = 1, arrayLength=2, sampleCount = two) +uniform layout(binding=10,r64ui) u64image2DMSArray image_2dMultiSampleArray; +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + +bool checkAllImageSize() +{ + return true + && imageSize(image_1d) == int(4) +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageSize(image_buffer) == int(4) +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageSize(image_1dArray) == ivec2(4, 2) + && imageSize(image_2d) == ivec2(4) + && imageSize(image_2dArray) == ivec3(4, 4, 2) + && imageSize(image_2dRect) == ivec2(4) + && imageSize(image_3d) == ivec3(4) + && imageSize(image_cube) == ivec2(4) + && imageSize(image_cubeArray) == ivec3(4, 4, 2) +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageSize(image_2dMultiSample) == ivec2(4) + && imageSize(image_2dMultiSampleArray) == ivec3(4, 4, 2) +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageLoad() +{ + return true + && imageLoad(image_1d, 0).x == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageLoad(image_buffer, 0).x == 1 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageLoad(image_1dArray, ivec2(0)).x == 1 + && imageLoad(image_2d, ivec2(0)).x == 1 + && imageLoad(image_2dRect, ivec2(0)).x == 1 + && imageLoad(image_2dArray, ivec3(0)).x == 1 + && imageLoad(image_3d, ivec3(0)).x == 1 + && imageLoad(image_cube, ivec3(0)).x == 1 + && imageLoad(image_cubeArray, ivec3(0)).x == 1 + && imageLoad(image_cubeArray, ivec3(0)).x == 1 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageLoad(image_2dMultiSample, ivec2(0), 1).x == 1 + && imageLoad(image_2dMultiSampleArray, ivec3(0), 1).x == 1 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool resetAllImageValues() +{ + imageStore(image_1d, 0,u64vec4(1)); +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + imageStore(image_buffer, 0,u64vec4(1)); +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + imageStore(image_1dArray, ivec2(0),u64vec4(1)); + imageStore(image_2d, ivec2(0),u64vec4(1)); + imageStore(image_2dRect, ivec2(0),u64vec4(1)); + imageStore(image_2dArray, ivec3(0),u64vec4(1)); + imageStore(image_3d, ivec3(0),u64vec4(1)); + imageStore(image_cube, ivec3(0),u64vec4(1)); + imageStore(image_cubeArray, ivec3(0),u64vec4(1)); +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + imageStore(image_2dMultiSample, ivec2(0), 1, u64vec4(1)); + imageStore(image_2dMultiSampleArray, ivec3(0), 1,u64vec4(1)); +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + return true; +} +uint64_t load_image_1d() +{ + return imageLoad(image_1d, 0).x; +} +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers +uint64_t load_image_buffer() +{ + return imageLoad(image_buffer, 0).x; +} +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers +uint64_t load_image_1dArray() +{ + return imageLoad(image_1dArray, ivec2(0)).x; +} +uint64_t load_image_2d() +{ + return imageLoad(image_2d, ivec2(0)).x; +} +uint64_t load_image_2dRect() +{ + return imageLoad(image_2dRect, ivec2(0)).x; +} +uint64_t load_image_2dArray() +{ + return imageLoad(image_2dArray, ivec3(0)).x; +} +uint64_t load_image_3d() +{ + return imageLoad(image_3d, ivec3(0)).x; +} +uint64_t load_image_cube() +{ + return imageLoad(image_cube, ivec3(0)).x; +} +uint64_t load_image_cubeArray() +{ + return imageLoad(image_cubeArray, ivec3(0)).x; +} +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures +uint64_t load_image_2dMultiSample() +{ + return imageLoad(image_2dMultiSample, ivec2(0), 1).x; +} +uint64_t load_image_2dMultiSampleArray() +{ + return imageLoad(image_2dMultiSampleArray, ivec3(0), 1).x; +} +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + +// requires ImageLoad test to pass +bool checkAllImageStore() +{ + bool loadCheck = true; + + imageStore(image_1d, 0,u64vec4(0)); + loadCheck = loadCheck && load_image_1d() == 0; +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + imageStore(image_buffer, 0,u64vec4(0)); + loadCheck = loadCheck && load_image_buffer() == 0; +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + imageStore(image_1dArray, ivec2(0),u64vec4(0)); + loadCheck = loadCheck && load_image_1dArray() == 0; + imageStore(image_2d, ivec2(0),u64vec4(0)); + loadCheck = loadCheck && load_image_2d() == 0; + imageStore(image_2dRect, ivec2(0),u64vec4(0)); + loadCheck = loadCheck && load_image_2dRect() == 0; + imageStore(image_2dArray, ivec3(0),u64vec4(0)); + loadCheck = loadCheck && load_image_2dArray() == 0; + imageStore(image_3d, ivec3(0),u64vec4(0)); + loadCheck = loadCheck && load_image_3d() == 0; + imageStore(image_cube, ivec3(0),u64vec4(0)); + loadCheck = loadCheck && load_image_cube() == 0; + imageStore(image_cubeArray, ivec3(0),u64vec4(0)); + loadCheck = loadCheck && load_image_cubeArray() == 0; +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + imageStore(image_2dMultiSample, ivec2(0), 1, u64vec4(0)); + loadCheck = loadCheck && load_image_2dMultiSample() == 0; + imageStore(image_2dMultiSampleArray, ivec3(0), 1,u64vec4(0)); + loadCheck = loadCheck && load_image_2dMultiSampleArray() == 0; +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + resetAllImageValues(); + return loadCheck; +} +bool checkAllImageSamples() +{ + resetAllImageValues(); + return true +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageSamples(image_2dMultiSample) == 2 + && imageSamples(image_2dMultiSampleArray) == 2 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicAdd() +{ + resetAllImageValues(); + return true + && imageAtomicAdd(image_1d, 0, 0) == 1 + && load_image_1d() == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicAdd(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicAdd(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 1 + && imageAtomicAdd(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicAdd(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicAdd(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 1 + && imageAtomicAdd(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicAdd(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicAdd(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicAdd(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicAdd(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicExchange() +{ + resetAllImageValues(); + return true + && imageAtomicExchange(image_1d, 0, 0) == 1 + && load_image_1d() == 0 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicExchange(image_buffer, 0, 2) == 1 + && load_image_buffer() == 2 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicExchange(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 0 + && imageAtomicExchange(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 2 + && imageAtomicExchange(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicExchange(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 0 + && imageAtomicExchange(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 2 + && imageAtomicExchange(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 2 + && imageAtomicExchange(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 2 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicExchange(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicExchange(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicMin() +{ + resetAllImageValues(); + return true + && imageAtomicMin(image_1d, 0, 0) == 1 + && load_image_1d() == 0 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicMin(image_buffer, 0, 2) == 1 + && load_image_buffer() == 1 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicMin(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 0 + && imageAtomicMin(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 1 + && imageAtomicMin(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 1 + && imageAtomicMin(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 0 + && imageAtomicMin(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 1 + && imageAtomicMin(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 1 + && imageAtomicMin(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 1 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicMin(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 1 + && imageAtomicMin(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 1 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicMax() +{ + resetAllImageValues(); + return true + && imageAtomicMax(image_1d, 0, 0) == 1 + && load_image_1d() == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicMax(image_buffer, 0, 2) == 1 + && load_image_buffer() == 2 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicMax(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 1 + && imageAtomicMax(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 2 + && imageAtomicMax(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicMax(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 1 + && imageAtomicMax(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 2 + && imageAtomicMax(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 2 + && imageAtomicMax(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 2 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicMax(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicMax(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicAnd() +{ + resetAllImageValues(); + return true + && imageAtomicAnd(image_1d, 0, 1) == 1 + && load_image_1d() == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicAnd(image_buffer, 0, 2) == 1 + && load_image_buffer() == 0 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicAnd(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 1 + && imageAtomicAnd(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 0 + && imageAtomicAnd(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 0 + && imageAtomicAnd(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 1 + && imageAtomicAnd(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 0 + && imageAtomicAnd(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 0 + && imageAtomicAnd(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 0 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicAnd(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 0 + && imageAtomicAnd(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 0 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicOr() +{ + resetAllImageValues(); + return true + && imageAtomicOr(image_1d, 0, 1) == 1 + && load_image_1d() == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicOr(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicOr(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 1 + && imageAtomicOr(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicOr(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicOr(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 1 + && imageAtomicOr(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicOr(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicOr(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicOr(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicOr(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicXor() +{ + resetAllImageValues(); + return true + && imageAtomicXor(image_1d, 0, 1) == 1 + && load_image_1d() == 0 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicXor(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicXor(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 0 + && imageAtomicXor(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicXor(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicXor(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 0 + && imageAtomicXor(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicXor(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicXor(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicXor(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicXor(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} +bool checkAllImageAtomicCompSwap() +{ + resetAllImageValues(); + return true + && imageAtomicCompSwap(image_1d, 0, 0, 2) == 1 + && load_image_1d() == 1 +#ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicCompSwap(image_buffer, 0, 1, 2) == 1 + && load_image_buffer() == 2 +#endif // #ifdef TEST_when_hardware_supports_i64_and_u64_buffers + && imageAtomicCompSwap(image_1dArray, ivec2(0), 0, 2) == 1 + && load_image_1dArray() == 1 + && imageAtomicCompSwap(image_2d, ivec2(0), 1, 2) == 1 + && load_image_2d() == 2 + && imageAtomicCompSwap(image_2dRect, ivec2(0), 1, 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicCompSwap(image_2dArray, ivec3(0), 0, 2) == 1 + && load_image_2dArray() == 1 + && imageAtomicCompSwap(image_3d, ivec3(0), 1, 2) == 1 + && load_image_3d() == 2 + && imageAtomicCompSwap(image_cube, ivec3(0), 1, 2) == 1 + && load_image_cube() == 2 + && imageAtomicCompSwap(image_cubeArray, ivec3(0), 1, 2) == 1 + && load_image_cubeArray() == 2 +#ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + && imageAtomicCompSwap(image_2dMultiSample, ivec2(0), 1, 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicCompSwap(image_2dMultiSampleArray, ivec3(0), 1, 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 +#endif // #ifdef test_when_hardware_supports_i64_and_u64_sampled_textures + ; +} + +// CHECK_GLSL: void main( +// CHECK_SPV: OpEntryPoint +void computeMain() +{ + outputBuffer.data[0] = true + && checkAllImageSize() + && checkAllImageLoad() + && checkAllImageStore() + && checkAllImageSamples() + && checkAllImageAtomicAdd() + && checkAllImageAtomicExchange() + && checkAllImageAtomicMin() + && checkAllImageAtomicMax() + && checkAllImageAtomicAnd() + && checkAllImageAtomicOr() + && checkAllImageAtomicXor() + && checkAllImageAtomicCompSwap() + ; + // BUF: 1 +}
\ No newline at end of file diff --git a/tests/glsl-intrinsic/image/uimageDim.slang b/tests/glsl-intrinsic/image/uimageDim.slang new file mode 100644 index 000000000..538855b7d --- /dev/null +++ b/tests/glsl-intrinsic/image/uimageDim.slang @@ -0,0 +1,410 @@ +//TEST:SIMPLE(filecheck=CHECK_GLSL): -allow-glsl -stage compute -entry computeMain -target glsl +//TEST:SIMPLE(filecheck=CHECK_SPV): -allow-glsl -stage compute -entry computeMain -target spirv -emit-spirv-directly +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl -emit-spirv-directly + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer +buffer MyBlockName2 +{ + uint data[1]; +} outputBuffer; + +layout(local_size_x = 1) in; + +//TEST_INPUT: set image_1d = RWTexture1D(format=R32_UINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=0,r32ui) uimage1D image_1d; +//TEST_INPUT: set image_buffer = RWTextureBuffer(format=R32_UINT, stride=8, data=[1 1 1 1]) +uniform layout(binding=1,r32ui) uimageBuffer image_buffer; +//TEST_INPUT: set image_1dArray = RWTexture1D(format=R32_UINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=2,r32ui) uimage1DArray image_1dArray; +//TEST_INPUT: set image_2d = RWTexture2D(format=R32_UINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=3,r32ui) uimage2D image_2d; +//TEST_INPUT: set image_2dRect = RWTexture2D(format=R32_UINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=4,r32ui) uimage2DRect image_2dRect; +//TEST_INPUT: set image_2dMultiSample = RWTexture2D(format=R32_UINT, size=4, content=one, mipMaps = 1, sampleCount = two) +uniform layout(binding=5,r32ui) uimage2DMS image_2dMultiSample; +//TEST_INPUT: set image_2dArray = RWTexture2D(format=R32_UINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=6,r32ui) uimage2DArray image_2dArray; +//TEST_INPUT: set image_3d = RWTexture3D(format=R32_UINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=7,r32ui) uimage3D image_3d; +//TEST_INPUT: set image_cube = RWTextureCube(format=R32_UINT, size=4, content=one, mipMaps = 1) +uniform layout(binding=8,r32ui) uimageCube image_cube; +//TEST_INPUT: set image_cubeArray = RWTextureCube(format=R32_UINT, size=4, content=one, mipMaps = 1, arrayLength=2) +uniform layout(binding=9,r32ui) uimageCubeArray image_cubeArray; +//TEST_INPUT: set image_2dMultiSampleArray = RWTexture2D(format=R32_UINT, size=4, content=one, mipMaps = 1, arrayLength=2, sampleCount = two) +uniform layout(binding=10,r32ui) uimage2DMSArray image_2dMultiSampleArray; + +bool checkAllImageSize() +{ + return true + && imageSize(image_1d) == int(4) + && imageSize(image_buffer) == int(4) + && imageSize(image_1dArray) == ivec2(4, 2) + && imageSize(image_2d) == ivec2(4) + && imageSize(image_2dArray) == ivec3(4, 4, 2) + && imageSize(image_2dRect) == ivec2(4) + && imageSize(image_2dMultiSample) == ivec2(4) + && imageSize(image_3d) == ivec3(4) + && imageSize(image_cube) == ivec2(4) + && imageSize(image_cubeArray) == ivec3(4, 4, 2) + && imageSize(image_2dMultiSampleArray) == ivec3(4, 4, 2) + ; +} +bool checkAllImageLoad() +{ + return true + && imageLoad(image_1d, 0).x == 1 + && imageLoad(image_buffer, 0).x == 1 + && imageLoad(image_1dArray, ivec2(0)).x == 1 + && imageLoad(image_2d, ivec2(0)).x == 1 + && imageLoad(image_2dRect, ivec2(0)).x == 1 + && imageLoad(image_2dMultiSample, ivec2(0), 1).x == 1 + && imageLoad(image_2dArray, ivec3(0)).x == 1 + && imageLoad(image_3d, ivec3(0)).x == 1 + && imageLoad(image_cube, ivec3(0)).x == 1 + && imageLoad(image_cubeArray, ivec3(0)).x == 1 + && imageLoad(image_cubeArray, ivec3(0)).x == 1 + && imageLoad(image_2dMultiSampleArray, ivec3(0), 1).x == 1 + ; +} +bool resetAllImageValues() +{ + imageStore(image_1d, 0, uvec4(1)); + imageStore(image_buffer, 0, uvec4(1)); + imageStore(image_1dArray, ivec2(0), uvec4(1)); + imageStore(image_2d, ivec2(0), uvec4(1)); + imageStore(image_2dRect, ivec2(0), uvec4(1)); + imageStore(image_2dMultiSample, ivec2(0), 1, uvec4(1)); + imageStore(image_2dArray, ivec3(0), uvec4(1)); + imageStore(image_3d, ivec3(0), uvec4(1)); + imageStore(image_cube, ivec3(0), uvec4(1)); + imageStore(image_cubeArray, ivec3(0), uvec4(1)); + imageStore(image_2dMultiSampleArray, ivec3(0), 1, uvec4(1)); + return true; +} +uint load_image_1d() +{ + return imageLoad(image_1d, 0).x; +} +uint load_image_buffer() +{ + return imageLoad(image_buffer, 0).x; +} +uint load_image_1dArray() +{ + return imageLoad(image_1dArray, ivec2(0)).x; +} +uint load_image_2d() +{ + return imageLoad(image_2d, ivec2(0)).x; +} +uint load_image_2dRect() +{ + return imageLoad(image_2dRect, ivec2(0)).x; +} +uint load_image_2dMultiSample() +{ + return imageLoad(image_2dMultiSample, ivec2(0), 1).x; +} +uint load_image_2dArray() +{ + return imageLoad(image_2dArray, ivec3(0)).x; +} +uint load_image_3d() +{ + return imageLoad(image_3d, ivec3(0)).x; +} +uint load_image_cube() +{ + return imageLoad(image_cube, ivec3(0)).x; +} +uint load_image_cubeArray() +{ + return imageLoad(image_cubeArray, ivec3(0)).x; +} +uint load_image_2dMultiSampleArray() +{ + return imageLoad(image_2dMultiSampleArray, ivec3(0), 1).x; +} +// requires ImageLoad test to pass +bool checkAllImageStore() +{ + bool loadCheck = true; + imageStore(image_1d, 0, uvec4(0)); + loadCheck = loadCheck && load_image_1d() == 0; + imageStore(image_buffer, 0, uvec4(0)); + loadCheck = loadCheck && load_image_buffer() == 0; + imageStore(image_1dArray, ivec2(0), uvec4(0)); + loadCheck = loadCheck && load_image_1dArray() == 0; + imageStore(image_2d, ivec2(0), uvec4(0)); + loadCheck = loadCheck && load_image_2d() == 0; + imageStore(image_2dRect, ivec2(0), uvec4(0)); + loadCheck = loadCheck && load_image_2dRect() == 0; + imageStore(image_2dMultiSample, ivec2(0), 1, uvec4(0)); + loadCheck = loadCheck && load_image_2dMultiSample() == 0; + imageStore(image_2dArray, ivec3(0), uvec4(0)); + loadCheck = loadCheck && load_image_2dArray() == 0; + imageStore(image_3d, ivec3(0), uvec4(0)); + loadCheck = loadCheck && load_image_3d() == 0; + imageStore(image_cube, ivec3(0), uvec4(0)); + loadCheck = loadCheck && load_image_cube() == 0; + imageStore(image_cubeArray, ivec3(0), uvec4(0)); + loadCheck = loadCheck && load_image_cubeArray() == 0; + imageStore(image_2dMultiSampleArray, ivec3(0), 1, uvec4(0)); + loadCheck = loadCheck && load_image_2dMultiSampleArray() == 0; + resetAllImageValues(); + return loadCheck; +} +bool checkAllImageSamples() +{ + resetAllImageValues(); + return true + && imageSamples(image_2dMultiSample) == 2 + && imageSamples(image_2dMultiSampleArray) == 2 + ; +} +bool checkAllImageAtomicAdd() +{ + resetAllImageValues(); + return true + && imageAtomicAdd(image_1d, 0, 0) == 1 + && load_image_1d() == 1 + && imageAtomicAdd(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 + && imageAtomicAdd(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 1 + && imageAtomicAdd(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicAdd(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicAdd(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicAdd(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 1 + && imageAtomicAdd(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicAdd(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicAdd(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 + && imageAtomicAdd(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 + ; +} +bool checkAllImageAtomicExchange() +{ + resetAllImageValues(); + return true + && imageAtomicExchange(image_1d, 0, 0) == 1 + && load_image_1d() == 0 + && imageAtomicExchange(image_buffer, 0, 2) == 1 + && load_image_buffer() == 2 + && imageAtomicExchange(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 0 + && imageAtomicExchange(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 2 + && imageAtomicExchange(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicExchange(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicExchange(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 0 + && imageAtomicExchange(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 2 + && imageAtomicExchange(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 2 + && imageAtomicExchange(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 2 + && imageAtomicExchange(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 + ; +} +bool checkAllImageAtomicMin() +{ + resetAllImageValues(); + return true + && imageAtomicMin(image_1d, 0, 0) == 1 + && load_image_1d() == 0 + && imageAtomicMin(image_buffer, 0, 2) == 1 + && load_image_buffer() == 1 + && imageAtomicMin(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 0 + && imageAtomicMin(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 1 + && imageAtomicMin(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 1 + && imageAtomicMin(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 1 + && imageAtomicMin(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 0 + && imageAtomicMin(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 1 + && imageAtomicMin(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 1 + && imageAtomicMin(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 1 + && imageAtomicMin(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 1 + ; +} +bool checkAllImageAtomicMax() +{ + resetAllImageValues(); + return true + && imageAtomicMax(image_1d, 0, 0) == 1 + && load_image_1d() == 1 + && imageAtomicMax(image_buffer, 0, 2) == 1 + && load_image_buffer() == 2 + && imageAtomicMax(image_1dArray, ivec2(0), 0) == 1 + && load_image_1dArray() == 1 + && imageAtomicMax(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 2 + && imageAtomicMax(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicMax(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicMax(image_2dArray, ivec3(0), 0) == 1 + && load_image_2dArray() == 1 + && imageAtomicMax(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 2 + && imageAtomicMax(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 2 + && imageAtomicMax(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 2 + && imageAtomicMax(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 + ; +} +bool checkAllImageAtomicAnd() +{ + resetAllImageValues(); + return true + && imageAtomicAnd(image_1d, 0, 1) == 1 + && load_image_1d() == 1 + && imageAtomicAnd(image_buffer, 0, 2) == 1 + && load_image_buffer() == 0 + && imageAtomicAnd(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 1 + && imageAtomicAnd(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 0 + && imageAtomicAnd(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 0 + && imageAtomicAnd(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 0 + && imageAtomicAnd(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 1 + && imageAtomicAnd(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 0 + && imageAtomicAnd(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 0 + && imageAtomicAnd(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 0 + && imageAtomicAnd(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 0 + ; +} +bool checkAllImageAtomicOr() +{ + resetAllImageValues(); + return true + && imageAtomicOr(image_1d, 0, 1) == 1 + && load_image_1d() == 1 + && imageAtomicOr(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 + && imageAtomicOr(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 1 + && imageAtomicOr(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicOr(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicOr(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicOr(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 1 + && imageAtomicOr(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicOr(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicOr(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 + && imageAtomicOr(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 + ; +} +bool checkAllImageAtomicXor() +{ + resetAllImageValues(); + return true + && imageAtomicXor(image_1d, 0, 1) == 1 + && load_image_1d() == 0 + && imageAtomicXor(image_buffer, 0, 2) == 1 + && load_image_buffer() == 3 + && imageAtomicXor(image_1dArray, ivec2(0), 1) == 1 + && load_image_1dArray() == 0 + && imageAtomicXor(image_2d, ivec2(0), 2) == 1 + && load_image_2d() == 3 + && imageAtomicXor(image_2dRect, ivec2(0), 2) == 1 + && load_image_2dRect() == 3 + && imageAtomicXor(image_2dMultiSample, ivec2(0), 1, 2) == 1 + && load_image_2dMultiSample() == 3 + && imageAtomicXor(image_2dArray, ivec3(0), 1) == 1 + && load_image_2dArray() == 0 + && imageAtomicXor(image_3d, ivec3(0), 2) == 1 + && load_image_3d() == 3 + && imageAtomicXor(image_cube, ivec3(0), 2) == 1 + && load_image_cube() == 3 + && imageAtomicXor(image_cubeArray, ivec3(0), 2) == 1 + && load_image_cubeArray() == 3 + && imageAtomicXor(image_2dMultiSampleArray, ivec3(0), 1, 2) == 1 + && load_image_2dMultiSampleArray() == 3 + ; +} +bool checkAllImageAtomicCompSwap() +{ + resetAllImageValues(); + return true + && imageAtomicCompSwap(image_1d, 0, 0, 2) == 1 + && load_image_1d() == 1 + && imageAtomicCompSwap(image_buffer, 0, 1, 2) == 1 + && load_image_buffer() == 2 + && imageAtomicCompSwap(image_1dArray, ivec2(0), 0, 2) == 1 + && load_image_1dArray() == 1 + && imageAtomicCompSwap(image_2d, ivec2(0), 1, 2) == 1 + && load_image_2d() == 2 + && imageAtomicCompSwap(image_2dRect, ivec2(0), 1, 2) == 1 + && load_image_2dRect() == 2 + && imageAtomicCompSwap(image_2dMultiSample, ivec2(0), 1, 1, 2) == 1 + && load_image_2dMultiSample() == 2 + && imageAtomicCompSwap(image_2dArray, ivec3(0), 0, 2) == 1 + && load_image_2dArray() == 1 + && imageAtomicCompSwap(image_3d, ivec3(0), 1, 2) == 1 + && load_image_3d() == 2 + && imageAtomicCompSwap(image_cube, ivec3(0), 1, 2) == 1 + && load_image_cube() == 2 + && imageAtomicCompSwap(image_cubeArray, ivec3(0), 1, 2) == 1 + && load_image_cubeArray() == 2 + && imageAtomicCompSwap(image_2dMultiSampleArray, ivec3(0), 1, 1, 2) == 1 + && load_image_2dMultiSampleArray() == 2 + ; +} + +// CHECK_GLSL: void main( +// CHECK_SPV: OpEntryPoint +void computeMain() +{ + outputBuffer.data[0] = true + && checkAllImageSize() + && checkAllImageLoad() + && checkAllImageStore() + && checkAllImageSamples() + && checkAllImageAtomicAdd() + && checkAllImageAtomicExchange() + && checkAllImageAtomicMin() + && checkAllImageAtomicMax() + && checkAllImageAtomicAnd() + && checkAllImageAtomicOr() + && checkAllImageAtomicXor() + && checkAllImageAtomicCompSwap() + ; + // BUF: 1 +}
\ No newline at end of file diff --git a/tests/glsl/ssboMemberMemoryQualifier.slang b/tests/glsl/ssboMemberMemoryQualifier.slang new file mode 100644 index 000000000..78d029039 --- /dev/null +++ b/tests/glsl/ssboMemberMemoryQualifier.slang @@ -0,0 +1,54 @@ +//TEST:SIMPLE(filecheck=CHECK-GLSL): -stage compute -entry computeMain -allow-glsl -target glsl +//TEST:SIMPLE(filecheck=CHECK-SPV): -stage compute -entry computeMain -allow-glsl -target spirv -emit-spirv-directly + +// due to implementation limitations (slang-check-expr.cpp, `void visitMemberExpr()`) we are unable to +// implement and use .length with glsl vectors to test `readonly writeonly` +//#define TEST_whenVectorLengthIsImplemented + +volatile buffer Block1 +{ + restrict uint data1; + readonly uint data2; + readonly writeonly uint data3; + writeonly uint data4; + coherent uint data5; + volatile uint data6; +} inputBuffer1; + +coherent buffer Block2 { + readonly vec4 member1; + vec4 member2; +}inputBuffer2; + +buffer Block3 { + coherent readonly vec4 member1; + coherent vec4 member2; +}inputBuffer3; + +buffer Block4 { + struct structTmp + { + int val; + }; + readonly structTmp myStruct; + coherent readonly vec4 member1; + coherent vec4 member2; + readonly writeonly vec3 member3; +}inputBuffer4; + +// CHECK-GLSL: main +// CHECK-SPV: OpEntryPoint +layout(local_size_x = 1) in; +void computeMain() +{ + int v = inputBuffer1.data1; + v = inputBuffer1.data2; + inputBuffer1.data4 = 1; + inputBuffer1.data5 = 1; + inputBuffer1.data6 = 1; + inputBuffer2.member2 = inputBuffer2.member1; + inputBuffer3.member2 = inputBuffer3.member1; +#ifdef TEST_whenVectorLengthIsImplemented + v = inputBuffer4.member3.length(); +#endif +}
\ No newline at end of file diff --git a/tests/glsl/ssboMemberMemoryQualifierReadError.slang b/tests/glsl/ssboMemberMemoryQualifierReadError.slang new file mode 100644 index 000000000..fe2ea1943 --- /dev/null +++ b/tests/glsl/ssboMemberMemoryQualifierReadError.slang @@ -0,0 +1,17 @@ +//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -allow-glsl -target glsl +//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -allow-glsl -target spirv -emit-spirv-directly + +volatile buffer MyBlockName1 +{ + readonly uint data2; + readonly writeonly uint data3; +} inputBuffer1; + +layout(local_size_x = 1) in; +void computeMain() +{ +//CHECK: error 30011 + inputBuffer1.data2 = 1; +//CHECK: error 30011 + inputBuffer1.data3 = 1; +}
\ No newline at end of file diff --git a/tests/glsl/ssboMemberMemoryQualifierWriteError.slang b/tests/glsl/ssboMemberMemoryQualifierWriteError.slang new file mode 100644 index 000000000..f4423be25 --- /dev/null +++ b/tests/glsl/ssboMemberMemoryQualifierWriteError.slang @@ -0,0 +1,24 @@ +//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -allow-glsl -target glsl +//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -allow-glsl -target spirv -emit-spirv-directly + +volatile buffer MyBlockName1 +{ + writeonly uint data2; + readonly writeonly uint data3; +} inputBuffer1; + +buffer MyBlockName2 +{ + uint data; +} outputBuffer; + +layout(local_size_x = 1) in; +void computeMain() +{ +//CHECK: error 30101 + int a = inputBuffer1.data2; +//CHECK: error 30101 + int b = inputBuffer1.data3; +//CHECK: error 30101 + outputBuffer.data = inputBuffer1.data2; +}
\ No newline at end of file diff --git a/tests/glsl/ssboMemoryQualifier.slang b/tests/glsl/ssboMemoryQualifier.slang new file mode 100644 index 000000000..67da12e9e --- /dev/null +++ b/tests/glsl/ssboMemoryQualifier.slang @@ -0,0 +1,39 @@ +//TEST:SIMPLE(filecheck=CHECK-GLSL): -stage compute -entry computeMain -allow-glsl -target glsl +//TEST:SIMPLE(filecheck=CHECK-SPV): -stage compute -entry computeMain -allow-glsl -target spirv -emit-spirv-directly + +volatile buffer MyBlockName1 +{ + uint data1; +} inputBuffer1; +restrict buffer MyBlockName2 +{ + uint data1; +} inputBuffer2; +readonly writeonly buffer MyBlockName3 +{ + uint data1; +} inputBuffer3; +writeonly buffer MyBlockName4 +{ + uint data1; +} inputBuffer4; +readonly buffer MyBlockName5 +{ + uint data1; +} inputBuffer5; +coherent buffer MyBlockName6 +{ + uint data1; +} inputBuffer6; + +// CHECK-GLSL: main +// CHECK-SPV: OpEntryPoint +layout(local_size_x = 1) in; +void computeMain() +{ + inputBuffer1.data1 = 1; + inputBuffer2.data1 = 1; + inputBuffer4.data1 = 1; + int v = inputBuffer5.data1; + inputBuffer6.data1 = 1; +}
\ No newline at end of file diff --git a/tests/glsl/ssboMemoryQualifierReadError.slang b/tests/glsl/ssboMemoryQualifierReadError.slang new file mode 100644 index 000000000..cdd47d5b2 --- /dev/null +++ b/tests/glsl/ssboMemoryQualifierReadError.slang @@ -0,0 +1,27 @@ +//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -allow-glsl -target glsl +//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -allow-glsl -target spirv -emit-spirv-directly + +readonly writeonly buffer MyBlockName3 +{ + uint data1; +} inputBuffer1; + +readonly buffer MyBlockName5 +{ + uint data1; +} inputBuffer2; + +buffer dontOptimizeOutBlock +{ + uint data1; + uint data2; +} optimizeBlock; + +layout(local_size_x = 1) in; +void computeMain() +{ +//CHECK: error 30011 + inputBuffer1.data1 = optimizeBlock.data1; +//CHECK: error 30011 + inputBuffer2.data1 = optimizeBlock.data2; +}
\ No newline at end of file diff --git a/tests/glsl/ssboMemoryQualifierWriteError.slang b/tests/glsl/ssboMemoryQualifierWriteError.slang new file mode 100644 index 000000000..636641b3f --- /dev/null +++ b/tests/glsl/ssboMemoryQualifierWriteError.slang @@ -0,0 +1,29 @@ +//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -allow-glsl -target glsl +//TEST:SIMPLE(filecheck=CHECK): -stage compute -entry computeMain -allow-glsl -target spirv -emit-spirv-directly + +readonly writeonly buffer MyBlockName3 +{ + uint data1; +} inputBuffer1; + +writeonly buffer MyBlockName4 +{ + uint data1; +} inputBuffer2; + +buffer dontOptimizeOutBlock +{ + uint data1; + uint data2; +} optimizeBlock; + +layout(local_size_x = 1) in; +void computeMain() +{ +//CHECK: error 30101 + optimizeBlock.data1 = inputBuffer1.data1; +//CHECK: error 30101 + optimizeBlock.data2 = inputBuffer2.data1; +//CHECK: error 30101 + int a = inputBuffer2.data1; +}
\ No newline at end of file diff --git a/tests/glsl/ssboStructInsideStructMemoryQualifierError.slang b/tests/glsl/ssboStructInsideStructMemoryQualifierError.slang new file mode 100644 index 000000000..c5376b4a8 --- /dev/null +++ b/tests/glsl/ssboStructInsideStructMemoryQualifierError.slang @@ -0,0 +1,23 @@ +//TEST:SIMPLE(filecheck=CHECK-GLSL): -stage compute -entry computeMain -allow-glsl -target glsl +//TEST:SIMPLE(filecheck=CHECK-SPV): -stage compute -entry computeMain -allow-glsl -target spirv -emit-spirv-directly + +// This code should error since memory qualifiers are only allowed inside: +// Shader storage blocks, variables declared within shader storage blocks +// and variables declared as image types. Named structs inside a Interface +// block violates these rules +// CHECK-GLSL: error +// CHECK-SPV: error +buffer Block4 { + struct StructTmp + { + readonly int val; + }; + readonly structTmp myStruct; + coherent readonly vec4 member1; + coherent vec4 member2; +}inputBuffer4; + +layout(local_size_x = 1) in; +void computeMain() +{ +}
\ No newline at end of file diff --git a/tests/nv-extensions/nv-ray-tracing-motion-blur.slang b/tests/nv-extensions/nv-ray-tracing-motion-blur.slang index c66e69d14..753101d7e 100644 --- a/tests/nv-extensions/nv-ray-tracing-motion-blur.slang +++ b/tests/nv-extensions/nv-ray-tracing-motion-blur.slang @@ -20,7 +20,7 @@ struct Uniforms }; ConstantBuffer<Uniforms> ubo; -layout(rgba8) +layout(rgba32f) RWTexture2D<float4> outputImage; RaytracingAccelerationStructure as; diff --git a/tests/vkray/raygen.slang b/tests/vkray/raygen.slang index 9ba88095d..18ac74d4b 100644 --- a/tests/vkray/raygen.slang +++ b/tests/vkray/raygen.slang @@ -22,7 +22,7 @@ struct Uniforms ConstantBuffer<Uniforms> ubo; -layout(rgba8) +layout(rgba32f) RWTexture2D<float4> outputImage; RaytracingAccelerationStructure as; diff --git a/tools/gfx-unit-test/gfx-test-texture-util.cpp b/tools/gfx-unit-test/gfx-test-texture-util.cpp index ed651475d..3b3a1a760 100644 --- a/tools/gfx-unit-test/gfx-test-texture-util.cpp +++ b/tools/gfx-unit-test/gfx-test-texture-util.cpp @@ -80,6 +80,8 @@ namespace gfx_test case Format::R16G16_FLOAT: return new ValidationTextureFormat<uint16_t>(2); case Format::R16_FLOAT: return new ValidationTextureFormat<uint16_t>(1); + case Format::R64_UINT: return new ValidationTextureFormat<uint64_t>(1); + case Format::R32G32B32A32_UINT: return new ValidationTextureFormat<uint32_t>(4); case Format::R32G32B32_UINT: return new ValidationTextureFormat<uint32_t>(3); case Format::R32G32_UINT: return new ValidationTextureFormat<uint32_t>(2); @@ -93,6 +95,8 @@ namespace gfx_test case Format::R8G8_UINT: return new ValidationTextureFormat<uint8_t>(2); case Format::R8_UINT: return new ValidationTextureFormat<uint8_t>(1); + case Format::R64_SINT: return new ValidationTextureFormat<int64_t>(1); + case Format::R32G32B32A32_SINT: return new ValidationTextureFormat<int32_t>(4); case Format::R32G32B32_SINT: return new ValidationTextureFormat<int32_t>(3); case Format::R32G32_SINT: return new ValidationTextureFormat<int32_t>(2); diff --git a/tools/gfx/d3d/d3d-util.cpp b/tools/gfx/d3d/d3d-util.cpp index 34d615744..8d76c74b3 100644 --- a/tools/gfx/d3d/d3d-util.cpp +++ b/tools/gfx/d3d/d3d-util.cpp @@ -167,6 +167,8 @@ D3D12_DEPTH_STENCILOP_DESC D3DUtil::translateStencilOpDesc(DepthStencilOpDesc de case Format::R16G16_FLOAT: return DXGI_FORMAT_R16G16_FLOAT; case Format::R16_FLOAT: return DXGI_FORMAT_R16_FLOAT; + case Format::R64_UINT: return DXGI_FORMAT_R32G32_UINT; + case Format::R32G32B32A32_UINT: return DXGI_FORMAT_R32G32B32A32_UINT; case Format::R32G32B32_UINT: return DXGI_FORMAT_R32G32B32_UINT; case Format::R32G32_UINT: return DXGI_FORMAT_R32G32_UINT; @@ -180,6 +182,8 @@ D3D12_DEPTH_STENCILOP_DESC D3DUtil::translateStencilOpDesc(DepthStencilOpDesc de case Format::R8G8_UINT: return DXGI_FORMAT_R8G8_UINT; case Format::R8_UINT: return DXGI_FORMAT_R8_UINT; + case Format::R64_SINT: return DXGI_FORMAT_R32G32_SINT; + case Format::R32G32B32A32_SINT: return DXGI_FORMAT_R32G32B32A32_SINT; case Format::R32G32B32_SINT: return DXGI_FORMAT_R32G32B32_SINT; case Format::R32G32_SINT: return DXGI_FORMAT_R32G32_SINT; diff --git a/tools/gfx/gfx.slang b/tools/gfx/gfx.slang index e9a31445b..37ae5182d 100644 --- a/tools/gfx/gfx.slang +++ b/tools/gfx/gfx.slang @@ -150,6 +150,8 @@ public enum class Format R16G16_FLOAT, R16_FLOAT, + R64_UINT, + R32G32B32A32_UINT, R32G32B32_UINT, R32G32_UINT, @@ -163,6 +165,8 @@ public enum class Format R8G8_UINT, R8_UINT, + R64_SINT, + R32G32B32A32_SINT, R32G32B32_SINT, R32G32_SINT, diff --git a/tools/gfx/render.cpp b/tools/gfx/render.cpp index 6dd0c90dd..68f81fba5 100644 --- a/tools/gfx/render.cpp +++ b/tools/gfx/render.cpp @@ -86,6 +86,8 @@ struct FormatInfoMap set(Format::R16G16_FLOAT, SLANG_SCALAR_TYPE_FLOAT16, 2); set(Format::R16_FLOAT, SLANG_SCALAR_TYPE_FLOAT16, 1); + set(Format::R64_UINT, SLANG_SCALAR_TYPE_UINT64, 1); + set(Format::R32G32B32A32_UINT, SLANG_SCALAR_TYPE_UINT32, 4); set(Format::R32G32B32_UINT, SLANG_SCALAR_TYPE_UINT32, 3); set(Format::R32G32_UINT, SLANG_SCALAR_TYPE_UINT32, 2); @@ -99,6 +101,8 @@ struct FormatInfoMap set(Format::R8G8_UINT, SLANG_SCALAR_TYPE_UINT8, 2); set(Format::R8_UINT, SLANG_SCALAR_TYPE_UINT8, 1); + set(Format::R64_SINT, SLANG_SCALAR_TYPE_INT64, 1); + set(Format::R32G32B32A32_SINT, SLANG_SCALAR_TYPE_INT32, 4); set(Format::R32G32B32_SINT, SLANG_SCALAR_TYPE_INT32, 3); set(Format::R32G32_SINT, SLANG_SCALAR_TYPE_INT32, 2); diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h index 27a19acfb..cceac20e1 100644 --- a/tools/gfx/vulkan/vk-api.h +++ b/tools/gfx/vulkan/vk-api.h @@ -250,6 +250,10 @@ struct VulkanExtendedFeatureProperties VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT atomicFloat2Features = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT }; + // Image int64 atomic features + VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT imageInt64AtomicFeatures = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT + }; // Extended dynamic state features VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT diff --git a/tools/gfx/vulkan/vk-device.cpp b/tools/gfx/vulkan/vk-device.cpp index b2cbb03c1..dd8a674cb 100644 --- a/tools/gfx/vulkan/vk-device.cpp +++ b/tools/gfx/vulkan/vk-device.cpp @@ -487,6 +487,11 @@ Result DeviceImpl::initVulkanInstanceAndDevice( extendedFeatures.atomicFloat2Features.pNext = deviceFeatures2.pNext; deviceFeatures2.pNext = &extendedFeatures.atomicFloat2Features; + // Image Int64 Atomic + // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT.html + extendedFeatures.imageInt64AtomicFeatures.pNext = deviceFeatures2.pNext; + deviceFeatures2.pNext = &extendedFeatures.imageInt64AtomicFeatures; + // mesh shader features extendedFeatures.meshShaderFeatures.pNext = deviceFeatures2.pNext; deviceFeatures2.pNext = &extendedFeatures.meshShaderFeatures; @@ -580,6 +585,13 @@ Result DeviceImpl::initVulkanInstanceAndDevice( ); SIMPLE_EXTENSION_FEATURE( + extendedFeatures.imageInt64AtomicFeatures, + shaderImageInt64Atomics, + VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME, + "image-atomic-int64" + ); + + SIMPLE_EXTENSION_FEATURE( extendedFeatures.extendedDynamicStateFeatures, extendedDynamicState, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, @@ -1638,6 +1650,97 @@ Result DeviceImpl::createTextureResource( VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + if(desc.sampleDesc.numSamples != 1) + { + // Handle senario where texture is sampled. We cannot use + // a simple buffer copy for sampled textures. ClearColorImage + // is not data accurate but it is fine for testing & works. + FormatInfo formatInfo; + gfxGetFormatInfo(desc.format, &formatInfo); + uint32_t data = 0; + VkClearColorValue clearColor; + switch(formatInfo.channelType) + { + case SLANG_SCALAR_TYPE_INT32: + for(int i = 0; i < 4; i++) + clearColor.int32[i] = *reinterpret_cast<int32_t*>(const_cast<void*>(initData->data)); + break; + case SLANG_SCALAR_TYPE_UINT32: + for(int i = 0; i < 4; i++) + clearColor.uint32[i] = *reinterpret_cast<uint32_t*>(const_cast<void*>(initData->data)); break; + break; + case SLANG_SCALAR_TYPE_INT64: + { + for(int i = 0; i < 4; i++) + clearColor.int32[i] = int32_t(*reinterpret_cast<int64_t*>(const_cast<void*>(initData->data))); + break; + } + case SLANG_SCALAR_TYPE_UINT64: + { + for(int i = 0; i < 4; i++) + clearColor.uint32[i] = uint32_t(*reinterpret_cast<uint64_t*>(const_cast<void*>(initData->data))); + break; + } + case SLANG_SCALAR_TYPE_FLOAT16: + { + for(int i = 0; i < 4; i++) + clearColor.float32[i] = HalfToFloat(*reinterpret_cast<uint16_t*>(const_cast<void*>(initData->data))); + break; + } + case SLANG_SCALAR_TYPE_FLOAT32: + { + for(int i = 0; i < 4; i++) + clearColor.float32[i] = (*reinterpret_cast<float*>(const_cast<void*>(initData->data))); + break; + } + case SLANG_SCALAR_TYPE_FLOAT64: + { + for(int i = 0; i < 4; i++) + clearColor.float32[i] = float(*reinterpret_cast<double*>(const_cast<void*>(initData->data))); + break; + } + case SLANG_SCALAR_TYPE_INT8: + { + for(int i = 0; i < 4; i++) + clearColor.int32[i] = int32_t(*reinterpret_cast<int8_t*>(const_cast<void*>(initData->data))); + break; + } + case SLANG_SCALAR_TYPE_UINT8: + { + for(int i = 0; i < 4; i++) + clearColor.uint32[i] = uint32_t(*reinterpret_cast<uint8_t*>(const_cast<void*>(initData->data))); + break; + } + case SLANG_SCALAR_TYPE_INT16: + { + for(int i = 0; i < 4; i++) + clearColor.int32[i] = int32_t(*reinterpret_cast<int16_t*>(const_cast<void*>(initData->data))); + break; + } + case SLANG_SCALAR_TYPE_UINT16: + { + for(int i = 0; i < 4; i++) + clearColor.uint32[i] = uint32_t(*reinterpret_cast<uint16_t*>(const_cast<void*>(initData->data))); + break; + } + }; + + VkImageSubresourceRange range{}; + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + range.baseMipLevel = 0; + range.levelCount = VK_REMAINING_MIP_LEVELS; + range.baseArrayLayer = 0; + range.layerCount = VK_REMAINING_ARRAY_LAYERS; + + m_api.vkCmdClearColorImage( + commandBuffer, + texture->m_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &clearColor, + 1, + &range); + } + else { Offset srcOffset = 0; for (int i = 0; i < arraySize; ++i) @@ -2154,6 +2257,23 @@ Result DeviceImpl::createBufferView( info.buffer = resourceImpl->m_buffer.m_buffer; info.offset = offset; info.range = size; + VkBufferUsageFlags2CreateInfoKHR bufferViewUsage{}; + bufferViewUsage.sType = VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR; + + if (desc.type == IResourceView::Type::UnorderedAccess) + { + info.pNext = &bufferViewUsage; + bufferViewUsage.usage = VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR; + } + else if (desc.type == IResourceView::Type::ShaderResource) + { + info.pNext = &bufferViewUsage; + bufferViewUsage.usage = VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR; + } + else + { + assert(!"unhandled"); + } SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateBufferView(m_device, &info, nullptr, &view)); } diff --git a/tools/gfx/vulkan/vk-util.cpp b/tools/gfx/vulkan/vk-util.cpp index e8007805a..1a571c812 100644 --- a/tools/gfx/vulkan/vk-util.cpp +++ b/tools/gfx/vulkan/vk-util.cpp @@ -25,6 +25,8 @@ namespace gfx { case Format::R8_TYPELESS: return VK_FORMAT_R8_UNORM; case Format::B8G8R8A8_TYPELESS: return VK_FORMAT_B8G8R8A8_UNORM; + case Format::R64_UINT: return VK_FORMAT_R64_UINT; + case Format::R32G32B32A32_FLOAT: return VK_FORMAT_R32G32B32A32_SFLOAT; case Format::R32G32B32_FLOAT: return VK_FORMAT_R32G32B32_SFLOAT; case Format::R32G32_FLOAT: return VK_FORMAT_R32G32_SFLOAT; @@ -47,6 +49,8 @@ namespace gfx { case Format::R8G8_UINT: return VK_FORMAT_R8G8_UINT; case Format::R8_UINT: return VK_FORMAT_R8_UINT; + case Format::R64_SINT: return VK_FORMAT_R64_SINT; + case Format::R32G32B32A32_SINT: return VK_FORMAT_R32G32B32A32_SINT; case Format::R32G32B32_SINT: return VK_FORMAT_R32G32B32_SINT; case Format::R32G32_SINT: return VK_FORMAT_R32G32_SINT; diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp index 6b30315fb..96f5db6e0 100644 --- a/tools/render-test/shader-input-layout.cpp +++ b/tools/render-test/shader-input-layout.cpp @@ -112,6 +112,25 @@ namespace renderer_test else val->textureDesc.content = InputTextureContent::Gradient; } + else if (word == "sampleCount") + { + parser.Read("="); + auto contentWord = parser.ReadWord(); + if(contentWord == "one") + val->textureDesc.sampleCount = InputTextureSampleCount::One; + else if(contentWord == "two") + val->textureDesc.sampleCount = InputTextureSampleCount::Two; + else if(contentWord == "four") + val->textureDesc.sampleCount = InputTextureSampleCount::Four; + else if(contentWord == "eight") + val->textureDesc.sampleCount = InputTextureSampleCount::Eight; + else if(contentWord == "sixteen") + val->textureDesc.sampleCount = InputTextureSampleCount::Sixteen; + else if(contentWord == "thirtyTwo") + val->textureDesc.sampleCount = InputTextureSampleCount::ThirtyTwo; + else if(contentWord == "sixtyFour") + val->textureDesc.sampleCount = InputTextureSampleCount::SixtyFour; + } else if(word == "mipMaps") { parser.Read("="); @@ -633,6 +652,13 @@ namespace renderer_test maybeParseOptions(parser, val.Ptr()); return val; } + else if (parser.AdvanceIf("RWTextureBuffer")) + { + RefPtr<ShaderInputLayout::BufferVal> val = new ShaderInputLayout::BufferVal; + val->bufferDesc.type = InputBufferType::StorageBuffer; + maybeParseOptions(parser, val.Ptr()); + return val; + } else if (parser.AdvanceIf("Texture2D")) { RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; @@ -1100,7 +1126,99 @@ namespace renderer_test return SLANG_OK; } + void loadDataIntoHalf(uint16_t& out, const uint8_t& in) + { + out = FloatToHalf((float(in) / 255.0f)); + } + void loadDataIntoFloat(float& out, const uint8_t& in) + { + out = (float(in)/255.0f); + } + template<typename T> + void loadDataIntoUint(T& out, const uint8_t& in) + { + out = T(in); + } + template<typename T> + void loadDataIntoInt(T& out, const uint8_t& in) + { + out = T(in); + } + + // T for type to return, F for function pointer to operate on uint8->T + template<typename T, typename F> + void generateTextureDataWithTargetTStorage(TextureData& output, const InputTextureDesc& desc, gfx::FormatInfo& formatInfo, F loadUint8ToT) + { + // the following function assumes input of 0 or 1 since our testing framework only tests with 0 or 1 + TextureData work; + generateTextureDataRGB8(work, desc); + + output.init(desc.format); + + output.m_textureSize = work.m_textureSize; + output.m_mipLevels = work.m_mipLevels; + output.m_arraySize = work.m_arraySize; + List<TextureData::Slice>& dstSlices = output.m_slices; + + Index numSlices = work.m_slices.getCount(); + dstSlices.setCount(numSlices); + + for (int i = 0; i < numSlices; ++i) + { + const TextureData::Slice& srcSlice = work.m_slices[i]; + + const Index pixelCount = srcSlice.valuesCount; + const uint8_t* srcPixels = (const uint8_t*)srcSlice.values; + + T* dstPixels = (T*)output.setSliceCount(i, pixelCount); + switch (formatInfo.channelCount) + { + case 1: + { + for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 1) + { + // Copy out r + loadUint8ToT(dstPixels[0], srcPixels[0]); + } + break; + } + case 2: + { + for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 2) + { + // Copy out rg + loadUint8ToT(dstPixels[0], srcPixels[0]); + loadUint8ToT(dstPixels[1], srcPixels[1]); + } + break; + } + case 3: + { + for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 3) + { + // Copy out rgb + loadUint8ToT(dstPixels[0], srcPixels[0]); + loadUint8ToT(dstPixels[1], srcPixels[1]); + loadUint8ToT(dstPixels[2], srcPixels[2]); + } + break; + } + case 4: + { + for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 4) + { + // Copy out rgba + loadUint8ToT(dstPixels[0], srcPixels[0]); + loadUint8ToT(dstPixels[1], srcPixels[1]); + loadUint8ToT(dstPixels[2], srcPixels[2]); + loadUint8ToT(dstPixels[3], srcPixels[3]); + } + break; + } + } + } + } void generateTextureData(TextureData& output, const InputTextureDesc& desc) { gfx::FormatInfo formatInfo; @@ -1117,75 +1235,12 @@ namespace renderer_test case Format::R16G16_FLOAT: case Format::R16G16B16A16_FLOAT: { - TextureData work; - generateTextureDataRGB8(work, desc); - - output.init(desc.format); - - output.m_textureSize = work.m_textureSize; - output.m_mipLevels = work.m_mipLevels; - output.m_arraySize = work.m_arraySize; - - List<TextureData::Slice>& dstSlices = output.m_slices; - - Index numSlices = work.m_slices.getCount(); - dstSlices.setCount(numSlices); - - for (int i = 0; i < numSlices; ++i) - { - const TextureData::Slice& srcSlice = work.m_slices[i]; - - const Index pixelCount = srcSlice.valuesCount; - const uint8_t* srcPixels = (const uint8_t*)srcSlice.values; - - int16_t* dstPixels = (int16_t*)output.setSliceCount(i, pixelCount); - - switch (formatInfo.channelCount) - { - case 1: - { - for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 1) - { - // Copy out r - dstPixels[0] = FloatToHalf(srcPixels[0] * (1.0f / 255)); - } - break; - } - case 2: - { - for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 2) - { - // Copy out rg - dstPixels[0] = FloatToHalf(srcPixels[0] * (1.0f / 255)); - dstPixels[1] = FloatToHalf(srcPixels[1] * (1.0f / 255)); - } - break; - } - case 3: - { - for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 3) - { - // Copy out rgb - dstPixels[0] = FloatToHalf(srcPixels[0] * (1.0f / 255)); - dstPixels[1] = FloatToHalf(srcPixels[1] * (1.0f / 255)); - dstPixels[2] = FloatToHalf(srcPixels[2] * (1.0f / 255)); - } - break; - } - case 4: - { - for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 4) - { - // Copy out rgba - dstPixels[0] = FloatToHalf(srcPixels[0] * (1.0f / 255)); - dstPixels[1] = FloatToHalf(srcPixels[1] * (1.0f / 255)); - dstPixels[2] = FloatToHalf(srcPixels[2] * (1.0f / 255)); - dstPixels[3] = FloatToHalf(srcPixels[3] * (1.0f / 255)); - } - break; - } - } - } + generateTextureDataWithTargetTStorage<uint16_t>(output, desc, formatInfo, loadDataIntoHalf); + break; + } + case Format::R64_UINT: + { + generateTextureDataWithTargetTStorage<uint64_t>(output, desc, formatInfo, loadDataIntoUint<uint64_t>); break; } case Format::R32_FLOAT: @@ -1194,76 +1249,56 @@ namespace renderer_test case Format::R32G32B32A32_FLOAT: case Format::D32_FLOAT: { - TextureData work; - generateTextureDataRGB8(work, desc); - - output.init(desc.format); - - output.m_textureSize = work.m_textureSize; - output.m_mipLevels = work.m_mipLevels; - output.m_arraySize = work.m_arraySize; - - List<TextureData::Slice>& dstSlices = output.m_slices; - - Index numSlices = work.m_slices.getCount(); - dstSlices.setCount(numSlices); - - for (int i = 0; i < numSlices; ++i) - { - const TextureData::Slice& srcSlice = work.m_slices[i]; - - const Index pixelCount = srcSlice.valuesCount; - const uint8_t* srcPixels = (const uint8_t*)srcSlice.values; - - float* dstPixels = (float*)output.setSliceCount(i, pixelCount); - - switch (formatInfo.channelCount) - { - case 1: - { - for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels++) - { - // Copy out r - dstPixels[0] = srcPixels[0] * (1.0f / 255); - } - break; - } - case 2: - { - for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 2) - { - // Copy out rg - dstPixels[0] = srcPixels[0] * (1.0f / 255); - dstPixels[1] = srcPixels[1] * (1.0f / 255); - } - break; - } - case 3: - { - for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 3) - { - // Copy out rgb - dstPixels[0] = srcPixels[0] * (1.0f / 255); - dstPixels[1] = srcPixels[1] * (1.0f / 255); - dstPixels[2] = srcPixels[2] * (1.0f / 255); - } - break; - } - case 4: - { - - for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 4) - { - // Copy out rgba - dstPixels[0] = srcPixels[0] * (1.0f / 255); - dstPixels[1] = srcPixels[1] * (1.0f / 255); - dstPixels[2] = srcPixels[2] * (1.0f / 255); - dstPixels[3] = srcPixels[3] * (1.0f / 255); - } - break; - } - } - } + generateTextureDataWithTargetTStorage<float>(output, desc, formatInfo, loadDataIntoFloat); + break; + } + case Format::R32_UINT: + case Format::R32G32_UINT: + case Format::R32G32B32_UINT: + case Format::R32G32B32A32_UINT: + { + generateTextureDataWithTargetTStorage<uint32_t>(output, desc, formatInfo, loadDataIntoUint<uint32_t>); + break; + } + case Format::R16_UINT: + case Format::R16G16_UINT: + case Format::R16G16B16A16_UINT: + { + generateTextureDataWithTargetTStorage<uint16_t>(output, desc, formatInfo, loadDataIntoUint<uint16_t>); + break; + } + case Format::R8_UINT: + case Format::R8G8_UINT: + case Format::R8G8B8A8_UINT: + { + generateTextureDataWithTargetTStorage<uint8_t>(output, desc, formatInfo, loadDataIntoUint<uint8_t>); + break; + } + case Format::R64_SINT: + { + generateTextureDataWithTargetTStorage<int64_t>(output, desc, formatInfo, loadDataIntoInt<int64_t>); + break; + } + case Format::R32_SINT: + case Format::R32G32_SINT: + case Format::R32G32B32_SINT: + case Format::R32G32B32A32_SINT: + { + generateTextureDataWithTargetTStorage<int32_t>(output, desc, formatInfo, loadDataIntoInt<int32_t>); + break; + } + case Format::R16_SINT: + case Format::R16G16_SINT: + case Format::R16G16B16A16_SINT: + { + generateTextureDataWithTargetTStorage<int16_t>(output, desc, formatInfo, loadDataIntoInt<int16_t>); + break; + } + case Format::R8_SINT: + case Format::R8G8_SINT: + case Format::R8G8B8A8_SINT: + { + generateTextureDataWithTargetTStorage<int8_t>(output, desc, formatInfo, loadDataIntoInt<int8_t>); break; } default: @@ -1299,6 +1334,37 @@ namespace renderer_test output.init(Format::R8G8B8A8_UNORM); + enum class SimpleScalarType { + kUint, + kInt, + kFloat, + }; + SimpleScalarType type; + gfx::FormatInfo formatInfo; + gfxGetFormatInfo(inputDesc.format, &formatInfo); + switch (formatInfo.channelType) + { + case SLANG_SCALAR_TYPE_UINT64: + case SLANG_SCALAR_TYPE_UINT32: + case SLANG_SCALAR_TYPE_UINT16: + case SLANG_SCALAR_TYPE_UINT8: + type = SimpleScalarType::kUint; + break; + case SLANG_SCALAR_TYPE_INT64: + case SLANG_SCALAR_TYPE_INT32: + case SLANG_SCALAR_TYPE_INT16: + case SLANG_SCALAR_TYPE_INT8: + type = SimpleScalarType::kInt; + break; + case SLANG_SCALAR_TYPE_FLOAT64: + case SLANG_SCALAR_TYPE_FLOAT32: + case SLANG_SCALAR_TYPE_FLOAT16: + type = SimpleScalarType::kFloat; + break; + default: + type = SimpleScalarType::kUint; + break; + } //List<List<unsigned int>>& dataBuffer = output.dataBuffer; int arraySize = arrLen; if (inputDesc.isCube) @@ -1327,36 +1393,68 @@ namespace renderer_test uint32_t* dst = (uint32_t*)output.setSliceCount(slice, bufferLen); - _iteratePixels(inputDesc.dimension, size, dst, [&](int x, int y, int z) -> unsigned int - { - if (inputDesc.content == InputTextureContent::Zero) - { - return 0x0; - } - else if (inputDesc.content == InputTextureContent::One) - { - return 0xFFFFFFFF; - } - else if (inputDesc.content == InputTextureContent::Gradient) - { - unsigned char r = (unsigned char)(x / (float)(size - 1) * 255.0f); - unsigned char g = (unsigned char)(y / (float)(size - 1) * 255.0f); - unsigned char b = (unsigned char)(z / (float)(size - 1) * 255.0f); - return 0xFF000000 + r + (g << 8) + (b << 16); - } - else if (inputDesc.content == InputTextureContent::ChessBoard) - { - unsigned int xSig = x < (size >> 1) ? 1 : 0; - unsigned int ySig = y < (size >> 1) ? 1 : 0; - unsigned int zSig = z < (size >> 1) ? 1 : 0; - auto sig = xSig ^ ySig ^ zSig; - if (sig) - return 0xFFFFFFFF; - else - return 0xFF808080; - } - return 0x0; - }); + if (type == SimpleScalarType::kFloat) + _iteratePixels(inputDesc.dimension, size, dst, [&](int x, int y, int z) -> unsigned int + { + if (inputDesc.content == InputTextureContent::Zero) + { + return 0x0; + } + else if (inputDesc.content == InputTextureContent::One) + { + return 0xFFFFFFFF; + } + else if (inputDesc.content == InputTextureContent::Gradient) + { + unsigned char r = (unsigned char)(x / (float)(size - 1) * 255.0f); + unsigned char g = (unsigned char)(y / (float)(size - 1) * 255.0f); + unsigned char b = (unsigned char)(z / (float)(size - 1) * 255.0f); + return 0xFF000000 + r + (g << 8) + (b << 16); + } + else if (inputDesc.content == InputTextureContent::ChessBoard) + { + unsigned int xSig = x < (size >> 1) ? 1 : 0; + unsigned int ySig = y < (size >> 1) ? 1 : 0; + unsigned int zSig = z < (size >> 1) ? 1 : 0; + auto sig = xSig ^ ySig ^ zSig; + if (sig) + return 0xFFFFFFFF; + else + return 0xFF808080; + } + return 0x0; + }); + else if (type == SimpleScalarType::kUint || type == SimpleScalarType::kInt) + _iteratePixels(inputDesc.dimension, size, dst, [&](int x, int y, int z) -> unsigned int + { + if (inputDesc.content == InputTextureContent::Zero) + { + return 0x0; + } + else if (inputDesc.content == InputTextureContent::One) + { + return 0x01010101; + } + else if (inputDesc.content == InputTextureContent::Gradient) + { + unsigned char r = (unsigned char)(x / (float)(size - 1)); + unsigned char g = (unsigned char)(y / (float)(size - 1)); + unsigned char b = (unsigned char)(z / (float)(size - 1)); + return 0x01000000 + r + (g << 8) + (b << 16); + } + else if (inputDesc.content == InputTextureContent::ChessBoard) + { + unsigned int xSig = x < (size >> 1) ? 1 : 0; + unsigned int ySig = y < (size >> 1) ? 1 : 0; + unsigned int zSig = z < (size >> 1) ? 1 : 0; + auto sig = xSig ^ ySig ^ zSig; + if (sig) + return 0x01010101; + else + return 0x0; + } + return 0x0; + }); slice++; } } diff --git a/tools/render-test/shader-input-layout.h b/tools/render-test/shader-input-layout.h index 2803d1915..de1da3da9 100644 --- a/tools/render-test/shader-input-layout.h +++ b/tools/render-test/shader-input-layout.h @@ -31,6 +31,16 @@ enum class InputTextureContent Zero, One, ChessBoard, Gradient }; +enum InputTextureSampleCount +{ + One = 1, + Two = 2, + Four = 4, + Eight = 8, + Sixteen = 16, + ThirtyTwo = 32, + SixtyFour = 64, +}; struct InputTextureDesc { int dimension = 2; @@ -41,6 +51,7 @@ struct InputTextureDesc int size = 4; int mipMapCount = 0; ///< 0 means the maximum number of mips will be bound + InputTextureSampleCount sampleCount = InputTextureSampleCount::One; Format format = Format::R8G8B8A8_UNORM; InputTextureContent content = InputTextureContent::One; diff --git a/tools/render-test/shader-renderer-util.cpp b/tools/render-test/shader-renderer-util.cpp index bbc000594..fe726012e 100644 --- a/tools/render-test/shader-renderer-util.cpp +++ b/tools/render-test/shader-renderer-util.cpp @@ -32,6 +32,7 @@ using Slang::Result; // Default to R8G8B8A8_UNORM const Format format = (inputDesc.format == Format::Unknown) ? Format::R8G8B8A8_UNORM : inputDesc.format; + textureResourceDesc.sampleDesc = ITextureResource::SampleDesc{inputDesc.sampleCount, 0}; textureResourceDesc.format = format; textureResourceDesc.numMipLevels = texData.m_mipLevels; textureResourceDesc.arraySize = inputDesc.arrayLength; |
