Commit a9ec8749 by James Dong Committed by Commit Bot

Vulkan: override format for mismatched attribs

Prevents Vulkan validation error by replacing the input format for any mismatched vertex attributes with a format compatible to what the shader expects. Bug: angleproject:3436 Change-Id: Ia52f29c084d82bbc4e9149102cd4b5fc25ccb9b3 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1698567 Commit-Queue: Courtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 8b2bb18f
......@@ -322,6 +322,7 @@ class ProgramState final : angle::NonCopyable
{
return mActiveAttribLocationsMask;
}
const AttributesMask &getNonBuiltinAttribLocationsMask() const { return mAttributesMask; }
unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; }
const std::vector<sh::OutputVariable> &getOutputVariables() const { return mOutputVariables; }
......@@ -344,6 +345,7 @@ class ProgramState final : angle::NonCopyable
const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; }
const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
{
......
......@@ -24,33 +24,6 @@ bool IsElementArrayBufferSubjectIndex(angle::SubjectIndex subjectIndex)
return (subjectIndex == MAX_VERTEX_ATTRIBS);
}
ANGLE_INLINE ComponentType GetVertexAttributeComponentType(bool pureInteger, VertexAttribType type)
{
if (pureInteger)
{
switch (type)
{
case VertexAttribType::Byte:
case VertexAttribType::Short:
case VertexAttribType::Int:
return ComponentType::Int;
case VertexAttribType::UnsignedByte:
case VertexAttribType::UnsignedShort:
case VertexAttribType::UnsignedInt:
return ComponentType::UnsignedInt;
default:
UNREACHABLE();
return ComponentType::NoType;
}
}
else
{
return ComponentType::Float;
}
}
constexpr angle::SubjectIndex kElementArrayBufferIndex = MAX_VERTEX_ATTRIBS;
} // namespace
......
......@@ -433,6 +433,23 @@ ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, Compone
*mask |= kComponentMasks[type] << index;
}
ANGLE_INLINE ComponentType GetComponentTypeMask(const ComponentTypeMask &mask, size_t index)
{
ASSERT(index <= kMaxComponentTypeMaskIndex);
uint32_t mask_bits = static_cast<uint32_t>((mask.to_ulong() >> index) & 0x10001);
switch (mask_bits)
{
case 0x10001:
return ComponentType::Float;
case 0x00001:
return ComponentType::Int;
case 0x10000:
return ComponentType::UnsignedInt;
default:
return ComponentType::InvalidEnum;
}
}
bool ValidateComponentTypeMasks(unsigned long outputTypes,
unsigned long inputTypes,
unsigned long outputMask,
......
......@@ -270,6 +270,32 @@ bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat
// Implemented in es3_copy_conversion_table_autogen.cpp
bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat);
ANGLE_INLINE ComponentType GetVertexAttributeComponentType(bool pureInteger, VertexAttribType type)
{
if (pureInteger)
{
switch (type)
{
case VertexAttribType::Byte:
case VertexAttribType::Short:
case VertexAttribType::Int:
return ComponentType::Int;
case VertexAttribType::UnsignedByte:
case VertexAttribType::UnsignedShort:
case VertexAttribType::UnsignedInt:
return ComponentType::UnsignedInt;
default:
UNREACHABLE();
return ComponentType::NoType;
}
}
else
{
return ComponentType::Float;
}
}
} // namespace gl
#endif // LIBANGLE_FORMATUTILS_H_
......@@ -518,9 +518,9 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context,
const vk::GraphicsPipelineDesc *descPtr;
// Draw call shader patching, shader compilation, and pipeline cache query.
ANGLE_TRY(mProgram->getGraphicsPipeline(this, mCurrentDrawMode, *mGraphicsPipelineDesc,
mProgram->getState().getActiveAttribLocationsMask(),
&descPtr, &mCurrentPipeline));
ANGLE_TRY(mProgram->getGraphicsPipeline(
this, mCurrentDrawMode, *mGraphicsPipelineDesc,
mProgram->getState().getNonBuiltinAttribLocationsMask(), &descPtr, &mCurrentPipeline));
mGraphicsPipelineTransition.reset();
}
else if (mGraphicsPipelineTransition.any())
......@@ -534,7 +534,8 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context,
ANGLE_TRY(mProgram->getGraphicsPipeline(
this, mCurrentDrawMode, *mGraphicsPipelineDesc,
mProgram->getState().getActiveAttribLocationsMask(), &descPtr, &mCurrentPipeline));
mProgram->getState().getNonBuiltinAttribLocationsMask(), &descPtr,
&mCurrentPipeline));
oldPipeline->addTransition(mGraphicsPipelineTransition, descPtr, mCurrentPipeline);
}
......
......@@ -144,7 +144,7 @@ class ProgramVk : public ProgramImpl
return shaderProgram->getGraphicsPipeline(
contextVk, &contextVk->getRenderPassCache(), renderer->getPipelineCache(),
contextVk->getCurrentQueueSerial(), mPipelineLayout.get(), desc, activeAttribLocations,
descPtrOut, pipelineOut);
mState.getAttributesTypeMask(), descPtrOut, pipelineOut);
}
// Used in testing only.
......
......@@ -560,7 +560,8 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
ANGLE_TRY(program->getGraphicsPipeline(
contextVk, &contextVk->getRenderPassCache(), renderer->getPipelineCache(), serial,
pipelineLayout.get(), *pipelineDesc, gl::AttributesMask(), &descPtr, &helper));
pipelineLayout.get(), *pipelineDesc, gl::AttributesMask(), gl::ComponentTypeMask(),
&descPtr, &helper));
helper->updateSerial(serial);
commandBuffer->bindGraphicsPipeline(helper->getPipeline());
if (descriptorSet != VK_NULL_HANDLE)
......
......@@ -338,6 +338,12 @@ constexpr size_t kTransitionBitShift = kTransitionByteShift + Log2(kBitsPerByte)
// the update function.
#define ANGLE_GET_INDEXED_TRANSITION_BIT(Member, Field, Index, BitWidth) \
(((BitWidth * Index) >> kTransitionBitShift) + ANGLE_GET_TRANSITION_BIT(Member, Field))
constexpr angle::PackedEnumMap<gl::ComponentType, VkFormat> kMismatchedComponentTypeMap = {{
{gl::ComponentType::Float, VK_FORMAT_R32G32B32A32_SFLOAT},
{gl::ComponentType::Int, VK_FORMAT_R32G32B32A32_SINT},
{gl::ComponentType::UnsignedInt, VK_FORMAT_R32G32B32A32_UINT},
}};
} // anonymous namespace
// RenderPassDesc implementation.
......@@ -567,6 +573,7 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
const RenderPass &compatibleRenderPass,
const PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const ShaderModule *vertexModule,
const ShaderModule *fragmentModule,
Pipeline *pipelineOut) const
......@@ -649,8 +656,23 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
}
// Get the corresponding VkFormat for the attrib's format.
angle::FormatID angleFormat = static_cast<angle::FormatID>(packedAttrib.format);
VkFormat vkFormat = context->getRenderer()->getFormat(angleFormat).vkBufferFormat;
angle::FormatID formatID = static_cast<angle::FormatID>(packedAttrib.format);
const vk::Format &format = context->getRenderer()->getFormat(formatID);
const angle::Format &angleFormat = format.angleFormat();
VkFormat vkFormat = format.vkBufferFormat;
gl::ComponentType attribType =
GetVertexAttributeComponentType(angleFormat.isPureInt(), angleFormat.vertexAttribType);
gl::ComponentType programAttribType =
gl::GetComponentTypeMask(programAttribsTypeMask, attribIndex);
if (attribType != programAttribType)
{
// Override the format with a compatible one.
vkFormat = kMismatchedComponentTypeMap[programAttribType];
bindingDesc.stride = 0; // Prevent out-of-bounds accesses.
}
// The binding index could become more dynamic in ES 3.1.
attribDesc.binding = attribIndex;
......@@ -1638,6 +1660,7 @@ angle::Result GraphicsPipelineCache::insertPipeline(
const vk::RenderPass &compatibleRenderPass,
const vk::PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule,
const vk::GraphicsPipelineDesc &desc,
......@@ -1650,8 +1673,9 @@ angle::Result GraphicsPipelineCache::insertPipeline(
if (context != nullptr)
{
ANGLE_TRY(desc.initializePipeline(context, pipelineCacheVk, compatibleRenderPass,
pipelineLayout, activeAttribLocationsMask, vertexModule,
fragmentModule, &newPipeline));
pipelineLayout, activeAttribLocationsMask,
programAttribsTypeMask, vertexModule, fragmentModule,
&newPipeline));
}
// The Serial will be updated outside of this query.
......
......@@ -361,6 +361,7 @@ class GraphicsPipelineDesc final
const RenderPass &compatibleRenderPass,
const PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const ShaderModule *vertexModule,
const ShaderModule *fragmentModule,
Pipeline *pipelineOut) const;
......@@ -818,6 +819,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
const vk::RenderPass &compatibleRenderPass,
const vk::PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule,
const vk::GraphicsPipelineDesc &desc,
......@@ -833,8 +835,8 @@ class GraphicsPipelineCache final : angle::NonCopyable
}
return insertPipeline(context, pipelineCacheVk, compatibleRenderPass, pipelineLayout,
activeAttribLocationsMask, vertexModule, fragmentModule, desc,
descPtrOut, pipelineOut);
activeAttribLocationsMask, programAttribsTypeMask, vertexModule,
fragmentModule, desc, descPtrOut, pipelineOut);
}
private:
......@@ -843,6 +845,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
const vk::RenderPass &compatibleRenderPass,
const vk::PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule,
const vk::GraphicsPipelineDesc &desc,
......
......@@ -1000,6 +1000,7 @@ class ShaderProgramHelper : angle::NonCopyable
const PipelineLayout &pipelineLayout,
const GraphicsPipelineDesc &pipelineDesc,
const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::GraphicsPipelineDesc **descPtrOut,
PipelineHelper **pipelineOut)
{
......@@ -1015,8 +1016,8 @@ class ShaderProgramHelper : angle::NonCopyable
return mGraphicsPipelines.getPipeline(context, pipelineCache, *compatibleRenderPass,
pipelineLayout, activeAttribLocationsMask,
vertexShader, fragmentShader, pipelineDesc,
descPtrOut, pipelineOut);
programAttribsTypeMask, vertexShader, fragmentShader,
pipelineDesc, descPtrOut, pipelineOut);
}
angle::Result getComputePipeline(Context *context,
......
......@@ -86,12 +86,14 @@ void VulkanPipelineCachePerfTest::step()
const vk::GraphicsPipelineDesc *desc = nullptr;
vk::PipelineHelper *result = nullptr;
gl::AttributesMask am;
gl::ComponentTypeMask ctm;
for (unsigned int iteration = 0; iteration < kIterationsPerStep; ++iteration)
{
for (const auto &hit : mCacheHits)
{
(void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, &sm, &sm, hit, &desc, &result);
(void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, ctm, &sm, &sm, hit, &desc,
&result);
}
}
......@@ -99,7 +101,8 @@ void VulkanPipelineCachePerfTest::step()
++missCount, ++mMissIndex)
{
const auto &miss = mCacheMisses[mMissIndex];
(void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, &sm, &sm, miss, &desc, &result);
(void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, ctm, &sm, &sm, miss, &desc,
&result);
}
}
......
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