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 ...@@ -322,6 +322,7 @@ class ProgramState final : angle::NonCopyable
{ {
return mActiveAttribLocationsMask; return mActiveAttribLocationsMask;
} }
const AttributesMask &getNonBuiltinAttribLocationsMask() const { return mAttributesMask; }
unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; } unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; } DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; }
const std::vector<sh::OutputVariable> &getOutputVariables() const { return mOutputVariables; } const std::vector<sh::OutputVariable> &getOutputVariables() const { return mOutputVariables; }
...@@ -344,6 +345,7 @@ class ProgramState final : angle::NonCopyable ...@@ -344,6 +345,7 @@ class ProgramState final : angle::NonCopyable
const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; } const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
const RangeUI &getImageUniformRange() const { return mImageUniformRange; } const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; } const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; }
const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
{ {
......
...@@ -24,33 +24,6 @@ bool IsElementArrayBufferSubjectIndex(angle::SubjectIndex subjectIndex) ...@@ -24,33 +24,6 @@ bool IsElementArrayBufferSubjectIndex(angle::SubjectIndex subjectIndex)
return (subjectIndex == MAX_VERTEX_ATTRIBS); 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; constexpr angle::SubjectIndex kElementArrayBufferIndex = MAX_VERTEX_ATTRIBS;
} // namespace } // namespace
......
...@@ -433,6 +433,23 @@ ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, Compone ...@@ -433,6 +433,23 @@ ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, Compone
*mask |= kComponentMasks[type] << index; *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, bool ValidateComponentTypeMasks(unsigned long outputTypes,
unsigned long inputTypes, unsigned long inputTypes,
unsigned long outputMask, unsigned long outputMask,
......
...@@ -270,6 +270,32 @@ bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat ...@@ -270,6 +270,32 @@ bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat
// Implemented in es3_copy_conversion_table_autogen.cpp // Implemented in es3_copy_conversion_table_autogen.cpp
bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat); 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 } // namespace gl
#endif // LIBANGLE_FORMATUTILS_H_ #endif // LIBANGLE_FORMATUTILS_H_
...@@ -518,9 +518,9 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context, ...@@ -518,9 +518,9 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context,
const vk::GraphicsPipelineDesc *descPtr; const vk::GraphicsPipelineDesc *descPtr;
// Draw call shader patching, shader compilation, and pipeline cache query. // Draw call shader patching, shader compilation, and pipeline cache query.
ANGLE_TRY(mProgram->getGraphicsPipeline(this, mCurrentDrawMode, *mGraphicsPipelineDesc, ANGLE_TRY(mProgram->getGraphicsPipeline(
mProgram->getState().getActiveAttribLocationsMask(), this, mCurrentDrawMode, *mGraphicsPipelineDesc,
&descPtr, &mCurrentPipeline)); mProgram->getState().getNonBuiltinAttribLocationsMask(), &descPtr, &mCurrentPipeline));
mGraphicsPipelineTransition.reset(); mGraphicsPipelineTransition.reset();
} }
else if (mGraphicsPipelineTransition.any()) else if (mGraphicsPipelineTransition.any())
...@@ -534,7 +534,8 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context, ...@@ -534,7 +534,8 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context,
ANGLE_TRY(mProgram->getGraphicsPipeline( ANGLE_TRY(mProgram->getGraphicsPipeline(
this, mCurrentDrawMode, *mGraphicsPipelineDesc, this, mCurrentDrawMode, *mGraphicsPipelineDesc,
mProgram->getState().getActiveAttribLocationsMask(), &descPtr, &mCurrentPipeline)); mProgram->getState().getNonBuiltinAttribLocationsMask(), &descPtr,
&mCurrentPipeline));
oldPipeline->addTransition(mGraphicsPipelineTransition, descPtr, mCurrentPipeline); oldPipeline->addTransition(mGraphicsPipelineTransition, descPtr, mCurrentPipeline);
} }
......
...@@ -144,7 +144,7 @@ class ProgramVk : public ProgramImpl ...@@ -144,7 +144,7 @@ class ProgramVk : public ProgramImpl
return shaderProgram->getGraphicsPipeline( return shaderProgram->getGraphicsPipeline(
contextVk, &contextVk->getRenderPassCache(), renderer->getPipelineCache(), contextVk, &contextVk->getRenderPassCache(), renderer->getPipelineCache(),
contextVk->getCurrentQueueSerial(), mPipelineLayout.get(), desc, activeAttribLocations, contextVk->getCurrentQueueSerial(), mPipelineLayout.get(), desc, activeAttribLocations,
descPtrOut, pipelineOut); mState.getAttributesTypeMask(), descPtrOut, pipelineOut);
} }
// Used in testing only. // Used in testing only.
......
...@@ -560,7 +560,8 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk, ...@@ -560,7 +560,8 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
ANGLE_TRY(program->getGraphicsPipeline( ANGLE_TRY(program->getGraphicsPipeline(
contextVk, &contextVk->getRenderPassCache(), renderer->getPipelineCache(), serial, 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); helper->updateSerial(serial);
commandBuffer->bindGraphicsPipeline(helper->getPipeline()); commandBuffer->bindGraphicsPipeline(helper->getPipeline());
if (descriptorSet != VK_NULL_HANDLE) if (descriptorSet != VK_NULL_HANDLE)
......
...@@ -338,6 +338,12 @@ constexpr size_t kTransitionBitShift = kTransitionByteShift + Log2(kBitsPerByte) ...@@ -338,6 +338,12 @@ constexpr size_t kTransitionBitShift = kTransitionByteShift + Log2(kBitsPerByte)
// the update function. // the update function.
#define ANGLE_GET_INDEXED_TRANSITION_BIT(Member, Field, Index, BitWidth) \ #define ANGLE_GET_INDEXED_TRANSITION_BIT(Member, Field, Index, BitWidth) \
(((BitWidth * Index) >> kTransitionBitShift) + ANGLE_GET_TRANSITION_BIT(Member, Field)) (((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 } // anonymous namespace
// RenderPassDesc implementation. // RenderPassDesc implementation.
...@@ -567,6 +573,7 @@ angle::Result GraphicsPipelineDesc::initializePipeline( ...@@ -567,6 +573,7 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
const RenderPass &compatibleRenderPass, const RenderPass &compatibleRenderPass,
const PipelineLayout &pipelineLayout, const PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const ShaderModule *vertexModule, const ShaderModule *vertexModule,
const ShaderModule *fragmentModule, const ShaderModule *fragmentModule,
Pipeline *pipelineOut) const Pipeline *pipelineOut) const
...@@ -649,8 +656,23 @@ angle::Result GraphicsPipelineDesc::initializePipeline( ...@@ -649,8 +656,23 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
} }
// Get the corresponding VkFormat for the attrib's format. // Get the corresponding VkFormat for the attrib's format.
angle::FormatID angleFormat = static_cast<angle::FormatID>(packedAttrib.format); angle::FormatID formatID = static_cast<angle::FormatID>(packedAttrib.format);
VkFormat vkFormat = context->getRenderer()->getFormat(angleFormat).vkBufferFormat; 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. // The binding index could become more dynamic in ES 3.1.
attribDesc.binding = attribIndex; attribDesc.binding = attribIndex;
...@@ -1638,6 +1660,7 @@ angle::Result GraphicsPipelineCache::insertPipeline( ...@@ -1638,6 +1660,7 @@ angle::Result GraphicsPipelineCache::insertPipeline(
const vk::RenderPass &compatibleRenderPass, const vk::RenderPass &compatibleRenderPass,
const vk::PipelineLayout &pipelineLayout, const vk::PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::ShaderModule *vertexModule, const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule, const vk::ShaderModule *fragmentModule,
const vk::GraphicsPipelineDesc &desc, const vk::GraphicsPipelineDesc &desc,
...@@ -1650,8 +1673,9 @@ angle::Result GraphicsPipelineCache::insertPipeline( ...@@ -1650,8 +1673,9 @@ angle::Result GraphicsPipelineCache::insertPipeline(
if (context != nullptr) if (context != nullptr)
{ {
ANGLE_TRY(desc.initializePipeline(context, pipelineCacheVk, compatibleRenderPass, ANGLE_TRY(desc.initializePipeline(context, pipelineCacheVk, compatibleRenderPass,
pipelineLayout, activeAttribLocationsMask, vertexModule, pipelineLayout, activeAttribLocationsMask,
fragmentModule, &newPipeline)); programAttribsTypeMask, vertexModule, fragmentModule,
&newPipeline));
} }
// The Serial will be updated outside of this query. // The Serial will be updated outside of this query.
......
...@@ -361,6 +361,7 @@ class GraphicsPipelineDesc final ...@@ -361,6 +361,7 @@ class GraphicsPipelineDesc final
const RenderPass &compatibleRenderPass, const RenderPass &compatibleRenderPass,
const PipelineLayout &pipelineLayout, const PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const ShaderModule *vertexModule, const ShaderModule *vertexModule,
const ShaderModule *fragmentModule, const ShaderModule *fragmentModule,
Pipeline *pipelineOut) const; Pipeline *pipelineOut) const;
...@@ -818,6 +819,7 @@ class GraphicsPipelineCache final : angle::NonCopyable ...@@ -818,6 +819,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
const vk::RenderPass &compatibleRenderPass, const vk::RenderPass &compatibleRenderPass,
const vk::PipelineLayout &pipelineLayout, const vk::PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::ShaderModule *vertexModule, const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule, const vk::ShaderModule *fragmentModule,
const vk::GraphicsPipelineDesc &desc, const vk::GraphicsPipelineDesc &desc,
...@@ -833,8 +835,8 @@ class GraphicsPipelineCache final : angle::NonCopyable ...@@ -833,8 +835,8 @@ class GraphicsPipelineCache final : angle::NonCopyable
} }
return insertPipeline(context, pipelineCacheVk, compatibleRenderPass, pipelineLayout, return insertPipeline(context, pipelineCacheVk, compatibleRenderPass, pipelineLayout,
activeAttribLocationsMask, vertexModule, fragmentModule, desc, activeAttribLocationsMask, programAttribsTypeMask, vertexModule,
descPtrOut, pipelineOut); fragmentModule, desc, descPtrOut, pipelineOut);
} }
private: private:
...@@ -843,6 +845,7 @@ class GraphicsPipelineCache final : angle::NonCopyable ...@@ -843,6 +845,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
const vk::RenderPass &compatibleRenderPass, const vk::RenderPass &compatibleRenderPass,
const vk::PipelineLayout &pipelineLayout, const vk::PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::ShaderModule *vertexModule, const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule, const vk::ShaderModule *fragmentModule,
const vk::GraphicsPipelineDesc &desc, const vk::GraphicsPipelineDesc &desc,
......
...@@ -1000,6 +1000,7 @@ class ShaderProgramHelper : angle::NonCopyable ...@@ -1000,6 +1000,7 @@ class ShaderProgramHelper : angle::NonCopyable
const PipelineLayout &pipelineLayout, const PipelineLayout &pipelineLayout,
const GraphicsPipelineDesc &pipelineDesc, const GraphicsPipelineDesc &pipelineDesc,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::GraphicsPipelineDesc **descPtrOut, const vk::GraphicsPipelineDesc **descPtrOut,
PipelineHelper **pipelineOut) PipelineHelper **pipelineOut)
{ {
...@@ -1015,8 +1016,8 @@ class ShaderProgramHelper : angle::NonCopyable ...@@ -1015,8 +1016,8 @@ class ShaderProgramHelper : angle::NonCopyable
return mGraphicsPipelines.getPipeline(context, pipelineCache, *compatibleRenderPass, return mGraphicsPipelines.getPipeline(context, pipelineCache, *compatibleRenderPass,
pipelineLayout, activeAttribLocationsMask, pipelineLayout, activeAttribLocationsMask,
vertexShader, fragmentShader, pipelineDesc, programAttribsTypeMask, vertexShader, fragmentShader,
descPtrOut, pipelineOut); pipelineDesc, descPtrOut, pipelineOut);
} }
angle::Result getComputePipeline(Context *context, angle::Result getComputePipeline(Context *context,
......
...@@ -86,12 +86,14 @@ void VulkanPipelineCachePerfTest::step() ...@@ -86,12 +86,14 @@ void VulkanPipelineCachePerfTest::step()
const vk::GraphicsPipelineDesc *desc = nullptr; const vk::GraphicsPipelineDesc *desc = nullptr;
vk::PipelineHelper *result = nullptr; vk::PipelineHelper *result = nullptr;
gl::AttributesMask am; gl::AttributesMask am;
gl::ComponentTypeMask ctm;
for (unsigned int iteration = 0; iteration < kIterationsPerStep; ++iteration) for (unsigned int iteration = 0; iteration < kIterationsPerStep; ++iteration)
{ {
for (const auto &hit : mCacheHits) 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() ...@@ -99,7 +101,8 @@ void VulkanPipelineCachePerfTest::step()
++missCount, ++mMissIndex) ++missCount, ++mMissIndex)
{ {
const auto &miss = mCacheMisses[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