зеркало из https://github.com/stride3d/xkslang.git
Add option to unwrap I/O block aggregates in reflection
* We follow similar rules to uniform block exploding.
This commit is contained in:
Родитель
567396b6b4
Коммит
1905069857
|
@ -534,6 +534,8 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
|
|||
ReflectOptions |= EShReflectionSeparateBuffers;
|
||||
} else if (lowerword == "reflect-all-block-variables") {
|
||||
ReflectOptions |= EShReflectionAllBlockVariables;
|
||||
} else if (lowerword == "reflect-unwrap-io-blocks") {
|
||||
ReflectOptions |= EShReflectionUnwrapIOBlocks;
|
||||
} else if (lowerword == "resource-set-bindings" || // synonyms
|
||||
lowerword == "resource-set-binding" ||
|
||||
lowerword == "rsb") {
|
||||
|
@ -1538,6 +1540,8 @@ void usage()
|
|||
" separately to uniforms\n"
|
||||
" --reflect-all-block-variables reflect all variables in blocks, whether\n"
|
||||
" inactive or active\n"
|
||||
" --reflect-unwrap-io-blocks unwrap input/output blocks the same as\n"
|
||||
" uniform blocks\n"
|
||||
" --resource-set-binding [stage] name set binding\n"
|
||||
" set descriptor set and binding for\n"
|
||||
" individual resources\n"
|
||||
|
|
|
@ -14,8 +14,8 @@ Buffer variable reflection:
|
|||
Buffer block reflection:
|
||||
|
||||
Pipeline input reflection:
|
||||
vertin: offset 0, type 1406, size 0, index 0, binding -1, stages 1
|
||||
vertin: offset 0, type 1406, size 1, index 0, binding -1, stages 1
|
||||
|
||||
Pipeline output reflection:
|
||||
fragout: offset 0, type 1406, size 0, index 0, binding -1, stages 16
|
||||
fragout: offset 0, type 1406, size 1, index 0, binding -1, stages 16
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ Buffer variable reflection:
|
|||
Buffer block reflection:
|
||||
|
||||
Pipeline input reflection:
|
||||
inval: offset 0, type 1406, size 0, index 0, binding -1, stages 16
|
||||
inval: offset 0, type 1406, size 1, index 0, binding -1, stages 16
|
||||
|
||||
Pipeline output reflection:
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
reflection.options.geom
|
||||
Uniform reflection:
|
||||
|
||||
Uniform block reflection:
|
||||
|
||||
Buffer variable reflection:
|
||||
|
||||
Buffer block reflection:
|
||||
|
||||
Pipeline input reflection:
|
||||
gl_PerVertex.gl_Position: offset 0, type 8b52, size 1, index 0, binding -1, stages 8
|
||||
gl_PerVertex.gl_PointSize: offset 0, type 1406, size 1, index 0, binding -1, stages 8
|
||||
gl_PerVertex.gl_ClipDistance[0]: offset 0, type 1406, size 1, index 0, binding -1, stages 8
|
||||
block.Color: offset 0, type 8b50, size 1, index 0, binding -1, stages 8
|
||||
block.Texcoord: offset 0, type 8b50, size 1, index 0, binding -1, stages 8
|
||||
block.in_a: offset 0, type 8b54, size 1, index 0, binding -1, stages 8
|
||||
|
||||
Pipeline output reflection:
|
||||
gl_Position: offset 0, type 8b52, size 1, index 0, binding -1, stages 8
|
||||
gl_PointSize: offset 0, type 1406, size 1, index 0, binding -1, stages 8
|
||||
gl_ClipDistance[0]: offset 0, type 1406, size 1, index 0, binding -1, stages 8
|
||||
block.Color: offset 0, type 8b52, size 1, index 0, binding -1, stages 8
|
||||
block.a: offset 0, type 8b52, size 1, index 0, binding -1, stages 8
|
||||
block.b[0]: offset 0, type 8b50, size 3, index 0, binding -1, stages 8
|
||||
|
|
@ -33,8 +33,11 @@ VertexCollection: offset -1, type ffffffff, size 400, index -1, binding -1, stag
|
|||
MultipleArrays: offset -1, type ffffffff, size 500, index -1, binding -1, stages 1, numMembers 9
|
||||
|
||||
Pipeline input reflection:
|
||||
gl_InstanceID: offset 0, type 1404, size 0, index 0, binding -1, stages 1
|
||||
gl_InstanceID: offset 0, type 1404, size 1, index 0, binding -1, stages 1
|
||||
|
||||
Pipeline output reflection:
|
||||
outval: offset 0, type 1406, size 0, index 0, binding -1, stages 1
|
||||
outval.val: offset 0, type 1406, size 1, index 0, binding -1, stages 1
|
||||
outval.a: offset 0, type 8b51, size 1, index 0, binding -1, stages 1
|
||||
outval.b[0]: offset 0, type 8b50, size 4, index 0, binding -1, stages 1
|
||||
outval.c: offset 0, type 8b5a, size 1, index 0, binding -1, stages 1
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#version 330 core
|
||||
|
||||
precision highp float;
|
||||
|
||||
layout(triangles) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
in block
|
||||
{
|
||||
vec2 Color;
|
||||
vec2 Texcoord;
|
||||
flat ivec3 in_a;
|
||||
} In[];
|
||||
|
||||
out block
|
||||
{
|
||||
vec4 Color;
|
||||
vec4 a;
|
||||
vec2 b[3];
|
||||
} Out;
|
||||
|
||||
void main()
|
||||
{
|
||||
for(int i = 0; i < gl_in.length(); ++i)
|
||||
{
|
||||
gl_Position = gl_in[i].gl_Position;
|
||||
Out.Color = vec4(In[i].Color, 0, 1);
|
||||
EmitVertex();
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
|
@ -26,7 +26,14 @@ uniform UBO {
|
|||
uvec4 unused;
|
||||
} ubo;
|
||||
|
||||
out float outval;
|
||||
struct OutputStruct {
|
||||
float val;
|
||||
vec3 a;
|
||||
vec2 b[4];
|
||||
mat2x2 c;
|
||||
};
|
||||
|
||||
out OutputStruct outval;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -40,5 +47,5 @@ void main()
|
|||
f += ubo.verts[gl_InstanceID].position[0];
|
||||
f += ubo.flt[gl_InstanceID];
|
||||
TriangleInfo tlocal[5] = t;
|
||||
outval = f;
|
||||
outval.val = f;
|
||||
}
|
||||
|
|
|
@ -32,15 +32,17 @@ diff -b $BASEDIR/badMacroArgs.frag.out $TARGETDIR/badMacroArgs.frag.out || HASER
|
|||
echo Running reflection...
|
||||
$EXE -l -q -C reflection.vert > $TARGETDIR/reflection.vert.out
|
||||
diff -b $BASEDIR/reflection.vert.out $TARGETDIR/reflection.vert.out || HASERROR=1
|
||||
$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables reflection.options.vert > $TARGETDIR/reflection.options.vert.out
|
||||
$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks reflection.options.vert > $TARGETDIR/reflection.options.vert.out
|
||||
diff -b $BASEDIR/reflection.options.vert.out $TARGETDIR/reflection.options.vert.out || HASERROR=1
|
||||
$EXE -l -q -C reflection.frag > $TARGETDIR/reflection.frag.out
|
||||
diff -b $BASEDIR/reflection.frag.out $TARGETDIR/reflection.frag.out || HASERROR=1
|
||||
$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables reflection.frag > $TARGETDIR/reflection.options.frag.out
|
||||
$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks reflection.frag > $TARGETDIR/reflection.options.frag.out
|
||||
diff -b $BASEDIR/reflection.options.frag.out $TARGETDIR/reflection.options.frag.out || HASERROR=1
|
||||
$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks reflection.options.geom > $TARGETDIR/reflection.options.geom.out
|
||||
diff -b $BASEDIR/reflection.options.geom.out $TARGETDIR/reflection.options.geom.out || HASERROR=1
|
||||
$EXE -l -q -C reflection.linked.vert reflection.linked.frag > $TARGETDIR/reflection.linked.out
|
||||
diff -b $BASEDIR/reflection.linked.out $TARGETDIR/reflection.linked.out || HASERROR=1
|
||||
$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables reflection.linked.vert reflection.linked.frag > $TARGETDIR/reflection.linked.options.out
|
||||
$EXE -l -q -C --reflect-strict-array-suffix --reflect-basic-array-suffix --reflect-intermediate-io --reflect-separate-buffers --reflect-all-block-variables --reflect-unwrap-io-blocks reflection.linked.vert reflection.linked.frag > $TARGETDIR/reflection.linked.options.out
|
||||
diff -b $BASEDIR/reflection.linked.options.out $TARGETDIR/reflection.linked.options.out || HASERROR=1
|
||||
$EXE -D -Od -e flizv -l -q -C -V -Od hlsl.reflection.vert > $TARGETDIR/hlsl.reflection.vert.out
|
||||
diff -b $BASEDIR/hlsl.reflection.vert.out $TARGETDIR/hlsl.reflection.vert.out || HASERROR=1
|
||||
|
|
|
@ -98,46 +98,46 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void addPipeInput(const TIntermSymbol& base)
|
||||
void addPipeIOVariable(const TIntermSymbol& base)
|
||||
{
|
||||
if (processedDerefs.find(&base) == processedDerefs.end()) {
|
||||
processedDerefs.insert(&base);
|
||||
|
||||
const TString &name = base.getName();
|
||||
const TType &type = base.getType();
|
||||
const bool input = base.getQualifier().isPipeInput();
|
||||
|
||||
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
|
||||
if (it == reflection.nameToIndex.end()) {
|
||||
reflection.nameToIndex[name.c_str()] = (int)reflection.indexToPipeInput.size();
|
||||
reflection.indexToPipeInput.push_back(TObjectReflection(name.c_str(), type, 0, mapToGlType(type), 0, 0));
|
||||
TReflection::TMapIndexToReflection &ioItems =
|
||||
input ? reflection.indexToPipeInput : reflection.indexToPipeOutput;
|
||||
|
||||
EShLanguageMask& stages = reflection.indexToPipeInput.back().stages;
|
||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
||||
if (reflection.options & EShReflectionUnwrapIOBlocks) {
|
||||
bool anonymous = IsAnonymous(name);
|
||||
|
||||
TString baseName;
|
||||
if (type.getBasicType() == EbtBlock) {
|
||||
baseName = anonymous ? TString() : type.getTypeName();
|
||||
} else {
|
||||
baseName = anonymous ? TString() : name;
|
||||
}
|
||||
|
||||
// by convention if this is an arrayed block we ignore the array in the reflection
|
||||
if (type.isArray()) {
|
||||
blowUpIOAggregate(input, baseName, TType(type, 0));
|
||||
} else {
|
||||
blowUpIOAggregate(input, baseName, type);
|
||||
}
|
||||
} else {
|
||||
EShLanguageMask& stages = reflection.indexToPipeInput[it->second].stages;
|
||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
||||
}
|
||||
}
|
||||
}
|
||||
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
|
||||
if (it == reflection.nameToIndex.end()) {
|
||||
reflection.nameToIndex[name.c_str()] = (int)ioItems.size();
|
||||
ioItems.push_back(TObjectReflection(name.c_str(), type, 0, mapToGlType(type), 0, 0));
|
||||
|
||||
void addPipeOutput(const TIntermSymbol& base)
|
||||
{
|
||||
if (processedDerefs.find(&base) == processedDerefs.end()) {
|
||||
processedDerefs.insert(&base);
|
||||
|
||||
const TString &name = base.getName();
|
||||
const TType &type = base.getType();
|
||||
|
||||
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
|
||||
if (it == reflection.nameToIndex.end()) {
|
||||
reflection.nameToIndex[name.c_str()] = (int)reflection.indexToPipeOutput.size();
|
||||
reflection.indexToPipeOutput.push_back(TObjectReflection(name.c_str(), type, 0, mapToGlType(type), 0, 0));
|
||||
|
||||
EShLanguageMask& stages = reflection.indexToPipeOutput.back().stages;
|
||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
||||
} else {
|
||||
EShLanguageMask& stages = reflection.indexToPipeOutput[it->second].stages;
|
||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
||||
EShLanguageMask& stages = ioItems.back().stages;
|
||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
||||
} else {
|
||||
EShLanguageMask& stages = ioItems[it->second].stages;
|
||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -473,6 +473,67 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// similar to blowUpActiveAggregate, but with simpler rules and no dereferences to follow.
|
||||
void blowUpIOAggregate(bool input, const TString &baseName, const TType &type)
|
||||
{
|
||||
TString name = baseName;
|
||||
|
||||
// if the type is still too coarse a granularity, this is still an aggregate to expand, expand it...
|
||||
if (! isReflectionGranularity(type)) {
|
||||
if (type.isArray()) {
|
||||
// Visit all the indices of this array, and for each one,
|
||||
// fully explode the remaining aggregate to dereference
|
||||
for (int i = 0; i < std::max(type.getOuterArraySize(), 1); ++i) {
|
||||
TString newBaseName = name;
|
||||
newBaseName.append(TString("[") + String(i) + "]");
|
||||
TType derefType(type, 0);
|
||||
|
||||
blowUpIOAggregate(input, newBaseName, derefType);
|
||||
}
|
||||
} else {
|
||||
// Visit all members of this aggregate, and for each one,
|
||||
// fully explode the remaining aggregate to dereference
|
||||
const TTypeList& typeList = *type.getStruct();
|
||||
|
||||
for (int i = 0; i < (int)typeList.size(); ++i) {
|
||||
TString newBaseName = name;
|
||||
if (newBaseName.size() > 0)
|
||||
newBaseName.append(".");
|
||||
newBaseName.append(typeList[i].type->getFieldName());
|
||||
TType derefType(type, i);
|
||||
|
||||
blowUpIOAggregate(input, newBaseName, derefType);
|
||||
}
|
||||
}
|
||||
|
||||
// it was all completed in the recursive calls above
|
||||
return;
|
||||
}
|
||||
|
||||
if ((reflection.options & EShReflectionBasicArraySuffix) && type.isArray()) {
|
||||
name.append(TString("[0]"));
|
||||
}
|
||||
|
||||
TReflection::TMapIndexToReflection &ioItems =
|
||||
input ? reflection.indexToPipeInput : reflection.indexToPipeOutput;
|
||||
|
||||
std::string namespacedName = input ? "in " : "out ";
|
||||
namespacedName += name.c_str();
|
||||
|
||||
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(namespacedName);
|
||||
if (it == reflection.nameToIndex.end()) {
|
||||
reflection.nameToIndex[namespacedName] = (int)ioItems.size();
|
||||
ioItems.push_back(
|
||||
TObjectReflection(name.c_str(), type, 0, mapToGlType(type), mapToGlArraySize(type), 0));
|
||||
|
||||
EShLanguageMask& stages = ioItems.back().stages;
|
||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
||||
} else {
|
||||
EShLanguageMask& stages = ioItems[it->second].stages;
|
||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
||||
}
|
||||
}
|
||||
|
||||
// Add a uniform dereference where blocks/struct/arrays are involved in the access.
|
||||
// Handles the situation where the left node is at the correct or too coarse a
|
||||
|
@ -1027,11 +1088,9 @@ void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
|
|||
if (base->getQualifier().storage == EvqUniform)
|
||||
addUniform(*base);
|
||||
|
||||
if (intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput())
|
||||
addPipeInput(*base);
|
||||
|
||||
if (intermediate.getStage() == reflection.lastStage && base->getQualifier().isPipeOutput())
|
||||
addPipeOutput(*base);
|
||||
if ((intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput()) ||
|
||||
(intermediate.getStage() == reflection.lastStage && base->getQualifier().isPipeOutput()))
|
||||
addPipeIOVariable(*base);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -246,6 +246,7 @@ typedef enum {
|
|||
EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader
|
||||
EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately
|
||||
EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive
|
||||
EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks
|
||||
} EShReflectionOptions;
|
||||
|
||||
//
|
||||
|
|
Загрузка…
Ссылка в новой задаче