summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--slang-gfx.h12
-rw-r--r--source/slang/core.meta.slang4
-rw-r--r--source/slang/glsl.meta.slang460
-rw-r--r--source/slang/slang-ast-modifier.h47
-rw-r--r--source/slang/slang-ast-support-types.h2
-rw-r--r--source/slang/slang-check-decl.cpp32
-rw-r--r--source/slang/slang-check-expr.cpp68
-rw-r--r--source/slang/slang-check-impl.h1
-rw-r--r--source/slang/slang-check-modifier.cpp51
-rw-r--r--source/slang/slang-diagnostic-defs.h4
-rw-r--r--source/slang/slang-emit-c-like.cpp1
-rw-r--r--source/slang/slang-emit-c-like.h1
-rw-r--r--source/slang/slang-emit-glsl.cpp47
-rw-r--r--source/slang/slang-emit-glsl.h2
-rw-r--r--source/slang/slang-emit-spirv.cpp64
-rw-r--r--source/slang/slang-ir-inst-defs.h6
-rw-r--r--source/slang/slang-ir-insts.h4
-rw-r--r--source/slang/slang-ir-spirv-legalize.cpp7
-rw-r--r--source/slang/slang-lower-to-ir.cpp16
-rw-r--r--source/slang/slang-parser.cpp78
-rw-r--r--tests/glsl-intrinsic/image/i64imageDim.slang476
-rw-r--r--tests/glsl-intrinsic/image/iimageDim.slang411
-rw-r--r--tests/glsl-intrinsic/image/iimageDimTiny.slang34
-rw-r--r--tests/glsl-intrinsic/image/imageAsParamWithMemoryQualifiers.slang43
-rw-r--r--tests/glsl-intrinsic/image/imageAsParamWithMemoryQualifiersError.slang27
-rw-r--r--tests/glsl-intrinsic/image/imageDim.slang303
-rw-r--r--tests/glsl-intrinsic/image/nonImageAsParamWithMemoryQualifierError.slang26
-rw-r--r--tests/glsl-intrinsic/image/u64imageDim.slang476
-rw-r--r--tests/glsl-intrinsic/image/uimageDim.slang410
-rw-r--r--tests/glsl/ssboMemberMemoryQualifier.slang54
-rw-r--r--tests/glsl/ssboMemberMemoryQualifierReadError.slang17
-rw-r--r--tests/glsl/ssboMemberMemoryQualifierWriteError.slang24
-rw-r--r--tests/glsl/ssboMemoryQualifier.slang39
-rw-r--r--tests/glsl/ssboMemoryQualifierReadError.slang27
-rw-r--r--tests/glsl/ssboMemoryQualifierWriteError.slang29
-rw-r--r--tests/glsl/ssboStructInsideStructMemoryQualifierError.slang23
-rw-r--r--tests/nv-extensions/nv-ray-tracing-motion-blur.slang2
-rw-r--r--tests/vkray/raygen.slang2
-rw-r--r--tools/gfx-unit-test/gfx-test-texture-util.cpp4
-rw-r--r--tools/gfx/d3d/d3d-util.cpp4
-rw-r--r--tools/gfx/gfx.slang4
-rw-r--r--tools/gfx/render.cpp4
-rw-r--r--tools/gfx/vulkan/vk-api.h4
-rw-r--r--tools/gfx/vulkan/vk-device.cpp120
-rw-r--r--tools/gfx/vulkan/vk-util.cpp4
-rw-r--r--tools/render-test/shader-input-layout.cpp436
-rw-r--r--tools/render-test/shader-input-layout.h11
-rw-r--r--tools/render-test/shader-renderer-util.cpp1
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;