diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-10-25 12:49:36 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-10-25 12:49:36 -0700 |
| commit | ad47fe71defcc96a7bed87a4c3a40543978f0fb8 (patch) | |
| tree | c0bc94a7996b0bf4128445d7bcb988de7aa90f93 /source | |
| parent | 4f0415e338862ffec50c2d47eddea958255b504e (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.
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/emit.cpp | 35 |
1 files changed, 34 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(")"); } |
