summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-10-25 12:49:36 -0700
committerGitHub <noreply@github.com>2018-10-25 12:49:36 -0700
commitad47fe71defcc96a7bed87a4c3a40543978f0fb8 (patch)
treec0bc94a7996b0bf4128445d7bcb988de7aa90f93
parent4f0415e338862ffec50c2d47eddea958255b504e (diff)
Fix Vulkan codegen for image atomics (#690)
The basic problem was that the front-end was generating code that used a `uint` vector for the coordinates, while GLSL requires an `int` vector. Without support for implicit type conversions, this leads to GLSL compilation failure. The fix here is to insert the type conversion as late as possible (during GLSL emit). This isn't a pretty solution, but it is the easiest one to implement in the current compiler. A more forward-looking approach would be to support "force inline" functions in the stdlib, so that we can implement the conversion logic in a stdlib implementation specialized for the Vulkan/GLSL target. At the moment, everything to do with image atomics is all sleight of hand anyway, so making it incrementally messier isn't a bit hit.
-rw-r--r--source/slang/emit.cpp35
-rw-r--r--tests/bugs/vk-image-atomics.slang12
-rw-r--r--tests/bugs/vk-image-atomics.slang.glsl18
3 files changed, 64 insertions, 1 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 9c7d61c51..1c02b64ef 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -3251,7 +3251,40 @@ struct EmitVisitor
//
Emit("(");
emitIROperand(ctx, arg->getOperand(0), mode, kEOp_General);
- Emit("), (");
+ Emit("), ");
+
+ // The coordinate argument will have been computed
+ // as a `vector<uint, N>` because that is how the
+ // HLSL image subscript operations are defined.
+ // In contrast, the GLSL `imageAtomic*` operations
+ // expect `vector<int, N>` coordinates, so we
+ // hill hackily insert the conversion here as
+ // part of the intrinsic op.
+ //
+ auto coords = arg->getOperand(1);
+ auto coordsType = coords->getDataType();
+
+ auto coordsVecType = as<IRVectorType>(coordsType);
+ IRIntegerValue elementCount = 1;
+ if(coordsVecType)
+ {
+ coordsType = coordsVecType->getElementType();
+ elementCount = GetIntVal(coordsVecType->getElementCount());
+ }
+
+ SLANG_ASSERT(coordsType->op == kIROp_UIntType);
+
+ if (elementCount > 1)
+ {
+ Emit("ivec");
+ emit(elementCount);
+ }
+ else
+ {
+ Emit("int");
+ }
+
+ Emit("(");
emitIROperand(ctx, arg->getOperand(1), mode, kEOp_General);
Emit(")");
}
diff --git a/tests/bugs/vk-image-atomics.slang b/tests/bugs/vk-image-atomics.slang
new file mode 100644
index 000000000..f846606f9
--- /dev/null
+++ b/tests/bugs/vk-image-atomics.slang
@@ -0,0 +1,12 @@
+//TEST:CROSS_COMPILE: -profile ps_5_0 -entry main -target spirv-assembly
+
+// Ensure that we can lower to `imageAtomicAdd` correctly.
+
+RWTexture2D<uint> t;
+
+float4 main() : SV_Target
+{
+ uint u;
+ InterlockedAdd(t[uint2(0)], 1, u);
+ return u;
+}
diff --git a/tests/bugs/vk-image-atomics.slang.glsl b/tests/bugs/vk-image-atomics.slang.glsl
new file mode 100644
index 000000000..383b396ed
--- /dev/null
+++ b/tests/bugs/vk-image-atomics.slang.glsl
@@ -0,0 +1,18 @@
+#version 450
+
+layout(r32ui)
+layout(binding = 0)
+uniform uimage2D t_0;
+
+layout(location = 0)
+out vec4 _S1;
+
+void main()
+{
+ const uint _S2 = uint(1);
+
+ uint _S3;
+ _S3 = imageAtomicAdd(t_0, ivec2(uvec2(0)), _S2);
+ _S1 = vec4(_S3);
+ return;
+}