mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-03 14:09:33 +03:00
Vulkan: Separate out XFB data from ShaderInterfaceVariableInfo
Right now the transform feedback data is embedded in the ShaderInterfaceVariableInfo. This caused ShaderInterfaceVariableInfo becomes non-trivial copy-able. This CL moves transform feedback related data out and into its own array, and entire vector of ShaderInterfaceVariableInfo is now memcpied. Further, most programs don't use transform feedback. Right now because transform feedback data is embedded in the ShaderInterfaceVariableInfo, it bloated the size of ShaderInterfaceVariableInfo even if you do not use XFB. This CL makes transform feedback variable info data a std::unique_ptr so that if not used, it is just a nullptr. When we load/save the structure, the ones that has nullptr gets skipped. Bug: b/296433003 Change-Id: I61940a683611717ab0445fcbf44b89b1b7166ee4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4799344 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Roman Lavrov <romanl@google.com>
This commit is contained in:
committed by
Angle LUCI CQ
parent
60b56591de
commit
014e584f75
@@ -99,6 +99,7 @@ class BinaryInputStream : angle::NonCopyable
|
||||
void readBool(bool *outValue) { *outValue = readBool(); }
|
||||
|
||||
void readBytes(unsigned char outArray[], size_t count) { read<unsigned char>(outArray, count); }
|
||||
const unsigned char *getBytes(size_t count) { return read<unsigned char>(nullptr, count); }
|
||||
|
||||
std::string readString()
|
||||
{
|
||||
@@ -171,7 +172,7 @@ class BinaryInputStream : angle::NonCopyable
|
||||
size_t mLength;
|
||||
|
||||
template <typename T>
|
||||
void read(T *v, size_t num)
|
||||
const uint8_t *read(T *v, size_t num)
|
||||
{
|
||||
static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
|
||||
|
||||
@@ -180,7 +181,7 @@ class BinaryInputStream : angle::NonCopyable
|
||||
if (!checkedLength.IsValid())
|
||||
{
|
||||
mError = true;
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
angle::CheckedNumeric<size_t> checkedOffset(mOffset);
|
||||
@@ -189,11 +190,17 @@ class BinaryInputStream : angle::NonCopyable
|
||||
if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mLength)
|
||||
{
|
||||
mError = true;
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memcpy(v, mData + mOffset, checkedLength.ValueOrDie());
|
||||
const uint8_t *srcBytes = mData + mOffset;
|
||||
if (v != nullptr)
|
||||
{
|
||||
memcpy(v, srcBytes, checkedLength.ValueOrDie());
|
||||
}
|
||||
mOffset = checkedOffset.ValueOrDie();
|
||||
|
||||
return srcBytes;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -151,6 +151,7 @@ class FastVector final
|
||||
const_reference back() const;
|
||||
|
||||
void swap(FastVector<T, N, Storage> &other);
|
||||
void resetWithRawData(size_type count, const uint8_t *data);
|
||||
|
||||
void resize(size_type count);
|
||||
void resize(size_type count, const value_type &value);
|
||||
@@ -449,6 +450,16 @@ void FastVector<T, N, Storage>::swap(FastVector<T, N, Storage> &other)
|
||||
std::swap(mFixedStorage, other.mFixedStorage);
|
||||
}
|
||||
|
||||
template <class T, size_t N, class Storage>
|
||||
void FastVector<T, N, Storage>::resetWithRawData(size_type count, const uint8_t *data)
|
||||
{
|
||||
static_assert(std::is_trivially_copyable<value_type>(),
|
||||
"This is a special method for trivially copyable types.");
|
||||
ASSERT(count > 0 && data != nullptr);
|
||||
resize_impl(count);
|
||||
std::memcpy(mData, data, count * sizeof(value_type));
|
||||
}
|
||||
|
||||
template <class T, size_t N, class Storage>
|
||||
ANGLE_INLINE void FastVector<T, N, Storage>::resize(size_type count)
|
||||
{
|
||||
@@ -614,6 +625,11 @@ class FastMap final
|
||||
|
||||
void clear() { mData.clear(); }
|
||||
|
||||
void resetWithRawData(size_type count, const uint8_t *data)
|
||||
{
|
||||
mData.resetWithRawData(count, data);
|
||||
}
|
||||
|
||||
bool empty() const { return mData.empty(); }
|
||||
size_t size() const { return mData.size(); }
|
||||
|
||||
|
||||
@@ -208,6 +208,27 @@ TEST(FastVector, Resize)
|
||||
EXPECT_EQ(2u, vec.size());
|
||||
}
|
||||
|
||||
// Test resetWithRawData on the vector
|
||||
TEST(FastVector, resetWithRawData)
|
||||
{
|
||||
FastVector<int, 5> vec;
|
||||
int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
|
||||
vec.resetWithRawData(9, reinterpret_cast<uint8_t *>(&data[0]));
|
||||
EXPECT_EQ(9u, vec.size());
|
||||
for (size_t i = 0; i < vec.size(); i++)
|
||||
{
|
||||
EXPECT_EQ(vec[i], data[i]);
|
||||
}
|
||||
|
||||
vec.resetWithRawData(4, reinterpret_cast<uint8_t *>(&data[0]));
|
||||
EXPECT_EQ(4u, vec.size());
|
||||
for (size_t i = 0; i < vec.size(); i++)
|
||||
{
|
||||
EXPECT_EQ(vec[i], data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Test iterating over the vector
|
||||
TEST(FastVector, Iteration)
|
||||
{
|
||||
|
||||
@@ -66,6 +66,7 @@ ShaderInterfaceVariableInfoMap::~ShaderInterfaceVariableInfoMap() = default;
|
||||
void ShaderInterfaceVariableInfoMap::clear()
|
||||
{
|
||||
mData.clear();
|
||||
mXFBData.clear();
|
||||
for (gl::ShaderType shaderType : gl::AllShaderTypes())
|
||||
{
|
||||
mIdToIndexMap[shaderType].clear();
|
||||
@@ -78,36 +79,43 @@ void ShaderInterfaceVariableInfoMap::clear()
|
||||
|
||||
void ShaderInterfaceVariableInfoMap::save(gl::BinaryOutputStream *stream)
|
||||
{
|
||||
for (gl::ShaderType shaderType : gl::AllShaderTypes())
|
||||
for (const IdToIndexMap &idToIndexMap : mIdToIndexMap)
|
||||
{
|
||||
stream->writeInt(mIdToIndexMap[shaderType].size());
|
||||
for (const VariableIndex &variableIndex : mIdToIndexMap[shaderType])
|
||||
stream->writeInt(idToIndexMap.size());
|
||||
if (idToIndexMap.size() > 0)
|
||||
{
|
||||
stream->writeInt(variableIndex.index);
|
||||
stream->writeBytes(reinterpret_cast<const uint8_t *>(idToIndexMap.data()),
|
||||
idToIndexMap.size() * sizeof(*idToIndexMap.data()));
|
||||
}
|
||||
}
|
||||
|
||||
stream->writeInt(mData.size());
|
||||
for (const ShaderInterfaceVariableInfo &info : mData)
|
||||
stream->writeVector(mData);
|
||||
|
||||
ASSERT(mXFBData.size() <= mData.size());
|
||||
size_t xfbInfoCount = 0;
|
||||
for (const XFBVariableInfoPtr &info : mXFBData)
|
||||
{
|
||||
stream->writeInt(info.descriptorSet);
|
||||
stream->writeInt(info.binding);
|
||||
stream->writeInt(info.location);
|
||||
stream->writeInt(info.component);
|
||||
stream->writeInt(info.index);
|
||||
// PackedEnumBitSet uses uint8_t
|
||||
stream->writeInt(info.activeStages.bits());
|
||||
if (!info)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
xfbInfoCount++;
|
||||
}
|
||||
stream->writeInt(xfbInfoCount);
|
||||
for (size_t xfbIndex = 0; xfbIndex < mXFBData.size(); xfbIndex++)
|
||||
{
|
||||
if (!mXFBData[xfbIndex])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
stream->writeInt(xfbIndex);
|
||||
XFBInterfaceVariableInfo &info = *mXFBData[xfbIndex];
|
||||
SaveShaderInterfaceVariableXfbInfo(info.xfb, stream);
|
||||
stream->writeInt(info.fieldXfb.size());
|
||||
for (const ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
|
||||
{
|
||||
SaveShaderInterfaceVariableXfbInfo(xfb, stream);
|
||||
}
|
||||
stream->writeBool(info.useRelaxedPrecision);
|
||||
stream->writeBool(info.varyingIsInput);
|
||||
stream->writeBool(info.varyingIsOutput);
|
||||
stream->writeInt(info.attributeComponentCount);
|
||||
stream->writeInt(info.attributeLocationCount);
|
||||
}
|
||||
|
||||
// Store gl_PerVertex members only for stages that have it.
|
||||
@@ -121,46 +129,41 @@ void ShaderInterfaceVariableInfoMap::save(gl::BinaryOutputStream *stream)
|
||||
}
|
||||
void ShaderInterfaceVariableInfoMap::load(gl::BinaryInputStream *stream)
|
||||
{
|
||||
ShaderInterfaceVariableInfoMap::VariableInfoArray data;
|
||||
gl::ShaderMap<ShaderInterfaceVariableInfoMap::IdToIndexMap> idToIndexMap;
|
||||
gl::ShaderMap<gl::PerVertexMemberBitSet> inputPerVertexActiveMembers;
|
||||
gl::ShaderMap<gl::PerVertexMemberBitSet> outputPerVertexActiveMembers;
|
||||
|
||||
for (gl::ShaderType shaderType : gl::AllShaderTypes())
|
||||
for (IdToIndexMap &idToIndexMap : mIdToIndexMap)
|
||||
{
|
||||
size_t idCount = stream->readInt<size_t>();
|
||||
for (uint32_t id = 0; id < idCount; ++id)
|
||||
// ASSERT(idToIndexMap.empty());
|
||||
size_t count = stream->readInt<size_t>();
|
||||
if (count > 0)
|
||||
{
|
||||
uint32_t index = stream->readInt<uint32_t>();
|
||||
idToIndexMap[shaderType][id] = {index};
|
||||
idToIndexMap.resetWithRawData(count,
|
||||
stream->getBytes(count * sizeof(*idToIndexMap.data())));
|
||||
}
|
||||
}
|
||||
|
||||
size_t dataSize = stream->readInt<size_t>();
|
||||
for (size_t infoIndex = 0; infoIndex < dataSize; ++infoIndex)
|
||||
stream->readVector(&mData);
|
||||
|
||||
ASSERT(mXFBData.empty());
|
||||
size_t xfbInfoCount = stream->readInt<size_t>();
|
||||
ASSERT(xfbInfoCount <= mData.size());
|
||||
if (xfbInfoCount > 0)
|
||||
{
|
||||
ShaderInterfaceVariableInfo info;
|
||||
|
||||
info.descriptorSet = stream->readInt<uint32_t>();
|
||||
info.binding = stream->readInt<uint32_t>();
|
||||
info.location = stream->readInt<uint32_t>();
|
||||
info.component = stream->readInt<uint32_t>();
|
||||
info.index = stream->readInt<uint32_t>();
|
||||
// PackedEnumBitSet uses uint8_t
|
||||
info.activeStages = gl::ShaderBitSet(stream->readInt<uint8_t>());
|
||||
LoadShaderInterfaceVariableXfbInfo(stream, &info.xfb);
|
||||
info.fieldXfb.resize(stream->readInt<size_t>());
|
||||
for (ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
|
||||
mXFBData.resize(mData.size());
|
||||
for (size_t i = 0; i < xfbInfoCount; ++i)
|
||||
{
|
||||
LoadShaderInterfaceVariableXfbInfo(stream, &xfb);
|
||||
}
|
||||
info.useRelaxedPrecision = stream->readBool();
|
||||
info.varyingIsInput = stream->readBool();
|
||||
info.varyingIsOutput = stream->readBool();
|
||||
info.attributeComponentCount = stream->readInt<uint8_t>();
|
||||
info.attributeLocationCount = stream->readInt<uint8_t>();
|
||||
size_t xfbIndex = stream->readInt<size_t>();
|
||||
mXFBData[xfbIndex] = std::make_unique<XFBInterfaceVariableInfo>();
|
||||
|
||||
data.push_back(info);
|
||||
XFBInterfaceVariableInfo &info = *mXFBData[xfbIndex];
|
||||
LoadShaderInterfaceVariableXfbInfo(stream, &info.xfb);
|
||||
info.fieldXfb.resize(stream->readInt<size_t>());
|
||||
for (ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
|
||||
{
|
||||
LoadShaderInterfaceVariableXfbInfo(stream, &xfb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outputPerVertexActiveMembers[gl::ShaderType::Vertex] =
|
||||
@@ -178,8 +181,6 @@ void ShaderInterfaceVariableInfoMap::load(gl::BinaryInputStream *stream)
|
||||
outputPerVertexActiveMembers[gl::ShaderType::Geometry] =
|
||||
gl::PerVertexMemberBitSet(stream->readInt<uint8_t>());
|
||||
|
||||
mData.swap(data);
|
||||
mIdToIndexMap.swap(idToIndexMap);
|
||||
mInputPerVertexActiveMembers.swap(inputPerVertexActiveMembers);
|
||||
mOutputPerVertexActiveMembers.swap(outputPerVertexActiveMembers);
|
||||
}
|
||||
@@ -227,6 +228,23 @@ ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::getMutable(gl::Shad
|
||||
return mData[index];
|
||||
}
|
||||
|
||||
XFBInterfaceVariableInfo *ShaderInterfaceVariableInfoMap::getXFBMutable(gl::ShaderType shaderType,
|
||||
uint32_t id)
|
||||
{
|
||||
ASSERT(hasVariable(shaderType, id));
|
||||
uint32_t index = getVariableIndex(shaderType, id).index;
|
||||
if (index >= mXFBData.size())
|
||||
{
|
||||
mXFBData.resize(index + 1);
|
||||
}
|
||||
if (!mXFBData[index])
|
||||
{
|
||||
mXFBData[index] = std::make_unique<XFBInterfaceVariableInfo>();
|
||||
}
|
||||
mData[index].hasTransformFeedback = true;
|
||||
return mXFBData[index].get();
|
||||
}
|
||||
|
||||
ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::add(gl::ShaderType shaderType,
|
||||
uint32_t id)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,8 @@ class ShaderInterfaceVariableInfoMap final : angle::NonCopyable
|
||||
public:
|
||||
// For each interface variable, a ShaderInterfaceVariableInfo is created. These are stored in a
|
||||
// flat array.
|
||||
using VariableInfoArray = std::vector<ShaderInterfaceVariableInfo>;
|
||||
using VariableInfoArray = std::vector<ShaderInterfaceVariableInfo>;
|
||||
using XFBVariableInfoArray = std::vector<XFBVariableInfoPtr>;
|
||||
|
||||
// Each interface variable has an associted SPIR-V id (which is different per shader type).
|
||||
// The following map is from a SPIR-V id to its associated info in VariableInfoArray.
|
||||
@@ -62,6 +63,7 @@ class ShaderInterfaceVariableInfoMap final : angle::NonCopyable
|
||||
void setOutputPerVertexActiveMembers(gl::ShaderType shaderType,
|
||||
gl::PerVertexMemberBitSet activeMembers);
|
||||
ShaderInterfaceVariableInfo &getMutable(gl::ShaderType shaderType, uint32_t id);
|
||||
XFBInterfaceVariableInfo *getXFBMutable(gl::ShaderType shaderType, uint32_t id);
|
||||
|
||||
const ShaderInterfaceVariableInfo &getDefaultUniformInfo(gl::ShaderType shaderType) const;
|
||||
const ShaderInterfaceVariableInfo &getAtomicCounterInfo(gl::ShaderType shaderType) const;
|
||||
@@ -78,6 +80,14 @@ class ShaderInterfaceVariableInfoMap final : angle::NonCopyable
|
||||
uint32_t id) const;
|
||||
const VariableInfoArray &getData() const { return mData; }
|
||||
const gl::ShaderMap<IdToIndexMap> &getIdToIndexMap() const { return mIdToIndexMap; }
|
||||
const XFBInterfaceVariableInfo &getXFBDataForVariableInfo(
|
||||
const ShaderInterfaceVariableInfo *info) const
|
||||
{
|
||||
size_t index = info - mData.data();
|
||||
ASSERT(index < mXFBData.size());
|
||||
ASSERT(mXFBData[index]);
|
||||
return *mXFBData[index];
|
||||
}
|
||||
const gl::ShaderMap<gl::PerVertexMemberBitSet> &getInputPerVertexActiveMembers() const
|
||||
{
|
||||
return mInputPerVertexActiveMembers;
|
||||
@@ -95,6 +105,8 @@ class ShaderInterfaceVariableInfoMap final : angle::NonCopyable
|
||||
const VariableIndex &getVariableIndex(gl::ShaderType shaderType, uint32_t id) const;
|
||||
|
||||
VariableInfoArray mData;
|
||||
// Transform feedback array will be empty if no XFB is used.
|
||||
XFBVariableInfoArray mXFBData;
|
||||
gl::ShaderMap<IdToIndexMap> mIdToIndexMap;
|
||||
|
||||
// Active members of `in gl_PerVertex` and `out gl_PerVertex`
|
||||
|
||||
@@ -158,29 +158,31 @@ void AddVaryingLocationInfo(ShaderInterfaceVariableInfoMap *infoMap,
|
||||
}
|
||||
|
||||
// Modify an existing out variable and add transform feedback information.
|
||||
ShaderInterfaceVariableInfo *SetXfbInfo(ShaderInterfaceVariableInfoMap *infoMap,
|
||||
gl::ShaderType shaderType,
|
||||
uint32_t varId,
|
||||
int fieldIndex,
|
||||
uint32_t xfbBuffer,
|
||||
uint32_t xfbOffset,
|
||||
uint32_t xfbStride,
|
||||
uint32_t arraySize,
|
||||
uint32_t columnCount,
|
||||
uint32_t rowCount,
|
||||
uint32_t arrayIndex,
|
||||
GLenum componentType)
|
||||
void SetXfbInfo(ShaderInterfaceVariableInfoMap *infoMap,
|
||||
gl::ShaderType shaderType,
|
||||
uint32_t varId,
|
||||
int fieldIndex,
|
||||
uint32_t xfbBuffer,
|
||||
uint32_t xfbOffset,
|
||||
uint32_t xfbStride,
|
||||
uint32_t arraySize,
|
||||
uint32_t columnCount,
|
||||
uint32_t rowCount,
|
||||
uint32_t arrayIndex,
|
||||
GLenum componentType)
|
||||
{
|
||||
ShaderInterfaceVariableInfo &info = infoMap->getMutable(shaderType, varId);
|
||||
ShaderInterfaceVariableXfbInfo *xfb = &info.xfb;
|
||||
XFBInterfaceVariableInfo *info = infoMap->getXFBMutable(shaderType, varId);
|
||||
ASSERT(info != nullptr);
|
||||
|
||||
ShaderInterfaceVariableXfbInfo *xfb = &info->xfb;
|
||||
|
||||
if (fieldIndex >= 0)
|
||||
{
|
||||
if (info.fieldXfb.size() <= static_cast<size_t>(fieldIndex))
|
||||
if (info->fieldXfb.size() <= static_cast<size_t>(fieldIndex))
|
||||
{
|
||||
info.fieldXfb.resize(fieldIndex + 1);
|
||||
info->fieldXfb.resize(fieldIndex + 1);
|
||||
}
|
||||
xfb = &info.fieldXfb[fieldIndex];
|
||||
xfb = &info->fieldXfb[fieldIndex];
|
||||
}
|
||||
|
||||
ASSERT(xfb->buffer == ShaderInterfaceVariableXfbInfo::kInvalid);
|
||||
@@ -201,8 +203,6 @@ ShaderInterfaceVariableInfo *SetXfbInfo(ShaderInterfaceVariableInfoMap *infoMap,
|
||||
xfb->rowCount = rowCount;
|
||||
xfb->arrayIndex = arrayIndex;
|
||||
xfb->componentType = componentType;
|
||||
|
||||
return &info;
|
||||
}
|
||||
|
||||
void AssignTransformFeedbackEmulationBindings(gl::ShaderType shaderType,
|
||||
@@ -1604,6 +1604,7 @@ class SpirvTransformFeedbackCodeGenerator final : angle::NonCopyable
|
||||
{}
|
||||
|
||||
void visitVariable(const ShaderInterfaceVariableInfo &info,
|
||||
const XFBInterfaceVariableInfo &xfbInfo,
|
||||
gl::ShaderType shaderType,
|
||||
spirv::IdResultType typeId,
|
||||
spirv::IdResult id,
|
||||
@@ -1654,15 +1655,15 @@ class SpirvTransformFeedbackCodeGenerator final : angle::NonCopyable
|
||||
const bool usePrecisionFixer,
|
||||
spirv::Blob *blobOut);
|
||||
void addExecutionMode(spirv::IdRef entryPointId, spirv::Blob *blobOut);
|
||||
void addMemberDecorate(const ShaderInterfaceVariableInfo &info,
|
||||
void addMemberDecorate(const XFBInterfaceVariableInfo &info,
|
||||
spirv::IdRef id,
|
||||
spirv::Blob *blobOut);
|
||||
void addDecorate(const ShaderInterfaceVariableInfo &info,
|
||||
void addDecorate(const XFBInterfaceVariableInfo &xfbInfo,
|
||||
spirv::IdRef id,
|
||||
spirv::Blob *blobOut);
|
||||
|
||||
private:
|
||||
void gatherXfbVaryings(const ShaderInterfaceVariableInfo &info, spirv::IdRef id);
|
||||
void gatherXfbVaryings(const XFBInterfaceVariableInfo &info, spirv::IdRef id);
|
||||
void visitXfbVarying(const ShaderInterfaceVariableXfbInfo &xfb,
|
||||
spirv::IdRef baseId,
|
||||
uint32_t fieldIndex);
|
||||
@@ -1741,6 +1742,7 @@ constexpr size_t SpirvTransformFeedbackCodeGenerator::kXfbDecorationCount;
|
||||
constexpr spv::Decoration SpirvTransformFeedbackCodeGenerator::kXfbDecorations[kXfbDecorationCount];
|
||||
|
||||
void SpirvTransformFeedbackCodeGenerator::visitVariable(const ShaderInterfaceVariableInfo &info,
|
||||
const XFBInterfaceVariableInfo &xfbInfo,
|
||||
gl::ShaderType shaderType,
|
||||
spirv::IdResultType typeId,
|
||||
spirv::IdResult id,
|
||||
@@ -1748,13 +1750,14 @@ void SpirvTransformFeedbackCodeGenerator::visitVariable(const ShaderInterfaceVar
|
||||
{
|
||||
if (mIsEmulated)
|
||||
{
|
||||
gatherXfbVaryings(info, id);
|
||||
gatherXfbVaryings(xfbInfo, id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Note if the variable is captured by transform feedback. In that case, the TransformFeedback
|
||||
// capability needs to be added.
|
||||
if ((info.xfb.buffer != ShaderInterfaceVariableInfo::kInvalid || !info.fieldXfb.empty()) &&
|
||||
if ((xfbInfo.xfb.buffer != ShaderInterfaceVariableInfo::kInvalid ||
|
||||
!xfbInfo.fieldXfb.empty()) &&
|
||||
info.activeStages[shaderType])
|
||||
{
|
||||
mHasTransformFeedbackOutput = true;
|
||||
@@ -1922,7 +1925,7 @@ TransformationState SpirvTransformFeedbackCodeGenerator::transformVariable(
|
||||
return TransformationState::Unchanged;
|
||||
}
|
||||
|
||||
void SpirvTransformFeedbackCodeGenerator::gatherXfbVaryings(const ShaderInterfaceVariableInfo &info,
|
||||
void SpirvTransformFeedbackCodeGenerator::gatherXfbVaryings(const XFBInterfaceVariableInfo &info,
|
||||
spirv::IdRef id)
|
||||
{
|
||||
visitXfbVarying(info.xfb, id, ShaderInterfaceVariableXfbInfo::kInvalid);
|
||||
@@ -2411,7 +2414,7 @@ void SpirvTransformFeedbackCodeGenerator::addExecutionMode(spirv::IdRef entryPoi
|
||||
}
|
||||
}
|
||||
|
||||
void SpirvTransformFeedbackCodeGenerator::addMemberDecorate(const ShaderInterfaceVariableInfo &info,
|
||||
void SpirvTransformFeedbackCodeGenerator::addMemberDecorate(const XFBInterfaceVariableInfo &info,
|
||||
spirv::IdRef id,
|
||||
spirv::Blob *blobOut)
|
||||
{
|
||||
@@ -2452,7 +2455,7 @@ void SpirvTransformFeedbackCodeGenerator::addMemberDecorate(const ShaderInterfac
|
||||
}
|
||||
}
|
||||
|
||||
void SpirvTransformFeedbackCodeGenerator::addDecorate(const ShaderInterfaceVariableInfo &info,
|
||||
void SpirvTransformFeedbackCodeGenerator::addDecorate(const XFBInterfaceVariableInfo &info,
|
||||
spirv::IdRef id,
|
||||
spirv::Blob *blobOut)
|
||||
{
|
||||
@@ -3416,9 +3419,12 @@ void SpirvTransformer::visitVariable(const uint32_t *instruction)
|
||||
mVaryingPrecisionFixer.visitVariable(*info, mOptions.shaderType, typeId, id, storageClass,
|
||||
mSpirvBlobOut);
|
||||
}
|
||||
if (mOptions.isTransformFeedbackStage)
|
||||
if (mOptions.isTransformFeedbackStage && mVariableInfoById[id]->hasTransformFeedback)
|
||||
{
|
||||
mXfbCodeGenerator.visitVariable(*info, mOptions.shaderType, typeId, id, storageClass);
|
||||
const XFBInterfaceVariableInfo &xfbInfo =
|
||||
mVariableInfoMap.getXFBDataForVariableInfo(mVariableInfoById[id]);
|
||||
mXfbCodeGenerator.visitVariable(*info, xfbInfo, mOptions.shaderType, typeId, id,
|
||||
storageClass);
|
||||
}
|
||||
|
||||
mMultisampleTransformer.visitVariable(mOptions.shaderType, typeId, id, storageClass);
|
||||
@@ -3517,9 +3523,11 @@ TransformationState SpirvTransformer::transformDecorate(const uint32_t *instruct
|
||||
case spv::DecorationBlock:
|
||||
// If this is the Block decoration of a shader I/O block, add the transform feedback
|
||||
// decorations to its members right away.
|
||||
if (mOptions.isTransformFeedbackStage)
|
||||
if (mOptions.isTransformFeedbackStage && mVariableInfoById[id]->hasTransformFeedback)
|
||||
{
|
||||
mXfbCodeGenerator.addMemberDecorate(*info, id, mSpirvBlobOut);
|
||||
const XFBInterfaceVariableInfo &xfbInfo =
|
||||
mVariableInfoMap.getXFBDataForVariableInfo(mVariableInfoById[id]);
|
||||
mXfbCodeGenerator.addMemberDecorate(xfbInfo, id, mSpirvBlobOut);
|
||||
}
|
||||
break;
|
||||
case spv::DecorationInvariant:
|
||||
@@ -3569,9 +3577,11 @@ TransformationState SpirvTransformer::transformDecorate(const uint32_t *instruct
|
||||
}
|
||||
|
||||
// Add Xfb decorations, if any.
|
||||
if (mOptions.isTransformFeedbackStage)
|
||||
if (mOptions.isTransformFeedbackStage && mVariableInfoById[id]->hasTransformFeedback)
|
||||
{
|
||||
mXfbCodeGenerator.addDecorate(*info, id, mSpirvBlobOut);
|
||||
const XFBInterfaceVariableInfo &xfbInfo =
|
||||
mVariableInfoMap.getXFBDataForVariableInfo(mVariableInfoById[id]);
|
||||
mXfbCodeGenerator.addDecorate(xfbInfo, id, mSpirvBlobOut);
|
||||
}
|
||||
|
||||
return TransformationState::Transformed;
|
||||
|
||||
@@ -74,6 +74,7 @@ struct ShaderInterfaceVariableXfbInfo
|
||||
// Information for each shader interface variable. Not all fields are relevant to each shader
|
||||
// interface variable. For example opaque uniforms require a set and binding index, while vertex
|
||||
// attributes require a location.
|
||||
ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
|
||||
struct ShaderInterfaceVariableInfo
|
||||
{
|
||||
ShaderInterfaceVariableInfo();
|
||||
@@ -90,25 +91,36 @@ struct ShaderInterfaceVariableInfo
|
||||
uint32_t location = kInvalid;
|
||||
uint32_t component = kInvalid;
|
||||
uint32_t index = kInvalid;
|
||||
|
||||
// The stages this shader interface variable is active.
|
||||
gl::ShaderBitSet activeStages;
|
||||
// Used for transform feedback extension to decorate vertex shader output.
|
||||
ShaderInterfaceVariableXfbInfo xfb;
|
||||
std::vector<ShaderInterfaceVariableXfbInfo> fieldXfb;
|
||||
|
||||
// Indicates that the precision needs to be modified in the generated SPIR-V
|
||||
// to support only transferring medium precision data when there's a precision
|
||||
// mismatch between the shaders. For example, either the VS casts highp->mediump
|
||||
// or the FS casts mediump->highp.
|
||||
bool useRelaxedPrecision = false;
|
||||
uint8_t useRelaxedPrecision : 1 = false;
|
||||
// Indicate if varying is input or output, or both (in case of for example gl_Position in a
|
||||
// geometry shader)
|
||||
bool varyingIsInput = false;
|
||||
bool varyingIsOutput = false;
|
||||
uint8_t varyingIsInput : 1 = false;
|
||||
uint8_t varyingIsOutput : 1 = false;
|
||||
uint8_t hasTransformFeedback : 1 = false;
|
||||
uint8_t padding : 4 = 0;
|
||||
|
||||
// For vertex attributes, this is the number of components / locations. These are used by the
|
||||
// vertex attribute aliasing transformation only.
|
||||
uint8_t attributeComponentCount = 0;
|
||||
uint8_t attributeLocationCount = 0;
|
||||
};
|
||||
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
|
||||
|
||||
struct XFBInterfaceVariableInfo
|
||||
{
|
||||
// Used for transform feedback extension to decorate vertex shader output.
|
||||
ShaderInterfaceVariableXfbInfo xfb;
|
||||
std::vector<ShaderInterfaceVariableXfbInfo> fieldXfb;
|
||||
};
|
||||
using XFBVariableInfoPtr = std::unique_ptr<XFBInterfaceVariableInfo>;
|
||||
|
||||
uint32_t SpvGetXfbBufferBlockId(const uint32_t bufferIndex);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user