Commit 112a3a8e by Jamie Madill Committed by Commit Bot

Vulkan: De-couple Program from VertexArrayVk dirtyiness.

The VertexArrayVk is responsible for filling out the packed shader input info in ANGLE's packed PipelineDesc info structure. This packed info structure is used for Pipeline init and caching lookup. The prior design had this info depend on the active inputs in the current Program. This was undesirable because then, on a Program change, the ContextVk would have to call into the VertexArrayVk to invalidate this info. Instead, keep a working copy of the VertexArrayVk bits and only update the bits corresponding to dirty vertex attributes. This simplifies the cached state management a little bit for ContextVk. This also means we don't have to update the cached copy in the VertexArray on a change in VertexArray binding. Bug: angleproject:2163 Change-Id: I5ba74535367aed74957d17bdc61f882508562d0e Reviewed-on: https://chromium-review.googlesource.com/881703 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org>
parent adcf0ae6
...@@ -137,8 +137,8 @@ gl::Error ContextVk::initPipeline(const gl::Context *context) ...@@ -137,8 +137,8 @@ gl::Error ContextVk::initPipeline(const gl::Context *context)
// Ensure the topology of the pipeline description is updated. // Ensure the topology of the pipeline description is updated.
mPipelineDesc->updateTopology(mCurrentDrawMode); mPipelineDesc->updateTopology(mCurrentDrawMode);
// Ensure the attribs and bindings are updated. // Copy over the latest attrib and binding descriptions.
vertexArrayVk->updateVertexDescriptions(context, mPipelineDesc.get()); vertexArrayVk->getPackedInputDescriptions(mPipelineDesc.get());
// Ensure that the RenderPass description is updated. // Ensure that the RenderPass description is updated.
mPipelineDesc->updateRenderPassDesc(framebufferVk->getRenderPassDesc(context)); mPipelineDesc->updateRenderPassDesc(framebufferVk->getRenderPassDesc(context));
...@@ -549,12 +549,8 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -549,12 +549,8 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
WARN() << "DIRTY_BIT_RENDERBUFFER_BINDING unimplemented"; WARN() << "DIRTY_BIT_RENDERBUFFER_BINDING unimplemented";
break; break;
case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING: case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
{
VertexArrayVk *vertexArrayVk = vk::GetImpl(glState.getVertexArray());
vertexArrayVk->invalidateVertexDescriptions();
mVertexArrayDirty = true; mVertexArrayDirty = true;
break; break;
}
case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING: case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
WARN() << "DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING unimplemented"; WARN() << "DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING unimplemented";
break; break;
...@@ -568,11 +564,6 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -568,11 +564,6 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
{ {
ProgramVk *programVk = vk::GetImpl(glState.getProgram()); ProgramVk *programVk = vk::GetImpl(glState.getProgram());
mPipelineDesc->updateShaders(programVk); mPipelineDesc->updateShaders(programVk);
// Also invalidate the vertex descriptions cache in the Vertex Array.
VertexArrayVk *vertexArrayVk = vk::GetImpl(glState.getVertexArray());
vertexArrayVk->invalidateVertexDescriptions();
dirtyTextures = true; dirtyTextures = true;
break; break;
} }
......
...@@ -24,11 +24,13 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state) ...@@ -24,11 +24,13 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state)
: VertexArrayImpl(state), : VertexArrayImpl(state),
mCurrentArrayBufferHandles{}, mCurrentArrayBufferHandles{},
mCurrentArrayBufferResources{}, mCurrentArrayBufferResources{},
mCurrentElementArrayBufferResource(nullptr), mCurrentElementArrayBufferResource(nullptr)
mCurrentVertexDescsValid(false)
{ {
mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE); mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
mCurrentArrayBufferResources.fill(nullptr); mCurrentArrayBufferResources.fill(nullptr);
mPackedInputBindings.fill({0, 0});
mPackedInputAttributes.fill({0, 0, 0});
} }
VertexArrayVk::~VertexArrayVk() VertexArrayVk::~VertexArrayVk()
...@@ -49,9 +51,6 @@ void VertexArrayVk::syncState(const gl::Context *context, ...@@ -49,9 +51,6 @@ void VertexArrayVk::syncState(const gl::Context *context,
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
contextVk->onVertexArrayChange(); contextVk->onVertexArrayChange();
// Invalidate the vertex descriptions.
invalidateVertexDescriptions();
// Rebuild current attribute buffers cache. This will fail horribly if the buffer changes. // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
// TODO(jmadill): Handle buffer storage changes. // TODO(jmadill): Handle buffer storage changes.
const auto &attribs = mState.getVertexAttributes(); const auto &attribs = mState.getVertexAttributes();
...@@ -75,6 +74,9 @@ void VertexArrayVk::syncState(const gl::Context *context, ...@@ -75,6 +74,9 @@ void VertexArrayVk::syncState(const gl::Context *context,
size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit); size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
// Invalidate the input description for pipelines.
mDirtyPackedInputs.set(attribIndex);
const auto &attrib = attribs[attribIndex]; const auto &attrib = attribs[attribIndex];
const auto &binding = bindings[attrib.bindingIndex]; const auto &binding = bindings[attrib.bindingIndex];
...@@ -126,15 +128,15 @@ void VertexArrayVk::updateDrawDependencies(vk::CommandBufferNode *readNode, ...@@ -126,15 +128,15 @@ void VertexArrayVk::updateDrawDependencies(vk::CommandBufferNode *readNode,
} }
} }
void VertexArrayVk::invalidateVertexDescriptions() void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
{ {
mCurrentVertexDescsValid = false; updatePackedInputDescriptions();
pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
} }
void VertexArrayVk::updateVertexDescriptions(const gl::Context *context, void VertexArrayVk::updatePackedInputDescriptions()
vk::PipelineDesc *pipelineDesc)
{ {
if (mCurrentVertexDescsValid) if (!mDirtyPackedInputs.any())
{ {
return; return;
} }
...@@ -142,18 +144,13 @@ void VertexArrayVk::updateVertexDescriptions(const gl::Context *context, ...@@ -142,18 +144,13 @@ void VertexArrayVk::updateVertexDescriptions(const gl::Context *context,
const auto &attribs = mState.getVertexAttributes(); const auto &attribs = mState.getVertexAttributes();
const auto &bindings = mState.getVertexBindings(); const auto &bindings = mState.getVertexBindings();
const gl::Program *programGL = context->getGLState().getProgram(); for (auto attribIndex : mDirtyPackedInputs)
pipelineDesc->resetVertexInputState();
for (auto attribIndex : programGL->getActiveAttribLocationsMask())
{ {
const auto &attrib = attribs[attribIndex]; const auto &attrib = attribs[attribIndex];
const auto &binding = bindings[attrib.bindingIndex]; const auto &binding = bindings[attrib.bindingIndex];
if (attrib.enabled) if (attrib.enabled)
{ {
pipelineDesc->updateVertexInputInfo(static_cast<uint32_t>(attribIndex), binding, updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
attrib);
} }
else else
{ {
...@@ -161,7 +158,30 @@ void VertexArrayVk::updateVertexDescriptions(const gl::Context *context, ...@@ -161,7 +158,30 @@ void VertexArrayVk::updateVertexDescriptions(const gl::Context *context,
} }
} }
mCurrentVertexDescsValid = true; mDirtyPackedInputs.reset();
}
void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
const gl::VertexBinding &binding,
const gl::VertexAttribute &attrib)
{
vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
bindingDesc.stride = static_cast<uint16_t>(attribSize);
bindingDesc.inputRate = static_cast<uint16_t>(
binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
attribDesc.format = static_cast<uint16_t>(vkFormat);
attribDesc.location = static_cast<uint16_t>(attribIndex);
attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
} }
} // namespace rx } // namespace rx
...@@ -11,15 +11,10 @@ ...@@ -11,15 +11,10 @@
#define LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_ #define LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_
#include "libANGLE/renderer/VertexArrayImpl.h" #include "libANGLE/renderer/VertexArrayImpl.h"
#include "libANGLE/renderer/vulkan/vk_utils.h" #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
namespace rx namespace rx
{ {
namespace vk
{
class PipelineDesc;
} // namespace vk
class BufferVk; class BufferVk;
class VertexArrayVk : public VertexArrayImpl class VertexArrayVk : public VertexArrayImpl
...@@ -40,17 +35,28 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -40,17 +35,28 @@ class VertexArrayVk : public VertexArrayImpl
Serial serial, Serial serial,
DrawType drawType); DrawType drawType);
void invalidateVertexDescriptions(); void getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc);
void updateVertexDescriptions(const gl::Context *context, vk::PipelineDesc *pipelineDesc);
private: 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
// update vertex info for attributes the program doesn't use, (very silly edge case). The
// advantage is the cached state then doesn't depend on the Program, so doesn't have to be
// updated when the active Program changes.
void updatePackedInputDescriptions();
void updatePackedInputInfo(uint32_t attribIndex,
const gl::VertexBinding &binding,
const gl::VertexAttribute &attrib);
gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles; gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles;
gl::AttribArray<ResourceVk *> mCurrentArrayBufferResources; gl::AttribArray<ResourceVk *> mCurrentArrayBufferResources;
ResourceVk *mCurrentElementArrayBufferResource; ResourceVk *mCurrentElementArrayBufferResource;
// Keep a cache of binding and attribute descriptions for easy pipeline updates. // Keep a cache of binding and attribute descriptions for easy pipeline updates.
// TODO(jmadill): Update this when we support pipeline caching. // This is copied out of here into the pipeline description on a Context state change.
bool mCurrentVertexDescsValid; gl::AttributesMask mDirtyPackedInputs;
vk::VertexInputBindings mPackedInputBindings;
vk::VertexInputAttributes mPackedInputAttributes;
}; };
} // namespace rx } // namespace rx
......
...@@ -568,33 +568,11 @@ void PipelineDesc::updateViewport(const gl::Rectangle &viewport, float nearPlane ...@@ -568,33 +568,11 @@ void PipelineDesc::updateViewport(const gl::Rectangle &viewport, float nearPlane
mScissor.extent.height = viewport.height; mScissor.extent.height = viewport.height;
} }
void PipelineDesc::resetVertexInputState() void PipelineDesc::updateVertexInputInfo(const VertexInputBindings &bindings,
const VertexInputAttributes &attribs)
{ {
memset(&mVertexInputBindings, 0, sizeof(VertexInputBindings)); mVertexInputBindings = bindings;
memset(&mVertexInputAttribs, 0, sizeof(VertexInputAttributes)); mVertexInputAttribs = attribs;
}
void PipelineDesc::updateVertexInputInfo(uint32_t attribIndex,
const gl::VertexBinding &binding,
const gl::VertexAttribute &attrib)
{
PackedVertexInputBindingDesc &bindingDesc = mVertexInputBindings[attribIndex];
size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
bindingDesc.stride = static_cast<uint16_t>(attribSize);
bindingDesc.inputRate = static_cast<uint16_t>(
binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
PackedVertexInputAttributeDesc &attribDesc = mVertexInputAttribs[attribIndex];
attribDesc.format = static_cast<uint16_t>(vkFormat);
attribDesc.location = static_cast<uint16_t>(attribIndex);
attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
} }
void PipelineDesc::updateTopology(GLenum drawMode) void PipelineDesc::updateTopology(GLenum drawMode)
......
...@@ -264,10 +264,8 @@ class PipelineDesc final ...@@ -264,10 +264,8 @@ class PipelineDesc final
void updateShaders(ProgramVk *programVk); void updateShaders(ProgramVk *programVk);
// Vertex input state // Vertex input state
void resetVertexInputState(); void updateVertexInputInfo(const VertexInputBindings &bindings,
void updateVertexInputInfo(uint32_t attribIndex, const VertexInputAttributes &attribs);
const gl::VertexBinding &binding,
const gl::VertexAttribute &attrib);
// Input assembly info // Input assembly info
void updateTopology(GLenum drawMode); void updateTopology(GLenum drawMode);
......
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