summaryrefslogtreecommitdiff
path: root/source/slang/slang-emit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-emit.cpp')
-rw-r--r--source/slang/slang-emit.cpp89
1 files changed, 89 insertions, 0 deletions
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 3caef0a9f..efa56c261 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -5,6 +5,7 @@
#include "../core/slang-type-text-util.h"
#include "slang-ir-bind-existentials.h"
+#include "slang-ir-byte-address-legalize.h"
#include "slang-ir-dce.h"
#include "slang-ir-entry-point-uniforms.h"
#include "slang-ir-glsl-legalize.h"
@@ -411,6 +412,94 @@ Result linkAndOptimizeIR(
break;
}
+ // For all targets, we translate load/store operations
+ // of aggregate types from/to byte-address buffers into
+ // stores of individual scalar or vector values.
+ //
+ {
+ ByteAddressBufferLegalizationOptions byteAddressBufferOptions;
+
+ // Depending on the target, we may decide to do
+ // more aggressive translation that reduces the
+ // load/store operations down to invididual scalars
+ // (splitting up vector ops).
+ //
+ switch( target )
+ {
+ default:
+ break;
+
+ case CodeGenTarget::GLSL:
+ // For GLSL targets, we want to translate the vector load/store
+ // operations into scalar ops. This is in part as a simplification,
+ // but it also ensures that our generated code respects the lax
+ // alignment rules for D3D byte-address buffers (the base address
+ // of a buffer need not be more than 4-byte aligned, and loads
+ // of vectors need only be aligned based on their element type).
+ //
+ // TODO: We should consider having an extended variant of `Load<T>`
+ // on byte-address buffers which expresses a programmer's knowledge
+ // that the load will have greater alignment than required by D3D.
+ // That could either come as an explicit guaranteed-alignment
+ // operand, or instead as something like a `Load4Aligned<T>` operation
+ // that returns a `vector<4,T>` and assumes `4*sizeof(T)` alignemtn.
+ //
+ byteAddressBufferOptions.scalarizeVectorLoadStore = true;
+
+ // For GLSL targets, there really isn't a low-level concept
+ // of a byte-address buffer at all, and the standard "shader storage
+ // buffer" (SSBO) feature is a lot closer to an HLSL structured
+ // buffer for our purposes.
+ //
+ // In particular, each SSBO can only have a single element type,
+ // so that even with bitcasts we can't have a single buffer declaration
+ // (e.g., one with `uint` elements) service all load/store operations
+ // (e.g., a `half` value can't be stored atomically if there are
+ // `uint` elements, unless we use explicit atomics).
+ //
+ // In order to simplify things, we will translate byte-address buffer
+ // ops to equivalent structured-buffer ops for GLSL targets, where
+ // each unique type being loaded/stored yields a different global
+ // parameter declaration of the buffer.
+ //
+ byteAddressBufferOptions.translateToStructuredBufferOps = true;
+ break;
+ }
+
+ // We also need to decide whether to translate
+ // any "leaf" load/store operations over to
+ // use only unsigned-integer types and then
+ // bit-cast, or if we prefer to leave them
+ // as load/store of the original type.
+ //
+ switch( target )
+ {
+ case CodeGenTarget::HLSL:
+ {
+ auto profile = targetRequest->targetProfile;
+ if( profile.getFamily() == ProfileFamily::DX )
+ {
+ if(profile.GetVersion() <= ProfileVersion::DX_5_0)
+ {
+ // Fxc and earlier dxc versions do not support
+ // a templates `.Load<T>` operation on byte-address
+ // buffers, and instead need us to emit separate
+ // `uint` loads and then bit-cast over to
+ // the correct type.
+ //
+ byteAddressBufferOptions.useBitCastFromUInt = true;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ legalizeByteAddressBufferOps(session, irModule, byteAddressBufferOptions);
+ }
+
// For GLSL only, we will need to perform "legalization" of
// the entry point and any entry-point parameters.
//