Commit be7049d7 by Jamie Madill Committed by Commit Bot

Vulkan: Redesign buffer descriptor set cache key.

Instead of writing the bitset masks, iterate up until the last active buffer. Write zeros instead of skipping spaces. This is a bit simpler to implement and also fixes a bug where empty buffers could cause us to write invalid handles. Bug: angleproject:5736 Change-Id: I785ef18ef5ae45109ec7d6e0b079b79a9984a1f8 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2837848 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent cddb2003
...@@ -292,27 +292,48 @@ egl::ContextPriority GetContextPriority(const gl::State &state) ...@@ -292,27 +292,48 @@ egl::ContextPriority GetContextPriority(const gl::State &state)
template <typename MaskT> template <typename MaskT>
void AppendBufferVectorToDesc(vk::ShaderBuffersDescriptorDesc *desc, void AppendBufferVectorToDesc(vk::ShaderBuffersDescriptorDesc *desc,
const gl::BufferVector &buffers, const gl::BufferVector &buffers,
const MaskT &mask, const MaskT &buffersMask,
bool appendOffset) bool appendOffset)
{ {
for (size_t bufferIndex : mask) if (buffersMask.any())
{ {
const gl::OffsetBindingPointer<gl::Buffer> &binding = buffers[bufferIndex]; typename MaskT::param_type lastBufferIndex = buffersMask.last();
const gl::Buffer *bufferGL = binding.get(); for (typename MaskT::param_type bufferIndex = 0; bufferIndex <= lastBufferIndex;
BufferVk *bufferVk = vk::GetImpl(bufferGL); ++bufferIndex)
vk::BufferSerial bufferSerial = bufferVk->getBuffer().getBufferSerial();
desc->appendBufferSerial(bufferSerial);
ASSERT(static_cast<uint64_t>(binding.getSize()) <=
static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()));
desc->append32BitValue(static_cast<uint32_t>(binding.getSize()));
if (appendOffset)
{ {
ASSERT(static_cast<uint64_t>(binding.getOffset()) < const gl::OffsetBindingPointer<gl::Buffer> &binding = buffers[bufferIndex];
const gl::Buffer *bufferGL = binding.get();
if (!bufferGL)
{
desc->append32BitValue(0);
continue;
}
BufferVk *bufferVk = vk::GetImpl(bufferGL);
if (!bufferVk->isBufferValid())
{
desc->append32BitValue(0);
continue;
}
vk::BufferSerial bufferSerial = bufferVk->getBuffer().getBufferSerial();
desc->appendBufferSerial(bufferSerial);
ASSERT(static_cast<uint64_t>(binding.getSize()) <=
static_cast<uint64_t>(std::numeric_limits<uint32_t>::max())); static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()));
desc->append32BitValue(static_cast<uint32_t>(binding.getOffset())); desc->append32BitValue(static_cast<uint32_t>(binding.getSize()));
if (appendOffset)
{
ASSERT(static_cast<uint64_t>(binding.getOffset()) <
static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()));
desc->append32BitValue(static_cast<uint32_t>(binding.getOffset()));
}
} }
} }
desc->append32BitValue(std::numeric_limits<uint32_t>::max());
} }
} // anonymous namespace } // anonymous namespace
...@@ -3939,20 +3960,6 @@ angle::Result ContextVk::invalidateCurrentShaderResources() ...@@ -3939,20 +3960,6 @@ angle::Result ContextVk::invalidateCurrentShaderResources()
{ {
mShaderBuffersDescriptorDesc.reset(); mShaderBuffersDescriptorDesc.reset();
#if defined(ANGLE_IS_64_BIT_CPU)
mShaderBuffersDescriptorDesc.append64BitValue(mState.getUniformBuffersMask().bits(0));
mShaderBuffersDescriptorDesc.append64BitValue(mState.getUniformBuffersMask().bits(1));
mShaderBuffersDescriptorDesc.append64BitValue(mState.getShaderStorageBuffersMask().bits());
mShaderBuffersDescriptorDesc.append64BitValue(mState.getAtomicCounterBuffersMask().bits());
#else
mShaderBuffersDescriptorDesc.append32BitValue(mState.getUniformBuffersMask().bits(0));
mShaderBuffersDescriptorDesc.append32BitValue(mState.getUniformBuffersMask().bits(1));
mShaderBuffersDescriptorDesc.append32BitValue(mState.getUniformBuffersMask().bits(2));
mShaderBuffersDescriptorDesc.append32BitValue(mState.getShaderStorageBuffersMask().bits(0));
mShaderBuffersDescriptorDesc.append32BitValue(mState.getShaderStorageBuffersMask().bits(1));
mShaderBuffersDescriptorDesc.append32BitValue(mState.getAtomicCounterBuffersMask().bits());
#endif // defined(ANGLE_IS_64_BIT_CPU)
ProgramExecutableVk *executableVk = nullptr; ProgramExecutableVk *executableVk = nullptr;
if (mState.getProgram()) if (mState.getProgram())
{ {
......
...@@ -3349,6 +3349,46 @@ void main(void){ ...@@ -3349,6 +3349,46 @@ void main(void){
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Tests rendering with a bound, unreferenced UBO that has no data. Covers a paticular back-end bug.
TEST_P(UniformBufferTest, EmptyUnusedUniformBuffer)
{
constexpr GLuint kBasicUBOIndex = 0;
constexpr GLuint kEmptyUBOIndex = 1;
// Create two UBOs. One is empty and the other is used.
constexpr GLfloat basicUBOData[4] = {1.0, 2.0, 3.0, 4.0};
GLBuffer basicUBO;
glBindBuffer(GL_UNIFORM_BUFFER, basicUBO);
glBufferData(GL_UNIFORM_BUFFER, sizeof(basicUBOData), basicUBOData, GL_STATIC_READ);
glBindBufferBase(GL_UNIFORM_BUFFER, kBasicUBOIndex, basicUBO);
GLBuffer emptyUBO;
glBindBufferBase(GL_UNIFORM_BUFFER, kEmptyUBOIndex, emptyUBO);
// Create a simple UBO program.
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
uniform basicBlock {
vec4 basicVec4;
};
out vec4 outColor;
void main() {
if (basicVec4 == vec4(1, 2, 3, 4)) {
outColor = vec4(0, 1, 0, 1);
} else {
outColor = vec4(1, 0, 0, 1);
}
})";
// Draw and check result. Should not crash.
ANGLE_GL_PROGRAM(uboProgram, essl3_shaders::vs::Simple(), kFS);
drawQuad(uboProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniformBufferTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniformBufferTest);
ANGLE_INSTANTIATE_TEST_ES3(UniformBufferTest); ANGLE_INSTANTIATE_TEST_ES3(UniformBufferTest);
......
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