Commit 5a4c932a by Jamie Madill Committed by Commit Bot

Vulkan: Implement "default" vertex attributes.

Rendering from disabled attributes is implemented using small dynamic buffers. The buffers use a stride of zero so the same vertex data is pulled for every index. This fixes all the disable attribute tests in dEQP. Bug: angleproject:2444 Change-Id: I04fe139076da3e3ff723bed8eb17e333b4cb0ddf Reviewed-on: https://chromium-review.googlesource.com/1136664 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 419acc8f
......@@ -58,8 +58,18 @@ constexpr gl::Rectangle kMaxSizedScissor(0,
constexpr VkColorComponentFlags kAllColorChannelsMask =
(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT);
constexpr VkBufferUsageFlags kVertexBufferUsage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
constexpr size_t kDefaultValueSize = sizeof(float) * 4;
constexpr size_t kDefaultBufferSize = kDefaultValueSize * 16;
} // anonymous namespace
// std::array only uses aggregate init. Thus we make a helper macro to reduce on code duplication.
#define INIT \
{ \
kVertexBufferUsage, kDefaultBufferSize \
}
ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
: ContextImpl(state),
vk::Context(renderer),
......@@ -69,7 +79,9 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
mClearColorMask(kAllColorChannelsMask),
mFlipYForCurrentSurface(false),
mDriverUniformsBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, sizeof(DriverUniforms) * 16),
mDriverUniformsDescriptorSet(VK_NULL_HANDLE)
mDriverUniformsDescriptorSet(VK_NULL_HANDLE),
mDefaultAttribBuffers{{INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT,
INIT, INIT, INIT, INIT}}
{
memset(&mClearColorValue, 0, sizeof(mClearColorValue));
memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
......@@ -87,6 +99,11 @@ void ContextVk::onDestroy(const gl::Context *context)
{
descriptorPool.destroy(getDevice());
}
for (vk::DynamicBuffer &defaultBuffer : mDefaultAttribBuffers)
{
defaultBuffer.destroy(getDevice());
}
}
gl::Error ContextVk::getIncompleteTexture(const gl::Context *context,
......@@ -120,6 +137,12 @@ gl::Error ContextVk::initialize()
mPipelineDesc.reset(new vk::PipelineDesc());
mPipelineDesc->initDefaults();
// Initialize current value/default attribute buffers.
for (vk::DynamicBuffer &buffer : mDefaultAttribBuffers)
{
buffer.init(1, mRenderer);
}
return gl::NoError();
}
......@@ -188,6 +211,11 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
mCurrentDrawMode = drawCallParams.mode();
}
if (mDirtyDefaultAttribs.any())
{
ANGLE_TRY(updateDefaultAttributes());
}
if (!mCurrentPipeline)
{
ANGLE_TRY(initPipeline(drawCallParams));
......@@ -598,8 +626,14 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt
case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
break;
case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
{
mVertexArrayBindingHasChanged = true;
// Note that we should implement faster dirty bits for VAO changes in ES 3.0.
// This might require keeping separate dirty info for the data and state.
mDirtyDefaultAttribs.set();
break;
}
case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
break;
case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
......@@ -639,7 +673,14 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt
case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
break;
case gl::State::DIRTY_BIT_CURRENT_VALUES:
{
for (size_t attribIndex : glState.getAndResetDirtyCurrentValues())
{
invalidateDefaultAttribute(attribIndex);
}
break;
}
break;
default:
UNREACHABLE();
break;
......@@ -968,4 +1009,55 @@ const gl::ActiveTextureArray<TextureVk *> &ContextVk::getActiveTextures() const
{
return mActiveTextures;
}
void ContextVk::invalidateDefaultAttribute(size_t attribIndex)
{
mDirtyDefaultAttribs.set(attribIndex);
}
angle::Result ContextVk::updateDefaultAttributes()
{
ASSERT(mDirtyDefaultAttribs.any());
const gl::Program *program = mState.getState().getProgram();
ASSERT(program);
const gl::AttributesMask &programAttribs = program->getActiveAttribLocationsMask();
const gl::AttributesMask &attribsToUpdate = (programAttribs & mDirtyDefaultAttribs);
for (size_t attribIndex : attribsToUpdate)
{
ANGLE_TRY(updateDefaultAttribute(attribIndex))
}
mDirtyDefaultAttribs &= ~attribsToUpdate;
return angle::Result::Continue();
}
angle::Result ContextVk::updateDefaultAttribute(size_t attribIndex)
{
vk::DynamicBuffer &defaultBuffer = mDefaultAttribBuffers[attribIndex];
defaultBuffer.releaseRetainedBuffers(mRenderer);
uint8_t *ptr;
VkBuffer bufferHandle = VK_NULL_HANDLE;
uint32_t offset = 0;
ANGLE_TRY(
defaultBuffer.allocate(this, kDefaultValueSize, &ptr, &bufferHandle, &offset, nullptr));
const gl::State &glState = mState.getState();
const gl::VertexAttribCurrentValueData &defaultValue =
glState.getVertexAttribCurrentValues()[attribIndex];
ASSERT(defaultValue.Type == GL_FLOAT);
memcpy(ptr, defaultValue.FloatValues, kDefaultValueSize);
ANGLE_TRY(defaultBuffer.flush(this));
VertexArrayVk *vertexArrayVk = vk::GetImpl(glState.getVertexArray());
vertexArrayVk->updateDefaultAttrib(mRenderer, attribIndex, bufferHandle, offset);
return angle::Result::Continue();
}
} // namespace rx
......@@ -157,6 +157,7 @@ class ContextVk : public ContextImpl, public vk::Context
const FeaturesVk &getFeatures() const;
void invalidateCurrentPipeline();
void invalidateDefaultAttribute(size_t attribIndex);
vk::DynamicDescriptorPool *getDynamicDescriptorPool(uint32_t descriptorSetIndex);
......@@ -185,6 +186,8 @@ class ContextVk : public ContextImpl, public vk::Context
angle::Result updateDriverUniforms(const gl::State &glState);
gl::Error updateActiveTextures(const gl::Context *context);
angle::Result updateDefaultAttributes();
angle::Result updateDefaultAttribute(size_t attribIndex);
vk::PipelineAndSerial *mCurrentPipeline;
gl::PrimitiveMode mCurrentDrawMode;
......@@ -230,6 +233,10 @@ class ContextVk : public ContextImpl, public vk::Context
// This cache should also probably include the texture index (shader location) and array
// index (also in the shader). This info is used in the descriptor update step.
gl::ActiveTextureArray<TextureVk *> mActiveTextures;
// "Current Value" aka default vertex attribute state.
gl::AttributesMask mDirtyDefaultAttribs;
gl::AttribArray<vk::DynamicBuffer> mDefaultAttribBuffers;
};
} // namespace rx
......
......@@ -147,16 +147,16 @@ angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
return angle::Result::Continue();
}
#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
syncDirtyAttrib(rendererVk, attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
invalidatePipeline = true; \
#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
syncDirtyAttrib(contextVk, attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
invalidatePipeline = true; \
break;
#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
syncDirtyAttrib(rendererVk, attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
invalidatePipeline = true; \
#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
syncDirtyAttrib(contextVk, attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
invalidatePipeline = true; \
break;
#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
......@@ -173,8 +173,7 @@ gl::Error VertexArrayVk::syncState(const gl::Context *context,
bool invalidatePipeline = false;
// Invalidate current pipeline.
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *rendererVk = contextVk->getRenderer();
ContextVk *contextVk = vk::GetImpl(context);
// Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
// TODO(jmadill): Handle buffer storage changes.
......@@ -233,7 +232,7 @@ gl::Error VertexArrayVk::syncState(const gl::Context *context,
return gl::NoError();
}
void VertexArrayVk::syncDirtyAttrib(const RendererVk *renderer,
void VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
size_t attribIndex)
......@@ -241,6 +240,8 @@ void VertexArrayVk::syncDirtyAttrib(const RendererVk *renderer,
// Invalidate the input description for pipelines.
mDirtyPackedInputs.set(attribIndex);
RendererVk *renderer = contextVk->getRenderer();
if (attrib.enabled)
{
gl::Buffer *bufferGL = binding.getBuffer().get();
......@@ -273,7 +274,15 @@ void VertexArrayVk::syncDirtyAttrib(const RendererVk *renderer,
}
else
{
WARN() << "Default vertex attributes unimplemented. http://anglebug.com/2444";
contextVk->invalidateDefaultAttribute(attribIndex);
// These will be filled out by the ContextVk.
mCurrentArrayBufferResources[attribIndex] = nullptr;
mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
mCurrentArrayBufferOffsets[attribIndex] = 0;
mCurrentArrayBufferStrides[attribIndex] = 0;
mCurrentArrayBufferFormats[attribIndex] =
&renderer->getFormat(angle::Format::ID::R32G32B32A32_FLOAT);
}
}
......@@ -326,7 +335,14 @@ void VertexArrayVk::updatePackedInputDescriptions()
}
else
{
WARN() << "Default vertex attributes unimplemented. http://anglebug.com/2444";
vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
bindingDesc.stride = 0;
bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
attribDesc.format = static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
attribDesc.location = static_cast<uint16_t>(attribIndex);
attribDesc.offset = 0;
}
}
......@@ -581,4 +597,21 @@ gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
return gl::NoError();
}
void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
size_t attribIndex,
VkBuffer bufferHandle,
uint32_t offset)
{
if (!mState.getEnabledAttributesMask().test(attribIndex))
{
mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
mCurrentArrayBufferOffsets[attribIndex] = offset;
mCurrentArrayBufferResources[attribIndex] = nullptr;
mCurrentArrayBufferStrides[attribIndex] = 0;
mCurrentArrayBufferFormats[attribIndex] =
&renderer->getFormat(angle::Format::ID::R32G32B32A32_FIXED);
mDirtyPackedInputs.set(attribIndex);
}
}
} // namespace rx
......@@ -60,6 +60,11 @@ class VertexArrayVk : public VertexArrayImpl
vk::CommandBuffer *commandBuffer,
bool shouldApplyVertexArray);
void updateDefaultAttrib(RendererVk *renderer,
size_t attribIndex,
VkBuffer bufferHandle,
uint32_t offset);
private:
// This will update any dirty packed input descriptions, regardless if they're used by the
// active program. This could lead to slight inefficiencies when the app would repeatedly
......@@ -93,7 +98,7 @@ class VertexArrayVk : public VertexArrayImpl
vk::CommandBuffer *commandBuffer,
bool newCommandBuffer);
void syncDirtyAttrib(const RendererVk *renderer,
void syncDirtyAttrib(ContextVk *contextVk,
const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
size_t attribIndex);
......
......@@ -262,23 +262,9 @@
2599 VULKAN : dEQP-GLES2.functional.rasterization.limits.points = SKIP
2601 VULKAN : dEQP-GLES2.functional.clipping.* = SKIP
2353 VULKAN : dEQP-GLES2.functional.polygon_offset.* = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_arrays.points.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_arrays.triangles.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_arrays.triangle_fan.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_arrays.triangle_strip.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_arrays.lines.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_arrays.line_strip.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_arrays.line_loop.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_elements.indices.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_elements.points.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_elements.triangles.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_elements.triangle_fan.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_elements.triangle_strip.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_elements.lines.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_elements.line_strip.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.draw_elements.line_loop.default_attribute = SKIP
2444 VULKAN : dEQP-GLES2.functional.draw.random.* = SKIP
2444 VULKAN : dEQP-GLES2.functional.default_vertex_attrib.* = SKIP
// Random draw tests often require non-float vertex data.
2405 VULKAN : dEQP-GLES2.functional.draw.random.* = SKIP
// fixed format vertex data
2405 VULKAN : dEQP-GLES2.functional.vertex_arrays.multiple_attributes.input_types.3_byte2_vec2_byte2_vec2_fixed* = SKIP
......
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