| // |
| // Copyright 2016 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // VertexArrayVk.cpp: |
| // Implements the class methods for VertexArrayVk. |
| // |
| |
| #include "libANGLE/renderer/vulkan/VertexArrayVk.h" |
| |
| #include "common/debug.h" |
| |
| #include "libANGLE/Context.h" |
| #include "libANGLE/renderer/vulkan/BufferVk.h" |
| #include "libANGLE/renderer/vulkan/CommandBufferNode.h" |
| #include "libANGLE/renderer/vulkan/ContextVk.h" |
| #include "libANGLE/renderer/vulkan/vk_format_utils.h" |
| |
| namespace rx |
| { |
| |
| VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state) |
| : VertexArrayImpl(state), |
| mCurrentArrayBufferHandles{}, |
| mCurrentArrayBufferResources{}, |
| mCurrentElementArrayBufferResource(nullptr) |
| { |
| mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE); |
| mCurrentArrayBufferResources.fill(nullptr); |
| |
| mPackedInputBindings.fill({0, 0}); |
| mPackedInputAttributes.fill({0, 0, 0}); |
| } |
| |
| VertexArrayVk::~VertexArrayVk() |
| { |
| } |
| |
| void VertexArrayVk::destroy(const gl::Context *context) |
| { |
| } |
| |
| void VertexArrayVk::syncState(const gl::Context *context, |
| const gl::VertexArray::DirtyBits &dirtyBits) |
| { |
| ASSERT(dirtyBits.any()); |
| |
| // Invalidate current pipeline. |
| ContextVk *contextVk = vk::GetImpl(context); |
| contextVk->onVertexArrayChange(); |
| |
| // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes. |
| // TODO(jmadill): Handle buffer storage changes. |
| const auto &attribs = mState.getVertexAttributes(); |
| const auto &bindings = mState.getVertexBindings(); |
| |
| for (auto dirtyBit : dirtyBits) |
| { |
| if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER) |
| { |
| gl::Buffer *bufferGL = mState.getElementArrayBuffer().get(); |
| if (bufferGL) |
| { |
| mCurrentElementArrayBufferResource = vk::GetImpl(bufferGL); |
| } |
| else |
| { |
| mCurrentElementArrayBufferResource = nullptr; |
| } |
| continue; |
| } |
| |
| size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit); |
| |
| // Invalidate the input description for pipelines. |
| mDirtyPackedInputs.set(attribIndex); |
| |
| const auto &attrib = attribs[attribIndex]; |
| const auto &binding = bindings[attrib.bindingIndex]; |
| |
| if (attrib.enabled) |
| { |
| gl::Buffer *bufferGL = binding.getBuffer().get(); |
| |
| if (bufferGL) |
| { |
| BufferVk *bufferVk = vk::GetImpl(bufferGL); |
| mCurrentArrayBufferResources[attribIndex] = bufferVk; |
| mCurrentArrayBufferHandles[attribIndex] = bufferVk->getVkBuffer().getHandle(); |
| } |
| else |
| { |
| mCurrentArrayBufferResources[attribIndex] = nullptr; |
| mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE; |
| } |
| } |
| else |
| { |
| UNIMPLEMENTED(); |
| } |
| } |
| } |
| |
| const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const |
| { |
| return mCurrentArrayBufferHandles; |
| } |
| |
| void VertexArrayVk::updateDrawDependencies(vk::CommandBufferNode *readNode, |
| const gl::AttributesMask &activeAttribsMask, |
| Serial serial, |
| DrawType drawType) |
| { |
| // Handle the bound array buffers. |
| for (auto attribIndex : activeAttribsMask) |
| { |
| ASSERT(mCurrentArrayBufferResources[attribIndex]); |
| mCurrentArrayBufferResources[attribIndex]->setReadNode(readNode, serial); |
| } |
| |
| // Handle the bound element array buffer. |
| if (drawType == DrawType::Elements) |
| { |
| ASSERT(mCurrentElementArrayBufferResource); |
| mCurrentElementArrayBufferResource->setReadNode(readNode, serial); |
| } |
| } |
| |
| void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc) |
| { |
| updatePackedInputDescriptions(); |
| pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes); |
| } |
| |
| void VertexArrayVk::updatePackedInputDescriptions() |
| { |
| if (!mDirtyPackedInputs.any()) |
| { |
| return; |
| } |
| |
| const auto &attribs = mState.getVertexAttributes(); |
| const auto &bindings = mState.getVertexBindings(); |
| |
| for (auto attribIndex : mDirtyPackedInputs) |
| { |
| const auto &attrib = attribs[attribIndex]; |
| const auto &binding = bindings[attrib.bindingIndex]; |
| if (attrib.enabled) |
| { |
| updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib); |
| } |
| else |
| { |
| UNIMPLEMENTED(); |
| } |
| } |
| |
| 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 |