Commit ee4a5266 by Shahbaz Youssefi Committed by Angle LUCI CQ

Vulkan: SPIR-V Gen: Function calls

This change implements function calls. As a result, transform feedback tests are enabled as well as support for transform feedback emulation (which contains functions and if blocks). `const` and opaque uniform function arguments take intermediate values, while the rest take memory objects. If the argument being passed is an unindexed lvalue, it can be directly given to the function. Otherwise a temporary variable is made which is initialized by the parameter if necessary (in and inout parameters) and later overwrites the parameter if necessary (out and inout parameters). Bug: angleproject:4889 Change-Id: I8976cdd17870c35d5a2daeed3c38de57ada931d9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2930363 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent c1932fb5
...@@ -78,11 +78,13 @@ SpirvType SPIRVBuilder::getSpirvType(const TType &type, TLayoutBlockStorage bloc ...@@ -78,11 +78,13 @@ SpirvType SPIRVBuilder::getSpirvType(const TType &type, TLayoutBlockStorage bloc
// Calculate the block storage from the interface block automatically. The fields inherit // Calculate the block storage from the interface block automatically. The fields inherit
// from this. Default to std140. // from this. Default to std140.
ASSERT(spirvType.blockStorage == EbsUnspecified); if (spirvType.blockStorage == EbsUnspecified)
spirvType.blockStorage = type.getLayoutQualifier().blockStorage;
if (!IsShaderIoBlock(type.getQualifier()) && spirvType.blockStorage != EbsStd430)
{ {
spirvType.blockStorage = EbsStd140; spirvType.blockStorage = type.getLayoutQualifier().blockStorage;
if (!IsShaderIoBlock(type.getQualifier()) && spirvType.blockStorage != EbsStd430)
{
spirvType.blockStorage = EbsStd140;
}
} }
} }
else if (spirvType.arraySizes.empty()) else if (spirvType.arraySizes.empty())
...@@ -151,7 +153,7 @@ spirv::IdRef SPIRVBuilder::getFunctionTypeId(spirv::IdRef returnTypeId, ...@@ -151,7 +153,7 @@ spirv::IdRef SPIRVBuilder::getFunctionTypeId(spirv::IdRef returnTypeId,
{ {
const spirv::IdRef functionTypeId = getNewId(); const spirv::IdRef functionTypeId = getNewId();
spirv::WriteTypeFunction(&mSpirvTypeAndConstantDecls, functionTypeId, returnTypeId, spirv::WriteTypeFunction(&mSpirvFunctionTypeDecls, functionTypeId, returnTypeId,
paramTypeIds); paramTypeIds);
iter = mFunctionTypeIdMap.insert({key, functionTypeId}).first; iter = mFunctionTypeIdMap.insert({key, functionTypeId}).first;
...@@ -180,11 +182,20 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block ...@@ -180,11 +182,20 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block
const spirv::IdRef subTypeId = getSpirvTypeData(subType, "").id; const spirv::IdRef subTypeId = getSpirvTypeData(subType, "").id;
const unsigned int length = type.arraySizes.back(); const unsigned int length = type.arraySizes.back();
const spirv::IdRef lengthId = getUintConstant(length); typeId = getNewId();
typeId = getNewId(); if (length == 0)
spirv::WriteTypeArray(&mSpirvTypeAndConstantDecls, typeId, subTypeId, lengthId); {
// Storage buffers may include a dynamically-sized array, which is identified by it
// having a length of 0.
spirv::WriteTypeRuntimeArray(&mSpirvTypeAndConstantDecls, typeId, subTypeId);
}
else
{
const spirv::IdRef lengthId = getUintConstant(length);
spirv::WriteTypeArray(&mSpirvTypeAndConstantDecls, typeId, subTypeId, lengthId);
}
} }
else if (type.block != nullptr) else if (type.block != nullptr)
{ {
...@@ -781,13 +792,19 @@ spirv::IdRef SPIRVBuilder::getCompositeConstant(spirv::IdRef typeId, const spirv ...@@ -781,13 +792,19 @@ spirv::IdRef SPIRVBuilder::getCompositeConstant(spirv::IdRef typeId, const spirv
return iter->second; return iter->second;
} }
void SPIRVBuilder::startNewFunction() void SPIRVBuilder::startNewFunction(spirv::IdRef functionId, const char *name)
{ {
ASSERT(mSpirvCurrentFunctionBlocks.empty()); ASSERT(mSpirvCurrentFunctionBlocks.empty());
// Add the first block of the function. // Add the first block of the function.
mSpirvCurrentFunctionBlocks.emplace_back(); mSpirvCurrentFunctionBlocks.emplace_back();
mSpirvCurrentFunctionBlocks.back().labelId = getNewId(); mSpirvCurrentFunctionBlocks.back().labelId = getNewId();
// Output debug information.
if (name)
{
spirv::WriteName(&mSpirvDebug, functionId, name);
}
} }
void SPIRVBuilder::assembleSpirvFunctionBlocks() void SPIRVBuilder::assembleSpirvFunctionBlocks()
...@@ -1060,7 +1077,8 @@ uint32_t SPIRVBuilder::calculateBaseAlignmentAndSize(const SpirvType &type, ...@@ -1060,7 +1077,8 @@ uint32_t SPIRVBuilder::calculateBaseAlignmentAndSize(const SpirvType &type,
uint32_t arraySizeProduct = 1; uint32_t arraySizeProduct = 1;
for (uint32_t arraySize : type.arraySizes) for (uint32_t arraySize : type.arraySizes)
{ {
arraySizeProduct *= arraySize; // For runtime arrays, arraySize will be 0 and should be excluded.
arraySizeProduct *= arraySize > 0 ? arraySize : 1;
} }
*sizeInStorageBlockOut = baseTypeData.sizeInStorageBlock * arraySizeProduct; *sizeInStorageBlockOut = baseTypeData.sizeInStorageBlock * arraySizeProduct;
...@@ -1281,8 +1299,8 @@ spirv::Blob SPIRVBuilder::getSpirv() ...@@ -1281,8 +1299,8 @@ spirv::Blob SPIRVBuilder::getSpirv()
// OpExtInstImport, OpEntryPoint etc. // OpExtInstImport, OpEntryPoint etc.
result.reserve(5 + mCapabilities.size() * 2 + mExecutionModes.size() * 3 + mSpirvDebug.size() + result.reserve(5 + mCapabilities.size() * 2 + mExecutionModes.size() * 3 + mSpirvDebug.size() +
mSpirvDecorations.size() + mSpirvTypeAndConstantDecls.size() + mSpirvDecorations.size() + mSpirvTypeAndConstantDecls.size() +
mSpirvTypePointerDecls.size() + mSpirvVariableDecls.size() + mSpirvTypePointerDecls.size() + mSpirvFunctionTypeDecls.size() +
mSpirvFunctions.size()); mSpirvVariableDecls.size() + mSpirvFunctions.size());
// Generate any necessary id before writing the id bound in header. // Generate any necessary id before writing the id bound in header.
const spirv::IdRef extInstImportId = getNewId(); const spirv::IdRef extInstImportId = getNewId();
...@@ -1338,6 +1356,7 @@ spirv::Blob SPIRVBuilder::getSpirv() ...@@ -1338,6 +1356,7 @@ spirv::Blob SPIRVBuilder::getSpirv()
result.insert(result.end(), mSpirvTypeAndConstantDecls.begin(), result.insert(result.end(), mSpirvTypeAndConstantDecls.begin(),
mSpirvTypeAndConstantDecls.end()); mSpirvTypeAndConstantDecls.end());
result.insert(result.end(), mSpirvTypePointerDecls.begin(), mSpirvTypePointerDecls.end()); result.insert(result.end(), mSpirvTypePointerDecls.begin(), mSpirvTypePointerDecls.end());
result.insert(result.end(), mSpirvFunctionTypeDecls.begin(), mSpirvFunctionTypeDecls.end());
result.insert(result.end(), mSpirvVariableDecls.begin(), mSpirvVariableDecls.end()); result.insert(result.end(), mSpirvVariableDecls.begin(), mSpirvVariableDecls.end());
result.insert(result.end(), mSpirvFunctions.begin(), mSpirvFunctions.end()); result.insert(result.end(), mSpirvFunctions.begin(), mSpirvFunctions.end());
......
...@@ -233,6 +233,7 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -233,6 +233,7 @@ class SPIRVBuilder : angle::NonCopyable
spirv::Blob *getSpirvDecorations() { return &mSpirvDecorations; } spirv::Blob *getSpirvDecorations() { return &mSpirvDecorations; }
spirv::Blob *getSpirvTypeAndConstantDecls() { return &mSpirvTypeAndConstantDecls; } spirv::Blob *getSpirvTypeAndConstantDecls() { return &mSpirvTypeAndConstantDecls; }
spirv::Blob *getSpirvTypePointerDecls() { return &mSpirvTypePointerDecls; } spirv::Blob *getSpirvTypePointerDecls() { return &mSpirvTypePointerDecls; }
spirv::Blob *getSpirvFunctionTypeDecls() { return &mSpirvFunctionTypeDecls; }
spirv::Blob *getSpirvVariableDecls() { return &mSpirvVariableDecls; } spirv::Blob *getSpirvVariableDecls() { return &mSpirvVariableDecls; }
spirv::Blob *getSpirvFunctions() { return &mSpirvFunctions; } spirv::Blob *getSpirvFunctions() { return &mSpirvFunctions; }
spirv::Blob *getSpirvCurrentFunctionBlock() spirv::Blob *getSpirvCurrentFunctionBlock()
...@@ -272,7 +273,7 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -272,7 +273,7 @@ class SPIRVBuilder : angle::NonCopyable
spirv::IdRef getCompositeConstant(spirv::IdRef typeId, const spirv::IdRefList &values); spirv::IdRef getCompositeConstant(spirv::IdRef typeId, const spirv::IdRefList &values);
// Helpers to start and end a function. // Helpers to start and end a function.
void startNewFunction(); void startNewFunction(spirv::IdRef functionId, const char *name);
void assembleSpirvFunctionBlocks(); void assembleSpirvFunctionBlocks();
// Helper to declare a variable. Function-local variables must be placed in the first block of // Helper to declare a variable. Function-local variables must be placed in the first block of
...@@ -352,6 +353,7 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -352,6 +353,7 @@ class SPIRVBuilder : angle::NonCopyable
spirv::Blob mSpirvDecorations; spirv::Blob mSpirvDecorations;
spirv::Blob mSpirvTypeAndConstantDecls; spirv::Blob mSpirvTypeAndConstantDecls;
spirv::Blob mSpirvTypePointerDecls; spirv::Blob mSpirvTypePointerDecls;
spirv::Blob mSpirvFunctionTypeDecls;
spirv::Blob mSpirvVariableDecls; spirv::Blob mSpirvVariableDecls;
spirv::Blob mSpirvFunctions; spirv::Blob mSpirvFunctions;
// A list of blocks created for the current function. These are assembled by // A list of blocks created for the current function. These are assembled by
......
...@@ -390,9 +390,11 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler, ...@@ -390,9 +390,11 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler,
constexpr uint32_t kMaxXfbBuffers = 4; constexpr uint32_t kMaxXfbBuffers = 4;
const TType *ivec4Type = StaticType::GetBasic<EbtInt, kMaxXfbBuffers>(); const TType *ivec4Type = StaticType::GetBasic<EbtInt, kMaxXfbBuffers>();
TType *stridesType = new TType(*ivec4Type);
stridesType->setQualifier(EvqConst);
// Create the parameter variable. // Create the parameter variable.
TVariable *stridesVar = new TVariable(symbolTable, ImmutableString("strides"), ivec4Type, TVariable *stridesVar = new TVariable(symbolTable, ImmutableString("strides"), stridesType,
SymbolType::AngleInternal); SymbolType::AngleInternal);
TIntermSymbol *stridesSymbol = new TIntermSymbol(stridesVar); TIntermSymbol *stridesSymbol = new TIntermSymbol(stridesVar);
...@@ -479,10 +481,8 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler, ...@@ -479,10 +481,8 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler,
// Create a call to ANGLEGetXfbOffsets too, for the sole purpose of preventing it from being // Create a call to ANGLEGetXfbOffsets too, for the sole purpose of preventing it from being
// culled as unused by glslang. // culled as unused by glslang.
TIntermSequence zero;
zero.push_back(CreateIndexNode(0));
TIntermSequence ivec4Zero; TIntermSequence ivec4Zero;
ivec4Zero.push_back(TIntermAggregate::CreateConstructor(*ivec4Type, &zero)); ivec4Zero.push_back(CreateZeroNode(*ivec4Type));
TIntermAggregate *getOffsetsCall = TIntermAggregate *getOffsetsCall =
TIntermAggregate::CreateFunctionCall(*getOffsetsFunction, &ivec4Zero); TIntermAggregate::CreateFunctionCall(*getOffsetsFunction, &ivec4Zero);
captureXfbBlock->appendStatement(getOffsetsCall); captureXfbBlock->appendStatement(getOffsetsCall);
...@@ -1340,8 +1340,7 @@ bool TranslatorVulkan::translate(TIntermBlock *root, ...@@ -1340,8 +1340,7 @@ bool TranslatorVulkan::translate(TIntermBlock *root,
} }
#if defined(ANGLE_ENABLE_DIRECT_SPIRV_GENERATION) #if defined(ANGLE_ENABLE_DIRECT_SPIRV_GENERATION)
constexpr ShCompileOptions kUnsupportedTransformations = constexpr ShCompileOptions kUnsupportedTransformations = SH_ADD_BRESENHAM_LINE_RASTER_EMULATION;
SH_ADD_VULKAN_XFB_EMULATION_SUPPORT_CODE | SH_ADD_BRESENHAM_LINE_RASTER_EMULATION;
if ((compileOptions & SH_GENERATE_SPIRV_DIRECTLY) != 0 && getShaderType() == GL_VERTEX_SHADER && if ((compileOptions & SH_GENERATE_SPIRV_DIRECTLY) != 0 && getShaderType() == GL_VERTEX_SHADER &&
(compileOptions & kUnsupportedTransformations) == 0) (compileOptions & kUnsupportedTransformations) == 0)
{ {
......
...@@ -1046,6 +1046,7 @@ class SpirvIDDiscoverer final : angle::NonCopyable ...@@ -1046,6 +1046,7 @@ class SpirvIDDiscoverer final : angle::NonCopyable
spirv::IdRef vec4Id() const { return mVec4Id; } spirv::IdRef vec4Id() const { return mVec4Id; }
spirv::IdRef vec4OutTypePointerId() const { return mVec4OutTypePointerId; } spirv::IdRef vec4OutTypePointerId() const { return mVec4OutTypePointerId; }
spirv::IdRef intId() const { return mIntId; } spirv::IdRef intId() const { return mIntId; }
spirv::IdRef ivec4Id() const { return mIvec4Id; }
spirv::IdRef uintId() const { return mUintId; } spirv::IdRef uintId() const { return mUintId; }
spirv::IdRef int0Id() const { return mInt0Id; } spirv::IdRef int0Id() const { return mInt0Id; }
spirv::IdRef floatHalfId() const { return mFloatHalfId; } spirv::IdRef floatHalfId() const { return mFloatHalfId; }
...@@ -1082,11 +1083,12 @@ class SpirvIDDiscoverer final : angle::NonCopyable ...@@ -1082,11 +1083,12 @@ class SpirvIDDiscoverer final : angle::NonCopyable
// and swizzles. // and swizzles.
// //
// - mFloatId: id of OpTypeFloat 32 // - mFloatId: id of OpTypeFloat 32
// - mVec4Id: id of OpTypeVector %mFloatID 4 // - mVec4Id: id of OpTypeVector %mFloatId 4
// - mVec4OutTypePointerId: id of OpTypePointer Output %mVec4ID // - mVec4OutTypePointerId: id of OpTypePointer Output %mVec4Id
// - mIntId: id of OpTypeInt 32 1 // - mIntId: id of OpTypeInt 32 1
// - mIvecId: id of OpTypeVector %mIntId 4
// - mUintId: id of OpTypeInt 32 0 // - mUintId: id of OpTypeInt 32 0
// - mInt0Id: id of OpConstant %mIntID 0 // - mInt0Id: id of OpConstant %mIntId 0
// - mFloatHalfId: id of OpConstant %mFloatId 0.5f // - mFloatHalfId: id of OpConstant %mFloatId 0.5f
// - mOutputPerVertexTypePointerId: id of OpTypePointer Output %mOutputPerVertex.typeId // - mOutputPerVertexTypePointerId: id of OpTypePointer Output %mOutputPerVertex.typeId
// - mOutputPerVertexId: id of OpVariable %mOutputPerVertexTypePointerId Output // - mOutputPerVertexId: id of OpVariable %mOutputPerVertexTypePointerId Output
...@@ -1095,6 +1097,7 @@ class SpirvIDDiscoverer final : angle::NonCopyable ...@@ -1095,6 +1097,7 @@ class SpirvIDDiscoverer final : angle::NonCopyable
spirv::IdRef mVec4Id; spirv::IdRef mVec4Id;
spirv::IdRef mVec4OutTypePointerId; spirv::IdRef mVec4OutTypePointerId;
spirv::IdRef mIntId; spirv::IdRef mIntId;
spirv::IdRef mIvec4Id;
spirv::IdRef mUintId; spirv::IdRef mUintId;
spirv::IdRef mInt0Id; spirv::IdRef mInt0Id;
spirv::IdRef mFloatHalfId; spirv::IdRef mFloatHalfId;
...@@ -1266,12 +1269,17 @@ void SpirvIDDiscoverer::visitTypeVector(spirv::IdResult id, ...@@ -1266,12 +1269,17 @@ void SpirvIDDiscoverer::visitTypeVector(spirv::IdResult id,
spirv::IdRef componentId, spirv::IdRef componentId,
spirv::LiteralInteger componentCount) spirv::LiteralInteger componentCount)
{ {
// Only interested in OpTypeVector %mFloatId 4 // Only interested in OpTypeVector %mFloatId 4 and OpTypeVector %mIntId 4
if (componentId == mFloatId && componentCount == 4) if (componentId == mFloatId && componentCount == 4)
{ {
ASSERT(!mVec4Id.valid()); ASSERT(!mVec4Id.valid());
mVec4Id = id; mVec4Id = id;
} }
if (componentId == mIntId && componentCount == 4)
{
ASSERT(!mIvec4Id.valid());
mIvec4Id = id;
}
} }
SpirvVariableType SpirvIDDiscoverer::visitVariable(spirv::IdResultType typeId, SpirvVariableType SpirvIDDiscoverer::visitVariable(spirv::IdResultType typeId,
...@@ -1350,6 +1358,12 @@ void SpirvIDDiscoverer::writePendingDeclarations(spirv::Blob *blobOut) ...@@ -1350,6 +1358,12 @@ void SpirvIDDiscoverer::writePendingDeclarations(spirv::Blob *blobOut)
spirv::WriteTypeInt(blobOut, mIntId, spirv::LiteralInteger(32), spirv::LiteralInteger(1)); spirv::WriteTypeInt(blobOut, mIntId, spirv::LiteralInteger(32), spirv::LiteralInteger(1));
} }
if (!mIvec4Id.valid())
{
mIvec4Id = SpirvTransformerBase::GetNewId(blobOut);
spirv::WriteTypeVector(blobOut, mIvec4Id, mIntId, spirv::LiteralInteger(4));
}
ASSERT(!mInt0Id.valid()); ASSERT(!mInt0Id.valid());
mInt0Id = SpirvTransformerBase::GetNewId(blobOut); mInt0Id = SpirvTransformerBase::GetNewId(blobOut);
spirv::WriteConstant(blobOut, mIntId, mInt0Id, spirv::LiteralContextDependentNumber(0)); spirv::WriteConstant(blobOut, mIntId, mInt0Id, spirv::LiteralContextDependentNumber(0));
...@@ -2149,6 +2163,13 @@ void SpirvTransformFeedbackCodeGenerator::writePendingDeclarations( ...@@ -2149,6 +2163,13 @@ void SpirvTransformFeedbackCodeGenerator::writePendingDeclarations(
spirv::WriteTypePointer(blobOut, mFloatUniformPointerId, spv::StorageClassUniform, spirv::WriteTypePointer(blobOut, mFloatUniformPointerId, spv::StorageClassUniform,
ids.floatId()); ids.floatId());
if (!mIVec4FuncPointerId.valid())
{
mIVec4FuncPointerId = SpirvTransformerBase::GetNewId(blobOut);
spirv::WriteTypePointer(blobOut, mIVec4FuncPointerId, spv::StorageClassFunction,
ids.ivec4Id());
}
mIntNIds.resize(4); mIntNIds.resize(4);
mIntNIds[0] = ids.int0Id(); mIntNIds[0] = ids.int0Id();
for (int n = 1; n < 4; ++n) for (int n = 1; n < 4; ++n)
...@@ -2282,7 +2303,6 @@ void SpirvTransformFeedbackCodeGenerator::writeTransformFeedbackEmulationOutput( ...@@ -2282,7 +2303,6 @@ void SpirvTransformFeedbackCodeGenerator::writeTransformFeedbackEmulationOutput(
// //
// - For the initial offsets calculation: // - For the initial offsets calculation:
// //
// %getOffsetsParam = OpVariable %mIVec4FuncPointerId Function %stridesComposite
// %xfbOffsetsResult = OpFunctionCall %ivec4 %ANGLEGetXfbOffsets %stridesComposite // %xfbOffsetsResult = OpFunctionCall %ivec4 %ANGLEGetXfbOffsets %stridesComposite
// %xfbOffsetsVar = OpVariable %mIVec4FuncPointerId Function // %xfbOffsetsVar = OpVariable %mIVec4FuncPointerId Function
// OpStore %xfbOffsetsVar %xfbOffsetsResult // OpStore %xfbOffsetsVar %xfbOffsetsResult
...@@ -2462,7 +2482,6 @@ void SpirvTransformFeedbackCodeGenerator::getVaryingTypeIds(const SpirvIDDiscove ...@@ -2462,7 +2482,6 @@ void SpirvTransformFeedbackCodeGenerator::getVaryingTypeIds(const SpirvIDDiscove
void SpirvTransformFeedbackCodeGenerator::writeGetOffsetsCall(spirv::IdRef xfbOffsets, void SpirvTransformFeedbackCodeGenerator::writeGetOffsetsCall(spirv::IdRef xfbOffsets,
spirv::Blob *blobOut) spirv::Blob *blobOut)
{ {
const spirv::IdRef xfbGetOffsetsParam(SpirvTransformerBase::GetNewId(blobOut));
const spirv::IdRef xfbOffsetsResult(SpirvTransformerBase::GetNewId(blobOut)); const spirv::IdRef xfbOffsetsResult(SpirvTransformerBase::GetNewId(blobOut));
const spirv::IdRef xfbOffsetsVar(SpirvTransformerBase::GetNewId(blobOut)); const spirv::IdRef xfbOffsetsVar(SpirvTransformerBase::GetNewId(blobOut));
...@@ -2470,17 +2489,13 @@ void SpirvTransformFeedbackCodeGenerator::writeGetOffsetsCall(spirv::IdRef xfbOf ...@@ -2470,17 +2489,13 @@ void SpirvTransformFeedbackCodeGenerator::writeGetOffsetsCall(spirv::IdRef xfbOf
// //
// ivec4 xfbOffsets = ANGLEGetXfbOffsets(ivec4(stride0, stride1, stride2, stride3)); // ivec4 xfbOffsets = ANGLEGetXfbOffsets(ivec4(stride0, stride1, stride2, stride3));
// Create a variable to hold the parameter, initialized with the constant ivec4 containing the
// strides.
spirv::WriteVariable(blobOut, mIVec4FuncPointerId, xfbGetOffsetsParam,
spv::StorageClassFunction, &mBufferStridesCompositeId);
// Create a variable to hold the result. // Create a variable to hold the result.
spirv::WriteVariable(blobOut, mIVec4FuncPointerId, xfbOffsetsVar, spv::StorageClassFunction, spirv::WriteVariable(blobOut, mIVec4FuncPointerId, xfbOffsetsVar, spv::StorageClassFunction,
nullptr); nullptr);
// Call a helper function generated by the translator to calculate the offsets for the current // Call a helper function generated by the translator to calculate the offsets for the current
// vertex. // vertex.
spirv::WriteFunctionCall(blobOut, mIVec4Id, xfbOffsetsResult, mGetXfbOffsetsFuncId, spirv::WriteFunctionCall(blobOut, mIVec4Id, xfbOffsetsResult, mGetXfbOffsetsFuncId,
{xfbGetOffsetsParam}); {mBufferStridesCompositeId});
// Store the results. // Store the results.
spirv::WriteStore(blobOut, xfbOffsetsVar, xfbOffsetsResult, nullptr); spirv::WriteStore(blobOut, xfbOffsetsVar, xfbOffsetsResult, nullptr);
// Load from the variable for use in expressions. // Load from the variable for use in expressions.
......
...@@ -64,8 +64,8 @@ ...@@ -64,8 +64,8 @@
5981 PIXEL4ORXL GLES : Texture3DTestES2.Luminance/* = SKIP 5981 PIXEL4ORXL GLES : Texture3DTestES2.Luminance/* = SKIP
5981 PIXEL4ORXL GLES : Texture3DTestES2.RGBA/* = SKIP 5981 PIXEL4ORXL GLES : Texture3DTestES2.RGBA/* = SKIP
5981 PIXEL4ORXL GLES : TextureBufferTestES31.UseAsUBOThenUpdateThenAsTextureBuffer/* = SKIP 5981 PIXEL4ORXL GLES : TextureBufferTestES31.UseAsUBOThenUpdateThenAsTextureBuffer/* = SKIP
5981 PIXEL4ORXL GLES : TransformFeedbackTestES31.IOBlocksInterleaved/* = SKIP 5981 PIXEL4ORXL GLES : TransformFeedbackTestIOBlocks.Interleaved/* = SKIP
5981 PIXEL4ORXL GLES : TransformFeedbackTestES31.IOBlocksSeparate/* = SKIP 5981 PIXEL4ORXL GLES : TransformFeedbackTestIOBlocks.Separate/* = SKIP
5981 PIXEL4ORXL GLES : VulkanExternalImageTest.ShouldClearOpaqueFdRGBA8/* = SKIP 5981 PIXEL4ORXL GLES : VulkanExternalImageTest.ShouldClearOpaqueFdRGBA8/* = SKIP
5981 PIXEL4ORXL GLES : VulkanExternalImageTest.TextureFormatCompatChromiumFd/* = SKIP 5981 PIXEL4ORXL GLES : VulkanExternalImageTest.TextureFormatCompatChromiumFd/* = SKIP
...@@ -98,4 +98,4 @@ ...@@ -98,4 +98,4 @@
5981 PIXEL4ORXL VULKAN : Texture2DArrayCopy.UnsizedFormats/* = SKIP 5981 PIXEL4ORXL VULKAN : Texture2DArrayCopy.UnsizedFormats/* = SKIP
5981 PIXEL4ORXL VULKAN : Texture3DCopy.UnsignedByteFormats/* = SKIP 5981 PIXEL4ORXL VULKAN : Texture3DCopy.UnsignedByteFormats/* = SKIP
5981 PIXEL4ORXL VULKAN : Texture3DCopy.UnsizedFormats/* = SKIP 5981 PIXEL4ORXL VULKAN : Texture3DCopy.UnsizedFormats/* = SKIP
5981 PIXEL4ORXL VULKAN : TransformFeedbackTestES31.IOBlocksInterleaved/* = SKIP 5981 PIXEL4ORXL VULKAN : TransformFeedbackTestIOBlocks.Interleaved/* = SKIP
...@@ -3052,9 +3052,12 @@ TEST_P(TransformFeedbackTestES32, PrimitivesWrittenAndGenerated) ...@@ -3052,9 +3052,12 @@ TEST_P(TransformFeedbackTestES32, PrimitivesWrittenAndGenerated)
} }
} }
class TransformFeedbackTestIOBlocks : public TransformFeedbackTestES31
{};
// Verify that capture of I/O block fields works, both when the instance name is specified and when // Verify that capture of I/O block fields works, both when the instance name is specified and when
// not. This test uses interleaved components. // not. This test uses interleaved components.
TEST_P(TransformFeedbackTestES31, IOBlocksInterleaved) TEST_P(TransformFeedbackTestIOBlocks, Interleaved)
{ {
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks")); ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
...@@ -3161,7 +3164,7 @@ void main() ...@@ -3161,7 +3164,7 @@ void main()
} }
// Verify that capture of I/O block fields works. This test uses separate components. // Verify that capture of I/O block fields works. This test uses separate components.
TEST_P(TransformFeedbackTestES31, IOBlocksSeparate) TEST_P(TransformFeedbackTestIOBlocks, Separate)
{ {
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks")); ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
...@@ -3305,7 +3308,11 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TransformFeedbackLifetimeTest); ...@@ -3305,7 +3308,11 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TransformFeedbackLifetimeTest);
ANGLE_INSTANTIATE_TEST_ES3(TransformFeedbackLifetimeTest); ANGLE_INSTANTIATE_TEST_ES3(TransformFeedbackLifetimeTest);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TransformFeedbackTestES31); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TransformFeedbackTestES31);
ANGLE_INSTANTIATE_TEST_ES31(TransformFeedbackTestES31); ANGLE_INSTANTIATE_TEST_ES31_AND(TransformFeedbackTestES31,
WithDirectSPIRVGeneration(ES31_VULKAN()));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TransformFeedbackTestIOBlocks);
ANGLE_INSTANTIATE_TEST_ES31(TransformFeedbackTestIOBlocks);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TransformFeedbackTestES32); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TransformFeedbackTestES32);
ANGLE_INSTANTIATE_TEST_ES32(TransformFeedbackTestES32); ANGLE_INSTANTIATE_TEST_ES32(TransformFeedbackTestES32);
......
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