|
|
@@ -1388,16 +1388,13 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vect
|
|
|
return createCompositeInsert(source, target, typeId, channels.front());
|
|
|
|
|
|
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
|
|
|
+
|
|
|
assert(isVector(target));
|
|
|
swizzle->addIdOperand(target);
|
|
|
- if (accessChain.component != NoResult)
|
|
|
- // For dynamic component selection, source does not involve in l-value swizzle
|
|
|
- swizzle->addIdOperand(target);
|
|
|
- else {
|
|
|
- assert(getNumComponents(source) == (int)channels.size());
|
|
|
- assert(isVector(source));
|
|
|
- swizzle->addIdOperand(source);
|
|
|
- }
|
|
|
+
|
|
|
+ assert(getNumComponents(source) == (int)channels.size());
|
|
|
+ assert(isVector(source));
|
|
|
+ swizzle->addIdOperand(source);
|
|
|
|
|
|
// Set up an identity shuffle from the base value to the result value
|
|
|
unsigned int components[4];
|
|
|
@@ -1406,12 +1403,8 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vect
|
|
|
components[i] = i;
|
|
|
|
|
|
// Punch in the l-value swizzle
|
|
|
- for (int i = 0; i < (int)channels.size(); ++i) {
|
|
|
- if (accessChain.component != NoResult)
|
|
|
- components[i] = channels[i]; // Only shuffle the base value
|
|
|
- else
|
|
|
- components[channels[i]] = numTargetComponents + i;
|
|
|
- }
|
|
|
+ for (int i = 0; i < (int)channels.size(); ++i)
|
|
|
+ components[channels[i]] = numTargetComponents + i;
|
|
|
|
|
|
// finish the instruction with these components selectors
|
|
|
for (int i = 0; i < numTargetComponents; ++i)
|
|
|
@@ -2203,7 +2196,7 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
|
|
|
accessChain.preSwizzleBaseType = preSwizzleBaseType;
|
|
|
|
|
|
// if needed, propagate the swizzle for the current access chain
|
|
|
- if (accessChain.swizzle.size()) {
|
|
|
+ if (accessChain.swizzle.size() > 0) {
|
|
|
std::vector<unsigned> oldSwizzle = accessChain.swizzle;
|
|
|
accessChain.swizzle.resize(0);
|
|
|
for (unsigned int i = 0; i < swizzle.size(); ++i) {
|
|
|
@@ -2224,24 +2217,18 @@ void Builder::accessChainStore(Id rvalue)
|
|
|
|
|
|
transferAccessChainSwizzle(true);
|
|
|
Id base = collapseAccessChain();
|
|
|
+ Id source = rvalue;
|
|
|
+
|
|
|
+ // dynamic component should be gone
|
|
|
+ assert(accessChain.component == NoResult);
|
|
|
|
|
|
// If swizzle still exists, it is out-of-order or not full, we must load the target vector,
|
|
|
// extract and insert elements to perform writeMask and/or swizzle.
|
|
|
- Id source = NoResult;
|
|
|
- if (accessChain.swizzle.size()) {
|
|
|
+ if (accessChain.swizzle.size() > 0) {
|
|
|
Id tempBaseId = createLoad(base);
|
|
|
- source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle);
|
|
|
+ source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
|
|
|
}
|
|
|
|
|
|
- // dynamic component selection
|
|
|
- if (accessChain.component != NoResult) {
|
|
|
- Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
|
|
|
- source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
|
|
|
- }
|
|
|
-
|
|
|
- if (source == NoResult)
|
|
|
- source = rvalue;
|
|
|
-
|
|
|
createStore(source, base);
|
|
|
}
|
|
|
|
|
|
@@ -2251,7 +2238,7 @@ Id Builder::accessChainLoad(Decoration precision, Id resultType)
|
|
|
Id id;
|
|
|
|
|
|
if (accessChain.isRValue) {
|
|
|
- // transfer access chain, but keep it static, so we can stay in registers
|
|
|
+ // transfer access chain, but try to stay in registers
|
|
|
transferAccessChainSwizzle(false);
|
|
|
if (accessChain.indexChain.size() > 0) {
|
|
|
Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType;
|
|
|
@@ -2299,16 +2286,16 @@ Id Builder::accessChainLoad(Decoration precision, Id resultType)
|
|
|
return id;
|
|
|
|
|
|
// Do remaining swizzling
|
|
|
- // First, static swizzling
|
|
|
- if (accessChain.swizzle.size()) {
|
|
|
- // static swizzle
|
|
|
+
|
|
|
+ // Do the basic swizzle
|
|
|
+ if (accessChain.swizzle.size() > 0) {
|
|
|
Id swizzledType = getScalarTypeId(getTypeId(id));
|
|
|
if (accessChain.swizzle.size() > 1)
|
|
|
swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size());
|
|
|
id = createRvalueSwizzle(precision, swizzledType, id, accessChain.swizzle);
|
|
|
}
|
|
|
|
|
|
- // dynamic single-component selection
|
|
|
+ // Do the dynamic component
|
|
|
if (accessChain.component != NoResult)
|
|
|
id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
|
|
|
|
|
|
@@ -2458,26 +2445,66 @@ void Builder::dump(std::vector<unsigned int>& out) const
|
|
|
// Protected methods.
|
|
|
//
|
|
|
|
|
|
-// Turn the described access chain in 'accessChain' into an instruction
|
|
|
+// Turn the described access chain in 'accessChain' into an instruction(s)
|
|
|
// computing its address. This *cannot* include complex swizzles, which must
|
|
|
-// be handled after this is called, but it does include swizzles that select
|
|
|
-// an individual element, as a single address of a scalar type can be
|
|
|
-// computed by an OpAccessChain instruction.
|
|
|
+// be handled after this is called.
|
|
|
+//
|
|
|
+// Can generate code.
|
|
|
Id Builder::collapseAccessChain()
|
|
|
{
|
|
|
assert(accessChain.isRValue == false);
|
|
|
|
|
|
- if (accessChain.indexChain.size() > 0) {
|
|
|
- if (accessChain.instr == 0) {
|
|
|
- StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
|
|
|
- accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
|
|
|
- }
|
|
|
-
|
|
|
+ // did we already emit an access chain for this?
|
|
|
+ if (accessChain.instr != NoResult)
|
|
|
return accessChain.instr;
|
|
|
- } else
|
|
|
+
|
|
|
+ // If we have a dynamic component, we can still transfer
|
|
|
+ // that into a final operand to the access chain. We need to remap the
|
|
|
+ // dynamic component through the swizzle to get a new dynamic component to
|
|
|
+ // update.
|
|
|
+ //
|
|
|
+ // This was not done in transferAccessChainSwizzle() because it might
|
|
|
+ // generate code.
|
|
|
+ remapDynamicSwizzle();
|
|
|
+ if (accessChain.component != NoResult) {
|
|
|
+ // transfer the dynamic component to the access chain
|
|
|
+ accessChain.indexChain.push_back(accessChain.component);
|
|
|
+ accessChain.component = NoResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ // note that non-trivial swizzling is left pending
|
|
|
+
|
|
|
+ // do we have an access chain?
|
|
|
+ if (accessChain.indexChain.size() == 0)
|
|
|
return accessChain.base;
|
|
|
|
|
|
- // note that non-trivial swizzling is left pending...
|
|
|
+ // emit the access chain
|
|
|
+ StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
|
|
|
+ accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
|
|
|
+
|
|
|
+ return accessChain.instr;
|
|
|
+}
|
|
|
+
|
|
|
+// For a dynamic component selection of a swizzle.
|
|
|
+//
|
|
|
+// Turn the swizzle and dynamic component into just a dynamic component.
|
|
|
+//
|
|
|
+// Generates code.
|
|
|
+void Builder::remapDynamicSwizzle()
|
|
|
+{
|
|
|
+ // do we have a swizzle to remap a dynamic component through?
|
|
|
+ if (accessChain.component != NoResult && accessChain.swizzle.size() > 1) {
|
|
|
+ // build a vector of the swizzle for the component to map into
|
|
|
+ std::vector<Id> components;
|
|
|
+ for (int c = 0; c < accessChain.swizzle.size(); ++c)
|
|
|
+ components.push_back(makeUintConstant(accessChain.swizzle[c]));
|
|
|
+ Id mapType = makeVectorType(makeUintType(32), (int)accessChain.swizzle.size());
|
|
|
+ Id map = makeCompositeConstant(mapType, components);
|
|
|
+
|
|
|
+ // use it
|
|
|
+ accessChain.component = createVectorExtractDynamic(map, makeUintType(32), accessChain.component);
|
|
|
+ accessChain.swizzle.clear();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// clear out swizzle if it is redundant, that is reselecting the same components
|
|
|
@@ -2503,38 +2530,30 @@ void Builder::simplifyAccessChainSwizzle()
|
|
|
|
|
|
// To the extent any swizzling can become part of the chain
|
|
|
// of accesses instead of a post operation, make it so.
|
|
|
-// If 'dynamic' is true, include transferring a non-static component index,
|
|
|
-// otherwise, only transfer static indexes.
|
|
|
+// If 'dynamic' is true, include transferring the dynamic component,
|
|
|
+// otherwise, leave it pending.
|
|
|
//
|
|
|
-// Also, Boolean vectors are likely to be special. While
|
|
|
-// for external storage, they should only be integer types,
|
|
|
-// function-local bool vectors could use sub-word indexing,
|
|
|
-// so keep that as a separate Insert/Extract on a loaded vector.
|
|
|
+// Does not generate code. just updates the access chain.
|
|
|
void Builder::transferAccessChainSwizzle(bool dynamic)
|
|
|
{
|
|
|
- // too complex?
|
|
|
- if (accessChain.swizzle.size() > 1)
|
|
|
- return;
|
|
|
-
|
|
|
// non existent?
|
|
|
if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
|
|
|
return;
|
|
|
|
|
|
- // single component...
|
|
|
-
|
|
|
- // skip doing it for Boolean vectors
|
|
|
- if (isBoolType(getContainedTypeId(accessChain.preSwizzleBaseType)))
|
|
|
+ // too complex?
|
|
|
+ // (this requires either a swizzle, or generating code for a dynamic component)
|
|
|
+ if (accessChain.swizzle.size() > 1)
|
|
|
return;
|
|
|
|
|
|
+ // single component, either in the swizzle and/or dynamic component
|
|
|
if (accessChain.swizzle.size() == 1) {
|
|
|
- // handle static component
|
|
|
+ assert(accessChain.component == NoResult);
|
|
|
+ // handle static component selection
|
|
|
accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
|
|
|
accessChain.swizzle.clear();
|
|
|
- // note, the only valid remaining dynamic access would be to this one
|
|
|
- // component, so don't bother even looking at accessChain.component
|
|
|
accessChain.preSwizzleBaseType = NoType;
|
|
|
- accessChain.component = NoResult;
|
|
|
} else if (dynamic && accessChain.component != NoResult) {
|
|
|
+ assert(accessChain.swizzle.size() == 0);
|
|
|
// handle dynamic component
|
|
|
accessChain.indexChain.push_back(accessChain.component);
|
|
|
accessChain.preSwizzleBaseType = NoType;
|