diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp index 5adcdf29eb..7cd71ca526 100644 --- a/src/libANGLE/renderer/vulkan/ContextVk.cpp +++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp @@ -1655,34 +1655,47 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context, vertexArrayVk->updateCurrentElementArrayBuffer(); } - if (shouldConvertUint8VkIndexType(indexType) && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER]) + if (shouldConvertUint8VkIndexType(indexType)) { - ANGLE_VK_PERF_WARNING(this, GL_DEBUG_SEVERITY_LOW, - "Potential inefficiency emulating uint8 vertex attributes due to " - "lack of hardware support"); + if (mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER]) + { + ANGLE_VK_PERF_WARNING( + this, GL_DEBUG_SEVERITY_LOW, + "Potential inefficiency emulating uint8 vertex attributes due to " + "lack of hardware support"); - BufferVk *bufferVk = vk::GetImpl(elementArrayBuffer); - vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); + BufferVk *bufferVk = vk::GetImpl(elementArrayBuffer); + vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); - if (bufferHelper.isHostVisible() && - mRenderer->hasResourceUseFinished(bufferHelper.getResourceUse())) - { - uint8_t *src = nullptr; - ANGLE_TRY(bufferVk->mapForReadAccessOnly(this, reinterpret_cast(&src))); - // Note: bufferOffset is not added here because mapImpl already adds it. - src += reinterpret_cast(indices); - const size_t byteCount = static_cast(elementArrayBuffer->getSize()) - - reinterpret_cast(indices); - BufferBindingDirty bindingDirty; - ANGLE_TRY(vertexArrayVk->convertIndexBufferCPU(this, indexType, byteCount, src, - &bindingDirty)); - ANGLE_TRY(bufferVk->unmapReadAccessOnly(this)); - } - else - { - ANGLE_TRY(vertexArrayVk->convertIndexBufferGPU(this, bufferVk, indices)); + if (bufferHelper.isHostVisible() && + mRenderer->hasResourceUseFinished(bufferHelper.getResourceUse())) + { + uint8_t *src = nullptr; + ANGLE_TRY( + bufferVk->mapForReadAccessOnly(this, reinterpret_cast(&src))); + // Note: bufferOffset is not added here because mapImpl already adds it. + src += reinterpret_cast(indices); + const size_t byteCount = static_cast(elementArrayBuffer->getSize()) - + reinterpret_cast(indices); + BufferBindingDirty bindingDirty; + ANGLE_TRY(vertexArrayVk->convertIndexBufferCPU(this, indexType, byteCount, src, + &bindingDirty)); + ANGLE_TRY(bufferVk->unmapReadAccessOnly(this)); + } + else + { + ANGLE_TRY(vertexArrayVk->convertIndexBufferGPU(this, bufferVk, indices)); + } } + // The converted (uint8->uint16) index buffer always holds the requested + // index range starting at offset 0, regardless of whether the conversion + // was re-run on this draw or reused from a previous draw with the same + // |indices|. mCurrentIndexBufferOffset was unconditionally set to the GL + // |indices| offset above; if we leave it and DIRTY_BIT_INDEX_BUFFER is + // later injected by flushDirtyGraphicsRenderPass(), handleDirtyGraphicsIndexBuffer + // would bind the small converted buffer at the (large) GL offset, causing a + // VkDeviceSize underflow / OOB vkCmdBindIndexBuffer offset. mCurrentIndexBufferOffset = 0; } }