Commit 06e1d0b4 by John Kessenich

glslang -> SPV: Improvements in swizzles on access chains: Bug 14007 (wrong…

glslang -> SPV: Improvements in swizzles on access chains: Bug 14007 (wrong type), simplications, tests, support mixed swizzle with dynamic component selection. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@31277 e7fa87d3-cd2b-0410-9028-fcbf551c1848
parent 6b3fd19d
......@@ -573,7 +573,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
// so short circuit the access-chain stuff with a swizzle.
std::vector<unsigned> swizzle;
swizzle.push_back(node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst());
builder.accessChainPushSwizzle(swizzle, node->getLeft()->getVectorSize(), convertGlslangToSpvType(node->getType()));
builder.accessChainPushSwizzle(swizzle, node->getLeft()->getVectorSize());
} else {
// normal case for indexing array or structure or block
builder.accessChainPush(builder.makeIntConstant(index), convertGlslangToSpvType(node->getType()));
......@@ -615,7 +615,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
std::vector<unsigned> swizzle;
for (int i = 0; i < (int)swizzleSequence.size(); ++i)
swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst());
builder.accessChainPushSwizzle(swizzle, node->getLeft()->getVectorSize(), convertGlslangToSpvType(node->getType()));
builder.accessChainPushSwizzle(swizzle, node->getLeft()->getVectorSize());
}
return false;
default:
......
......@@ -907,6 +907,27 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, std::vecto
return insert->getResultId();
}
Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
{
Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
extract->addIdOperand(vector);
extract->addIdOperand(componentIndex);
buildPoint->addInstruction(extract);
return extract->getResultId();
}
Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex)
{
Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic);
insert->addIdOperand(vector);
insert->addIdOperand(component);
insert->addIdOperand(componentIndex);
buildPoint->addInstruction(insert);
return insert->getResultId();
}
// An opcode that has no operands, no result id, and no type
void Builder::createNoResultOp(Op opCode)
{
......@@ -997,6 +1018,7 @@ Id Builder::createRvalueSwizzle(Id typeId, Id source, std::vector<unsigned>& cha
return createCompositeExtract(source, typeId, channels.front());
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
assert(isVector(source));
swizzle->addIdOperand(source);
swizzle->addIdOperand(source);
for (int i = 0; i < (int)channels.size(); ++i)
......@@ -1014,6 +1036,8 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<uns
return createCompositeInsert(source, target, typeId, channels.front());
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
assert(isVector(source));
assert(isVector(target));
swizzle->addIdOperand(target);
swizzle->addIdOperand(source);
......@@ -1813,13 +1837,12 @@ void Builder::clearAccessChain()
accessChain.instr = 0;
accessChain.swizzle.clear();
accessChain.component = 0;
accessChain.swizzleTargetWidth = 0;
accessChain.resultType = NoType;
accessChain.isRValue = false;
}
// Comments in header
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width, Id type)
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width)
{
// if needed, propagate the swizzle for the current access chain
if (accessChain.swizzle.size()) {
......@@ -1828,15 +1851,8 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width,
for (unsigned int i = 0; i < swizzle.size(); ++i) {
accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]);
}
} else {
} else
accessChain.swizzle = swizzle;
}
// track width the swizzle operates on; once known, it does not change
if (accessChain.swizzleTargetWidth == 0)
accessChain.swizzleTargetWidth = width;
accessChain.resultType = type;
// determine if we need to track this swizzle anymore
simplifyAccessChainSwizzle();
......@@ -1849,23 +1865,24 @@ void Builder::accessChainStore(Id rvalue)
Id base = collapseAccessChain();
if (accessChain.swizzle.size() && accessChain.component)
MissingFunctionality("simultaneous l-value swizzle and dynamic component selection");
// If swizzle 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;
Id source = NoResult;
if (accessChain.swizzle.size()) {
Id tempBaseId = createLoad(base);
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle);
} else if (accessChain.component) {
Id tempBaseId = createLoad(base);
Instruction* vectorInsert = new Instruction(getUniqueId(), getTypeId(tempBaseId), OpVectorInsertDynamic);
vectorInsert->addIdOperand(tempBaseId);
vectorInsert->addIdOperand(rvalue);
vectorInsert->addIdOperand(accessChain.component);
buildPoint->addInstruction(vectorInsert);
}
source = vectorInsert->getResultId();
} else
// dynamic component selection
if (accessChain.component) {
Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
}
if (source == NoResult)
source = rvalue;
createStore(source, base);
......@@ -1878,6 +1895,7 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
if (accessChain.isRValue) {
if (accessChain.indexChain.size() > 0) {
mergeAccessChainSwizzle(); // TODO: optimization: look at applying this optimization more widely
// if all the accesses are constants, we can use OpCompositeExtract
std::vector<unsigned> indexes;
bool constant = true;
......@@ -1913,14 +1931,25 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
id = createLoad(collapseAccessChain());
}
if (accessChain.component) {
Instruction* vectorExtract = new Instruction(getUniqueId(), getScalarTypeId(getTypeId(id)), OpVectorExtractDynamic);
vectorExtract->addIdOperand(id);
vectorExtract->addIdOperand(accessChain.component);
buildPoint->addInstruction(vectorExtract);
id = vectorExtract->getResultId();
} else if (accessChain.swizzle.size())
id = createRvalueSwizzle(accessChain.resultType, id, accessChain.swizzle);
// Done, unless there are swizzles to do
if (accessChain.swizzle.size() == 0 && accessChain.component == 0)
return id;
Id componentType = getScalarTypeId(accessChain.resultType);
// Do remaining swizzling
// First, static swizzling
if (accessChain.swizzle.size()) {
// static swizzle
Id resultType = componentType;
if (accessChain.swizzle.size() > 1)
resultType = makeVectorType(componentType, accessChain.swizzle.size());
id = createRvalueSwizzle(resultType, id, accessChain.swizzle);
}
// dynamic single-component selection
if (accessChain.component)
id = createVectorExtractDynamic(id, componentType, accessChain.component);
return id;
}
......@@ -2005,8 +2034,9 @@ Id Builder::collapseAccessChain()
// clear out swizzle if it is redundant
void Builder::simplifyAccessChainSwizzle()
{
// if swizzle has fewer components than our target, it is a writemask
if (accessChain.swizzleTargetWidth > (int)accessChain.swizzle.size())
// If the swizzle has fewer components than the vector, it is subsetting, and must stay
// to preserve that fact.
if (getNumTypeComponents(accessChain.resultType) > (int)accessChain.swizzle.size())
return;
// if components are out of order, it is a swizzle
......@@ -2017,7 +2047,31 @@ void Builder::simplifyAccessChainSwizzle()
// otherwise, there is no need to track this swizzle
accessChain.swizzle.clear();
accessChain.swizzleTargetWidth = 0;
}
// clear out swizzle if it can become part of the indexes
void Builder::mergeAccessChainSwizzle()
{
// is there even a chance of doing something? Need a single-component swizzle
if (accessChain.swizzle.size() > 1 ||
accessChain.swizzle.size() == 0 && accessChain.component == 0)
return;
// TODO: optimization: remove this, but for now confine this to non-dynamic accesses
// (the above test is correct when this is removed.)
if (accessChain.component)
return;
// move the swizzle over to the indexes
if (accessChain.swizzle.size() == 1)
accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
else
accessChain.indexChain.push_back(accessChain.component);
accessChain.resultType = getScalarTypeId(accessChain.resultType);
// now there is no need to track this swizzle
accessChain.component = NoResult;
accessChain.swizzle.clear();
}
// Utility method for creating a new block and setting the insert point to
......
......@@ -228,6 +228,9 @@ public:
Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
Id createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes);
Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex);
Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex);
void createNoResultOp(Op);
void createNoResultOp(Op, Id operand);
void createControlBarrier(unsigned executionScope);
......@@ -244,7 +247,7 @@ public:
// Take a copy of an lvalue (target) and a source of components, and set the
// source components into the lvalue where the 'channels' say to put them.
// An update version of the target is returned.
// An updated version of the target is returned.
// (No true lvalue or stores are used.)
Id createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<unsigned>& channels);
......@@ -426,9 +429,8 @@ public:
std::vector<Id> indexChain;
Id instr; // the instruction that generates this access chain
std::vector<unsigned> swizzle;
Id component; // a dynamic component index
int swizzleTargetWidth;
Id resultType; // dereferenced type, to be inclusive of swizzles, which can't have a pointer
Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle
Id resultType; // dereferenced type, to be exclusive of swizzles
bool isRValue;
};
......@@ -449,6 +451,7 @@ public:
{
assert(isPointer(lValue));
accessChain.base = lValue;
accessChain.resultType = getContainedTypeId(getTypeId(lValue));
}
// set new base value as an r-value
......@@ -467,7 +470,7 @@ public:
}
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width, Id type);
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width);
// push a variable component selection onto the access chain; supporting only one, so unsided
void accessChainPushComponent(Id component) { accessChain.component = component; }
......@@ -489,6 +492,7 @@ protected:
Id findCompositeConstant(Op typeClass, std::vector<Id>& comps) const;
Id collapseAccessChain();
void simplifyAccessChainSwizzle();
void mergeAccessChainSwizzle();
void createAndSetNoPredecessorBlock(const char*);
void createBranch(Block* block);
void createMerge(Op, Block*, unsigned int control);
......
......@@ -52,7 +52,7 @@ Linked fragment stage:
292: 19(int) Constant 2
299: 19(int) Constant 1
301: TypePointer Function 7(float)
331: TypeVector 7(float) 3
332: TypeVector 7(float) 3
347: 7(float) Constant 1073741824
354: 7(float) Constant 1065353216
359: 19(int) Constant 66
......@@ -435,11 +435,11 @@ Linked fragment stage:
329: 7(float) Load 302(f)
330: 7(float) FAdd 329 328
Store 302(f) 330
332: 8(fvec4) Load 10(v)
333: 331(fvec3) VectorShuffle 332 332 0 1 2
331: 8(fvec4) Load 10(v)
333: 332(fvec3) VectorShuffle 331 331 0 1 2
334: 8(fvec4) Load 10(v)
335: 331(fvec3) VectorShuffle 334 334 0 1 2
336: 331(fvec3) ExtInst 1(GLSL.std.450) 60(cross) 333 335
335: 332(fvec3) VectorShuffle 334 334 0 1 2
336: 332(fvec3) ExtInst 1(GLSL.std.450) 60(cross) 333 335
337: 7(float) CompositeExtract 336 0
338: 7(float) Load 302(f)
339: 7(float) FAdd 338 337
......
......@@ -58,7 +58,7 @@ Linked compute stage:
25: TypeVector 24(int) 3
26: TypePointer Input 25(ivec3)
27(gl_GlobalInvocationID): 26(ptr) Variable Input
28: TypeVector 24(int) 2
29: TypeVector 24(int) 2
32: TypePointer Function 8(float)
34(gl_LocalInvocationID): 26(ptr) Variable Input
38: 12(int) Constant 8
......@@ -87,12 +87,12 @@ Linked compute stage:
Store 16 14
20: 19(ptr) AccessChain 11(bufInst) 17
Store 20 18
29: 25(ivec3) Load 27(gl_GlobalInvocationID)
30: 28(ivec2) VectorShuffle 29 29 0 1
28: 25(ivec3) Load 27(gl_GlobalInvocationID)
30: 29(ivec2) VectorShuffle 28 28 0 1
31: 21(ivec2) Bitcast 30
Store 23(storePos) 31
35: 25(ivec3) Load 34(gl_LocalInvocationID)
36: 28(ivec2) VectorShuffle 35 35 0 1
36: 29(ivec2) VectorShuffle 35 35 0 1
37: 21(ivec2) Bitcast 36
39: 21(ivec2) CompositeConstruct 38 38
40: 21(ivec2) ISub 37 39
......
......@@ -59,7 +59,7 @@ Linked fragment stage:
50: TypePointer UniformConstant 49(ivec4)
51(v4): 50(ptr) Variable UniformConstant
71: 48(int) Constant 4
85: TypeVector 7(float) 3
86: TypeVector 7(float) 3
97: TypePointer Input 7(float)
98(f): 97(ptr) Variable Input
115: 14(int) Constant 16
......@@ -146,8 +146,8 @@ Linked fragment stage:
82: 8(fvec4) Load 36(gl_FragColor)
83: 8(fvec4) FAdd 82 81
Store 36(gl_FragColor) 83
86: 8(fvec4) Load 12(BaseColor)
87: 85(fvec3) VectorShuffle 86 86 0 1 2
85: 8(fvec4) Load 12(BaseColor)
87: 86(fvec3) VectorShuffle 85 85 0 1 2
88: 8(fvec4) Load 84(r)
89: 8(fvec4) VectorShuffle 88 87 4 5 6 3
Store 84(r) 89
......@@ -170,10 +170,10 @@ Linked fragment stage:
Branch 91
92: Label
104: 8(fvec4) Load 84(r)
105: 85(fvec3) VectorShuffle 104 104 0 1 2
105: 86(fvec3) VectorShuffle 104 104 0 1 2
106: 8(fvec4) Load 36(gl_FragColor)
107: 85(fvec3) VectorShuffle 106 106 0 1 2
108: 85(fvec3) FAdd 107 105
107: 86(fvec3) VectorShuffle 106 106 0 1 2
108: 86(fvec3) FAdd 107 105
109: 8(fvec4) Load 36(gl_FragColor)
110: 8(fvec4) VectorShuffle 109 108 4 5 6 3
Store 36(gl_FragColor) 110
......
#version 420
struct S
{
vec3 color;
};
layout(location = 0) out vec3 OutColor;
uniform int u;
void GetColor1(const S i)
{
OutColor += i.color.x;
}
void GetColor2(const S i, int comp)
{
OutColor += i.color[comp];
}
void GetColor3(const S i, int comp)
{
OutColor += i.color[comp].x;
}
void GetColor4(const S i, int comp)
{
OutColor += i.color[comp].x;
}
void GetColor5(const S i, int comp)
{
OutColor += i.color;
}
void GetColor6(const S i, int comp)
{
OutColor += i.color.yx[comp];
}
void GetColor7(const S i, int comp)
{
OutColor.xy += i.color.yxz.yx;
}
void GetColor8(const S i, int comp)
{
OutColor += i.color.yzx.yx.x.x;
}
void GetColor9(const S i, int comp)
{
OutColor.zxy += i.color;
}
void GetColor10(const S i, int comp)
{
OutColor.zy += i.color.xy;
}
void GetColor11(const S i, int comp)
{
OutColor.zxy.yx += i.color.xy;
}
void GetColor12(const S i, int comp)
{
OutColor[comp] += i.color.x;
}
void GetColor13(const S i, int comp)
{
// OutColor.zy[comp] += i.color.x; // not yet supported
}
void main()
{
S s;
OutColor = vec3(0.0);
GetColor1(s);
GetColor2(s, u);
GetColor3(s, u);
GetColor4(s, u);
GetColor5(s, u);
GetColor6(s, u);
GetColor7(s, u);
GetColor8(s, u);
GetColor9(s, u);
GetColor10(s, u);
GetColor11(s, u);
GetColor12(s, u);
GetColor13(s, u);
}
......@@ -28,6 +28,7 @@ spv.400.tesc
spv.400.tese
spv.420.geom
spv.430.vert
spv.accessChain.frag
spv.aggOps.frag
spv.always-discard.frag
spv.always-discard2.frag
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment