summaryrefslogtreecommitdiffstats
path: root/source/slang/emit.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-05-02 14:44:13 -0700
committerGitHub <noreply@github.com>2018-05-02 14:44:13 -0700
commit384df864fdd2c518924d32295a13894f16295d43 (patch)
treee2e2687ce295dfcf407ec47c0e6ce9231863ec96 /source/slang/emit.cpp
parent60bcc6809f57e12f3705cc65cb325b0983b08899 (diff)
Add support for "swizzled stores" (#544)
This was a known issue in our IR representation, which was now biting a user. The basic problem is that in code like the following: ```hlsl RWStructureBuffer<float4> buffer; ... buffer[index].xz = value; ``` we ideally want to be able to reproduce the original HLSL code exactly, but that requires directly encoding the way that this code writes to two elements of a vector, but not the others. The currently lowering strategy we had produced IR something like: ```hlsl float4 tmp = buffer[index]; tmp.xz = value; buffer[index] = tmp; ``` That transformation might seem valid, but it has some big problems: * It generates UAV reads that are not needed, which could impact performance * It performs read-modify-write operations on memory that the programmer didn't explicitly write, which could create data races The fix here is somewhat obvious: if the "base" of a swizzle operation on a left-hand side resolves to a pointer in our IR, then we can output a "swizzled store" instead of the read-modify-write dance. We currently keep the read-modify-write around since it is potentially needed as a fallback in the general case. Along the way I also tried to make sure that we handle the case where we have a swizzle of a swizzle on the left-hand side: ```hlsl buffer[index].xz.y = value; ``` That code should behave the same as `buffer[index].z = value`. I am currently detecting and cleaning up this logic in the lowering path for `SwizzleExpr`, because that is the only place in the lowering logic that "swizzled l-values" currently get created.
Diffstat (limited to 'source/slang/emit.cpp')
-rw-r--r--source/slang/emit.cpp25
1 files changed, 25 insertions, 0 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index be6112abe..9f9a089c8 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -3317,6 +3317,31 @@ struct EmitVisitor
emit(";\n");
}
break;
+
+ case kIROp_SwizzledStore:
+ {
+ auto ii = cast<IRSwizzledStore>(inst);
+ emit("(");
+ emitIROperand(ctx, ii->getDest(), mode);
+ emit(").");
+ UInt elementCount = ii->getElementCount();
+ for (UInt ee = 0; ee < elementCount; ++ee)
+ {
+ IRInst* irElementIndex = ii->getElementIndex(ee);
+ assert(irElementIndex->op == kIROp_IntLit);
+ IRConstant* irConst = (IRConstant*)irElementIndex;
+
+ UInt elementIndex = (UInt)irConst->u.intVal;
+ assert(elementIndex < 4);
+
+ char const* kComponents[] = { "x", "y", "z", "w" };
+ emit(kComponents[elementIndex]);
+ }
+ emit(" = ");
+ emitIROperand(ctx, ii->getSource(), mode);
+ emit(";\n");
+ }
+ break;
}
}