blob: de04ea52a2bba46f37ece11236529c63127cccc7 [file] [log] [blame]
Jamie Madill9e54b5a2016-05-25 12:57:39 -04001//
2// Copyright 2016 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// VertexArrayVk.cpp:
7// Implements the class methods for VertexArrayVk.
8//
9
10#include "libANGLE/renderer/vulkan/VertexArrayVk.h"
11
12#include "common/debug.h"
13
Jamie Madillc564c072017-06-01 12:45:42 -040014#include "libANGLE/Context.h"
Jamie Madillbd159f02017-10-09 19:39:06 -040015#include "libANGLE/renderer/vulkan/BufferVk.h"
Jamie Madill49ac74b2017-12-21 14:42:33 -050016#include "libANGLE/renderer/vulkan/CommandBufferNode.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040017#include "libANGLE/renderer/vulkan/ContextVk.h"
Jamie Madill3c424b42018-01-19 12:35:09 -050018#include "libANGLE/renderer/vulkan/vk_format_utils.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040019
Jamie Madill9e54b5a2016-05-25 12:57:39 -040020namespace rx
21{
22
Jamie Madillbd159f02017-10-09 19:39:06 -040023VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state)
24 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050025 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050026 mCurrentArrayBufferOffsets{},
Jamie Madillda854a22017-11-30 17:24:21 -050027 mCurrentArrayBufferResources{},
Jamie Madill112a3a82018-01-23 13:04:06 -050028 mCurrentElementArrayBufferResource(nullptr)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040029{
Jamie Madillda854a22017-11-30 17:24:21 -050030 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -050031 mCurrentArrayBufferOffsets.fill(0);
Jamie Madillda854a22017-11-30 17:24:21 -050032 mCurrentArrayBufferResources.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -050033
34 mPackedInputBindings.fill({0, 0});
35 mPackedInputAttributes.fill({0, 0, 0});
Jamie Madill9e54b5a2016-05-25 12:57:39 -040036}
37
Jamie Madillacf2f3a2017-11-21 19:22:44 -050038VertexArrayVk::~VertexArrayVk()
39{
40}
41
Jamie Madill4928b7c2017-06-20 12:57:39 -040042void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040043{
44}
45
Frank Henigman17448952017-01-05 15:48:26 -050046gl::Error VertexArrayVk::streamVertexData(ContextVk *context,
47 StreamingBuffer *stream,
48 int firstVertex,
49 int lastVertex)
50{
51 const auto &attribs = mState.getVertexAttributes();
52 const auto &bindings = mState.getVertexBindings();
53 const gl::Program *programGL = context->getGLState().getProgram();
54
55 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
56 // un-interleaved, wasting space and copying time. Consider improving on that.
57 for (auto attribIndex : programGL->getActiveAttribLocationsMask())
58 {
59 const auto &attrib = attribs[attribIndex];
60 const auto &binding = bindings[attrib.bindingIndex];
61 gl::Buffer *bufferGL = binding.getBuffer().get();
62
63 if (attrib.enabled && !bufferGL)
64 {
65 // TODO(fjhenigman): Work with more formats than just GL_FLOAT.
66 if (attrib.type != GL_FLOAT)
67 {
68 UNIMPLEMENTED();
69 return gl::InternalError();
70 }
71
72 // Only [firstVertex, lastVertex] is needed by the upcoming draw so that
73 // is all we copy, but we allocate space for [0, lastVertex] so indexing
74 // will work. If we don't start at zero all the indices will be off.
75 // TODO(fjhenigman): See if we can account for indices being off by adjusting
76 // the offset, thus avoiding wasted memory.
77 const size_t firstByte = firstVertex * binding.getStride();
78 const size_t lastByte =
79 lastVertex * binding.getStride() + gl::ComputeVertexAttributeTypeSize(attrib);
80 uint8_t *dst = nullptr;
81 ANGLE_TRY(stream->allocate(context, lastByte, &dst,
82 &mCurrentArrayBufferHandles[attribIndex],
83 &mCurrentArrayBufferOffsets[attribIndex]));
84 memcpy(dst + firstByte, static_cast<const uint8_t *>(attrib.pointer) + firstByte,
85 lastByte - firstByte);
86 }
87 }
88
89 ANGLE_TRY(stream->flush(context));
90 return gl::NoError();
91}
92
Jamie Madillc564c072017-06-01 12:45:42 -040093void VertexArrayVk::syncState(const gl::Context *context,
94 const gl::VertexArray::DirtyBits &dirtyBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -040095{
96 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -040097
Jamie Madillbd159f02017-10-09 19:39:06 -040098 // Invalidate current pipeline.
Jamie Madillacf2f3a2017-11-21 19:22:44 -050099 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill49ac74b2017-12-21 14:42:33 -0500100 contextVk->onVertexArrayChange();
Jamie Madillbd159f02017-10-09 19:39:06 -0400101
102 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
103 // TODO(jmadill): Handle buffer storage changes.
104 const auto &attribs = mState.getVertexAttributes();
105 const auto &bindings = mState.getVertexBindings();
106
107 for (auto dirtyBit : dirtyBits)
108 {
109 if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
Jamie Madillda854a22017-11-30 17:24:21 -0500110 {
111 gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
112 if (bufferGL)
113 {
114 mCurrentElementArrayBufferResource = vk::GetImpl(bufferGL);
115 }
116 else
117 {
118 mCurrentElementArrayBufferResource = nullptr;
119 }
Jamie Madillbd159f02017-10-09 19:39:06 -0400120 continue;
Jamie Madillda854a22017-11-30 17:24:21 -0500121 }
Jamie Madillbd159f02017-10-09 19:39:06 -0400122
123 size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
124
Jamie Madill112a3a82018-01-23 13:04:06 -0500125 // Invalidate the input description for pipelines.
126 mDirtyPackedInputs.set(attribIndex);
127
Jamie Madillbd159f02017-10-09 19:39:06 -0400128 const auto &attrib = attribs[attribIndex];
129 const auto &binding = bindings[attrib.bindingIndex];
Jamie Madillebf72992017-10-13 14:09:45 -0400130
Jamie Madillbd159f02017-10-09 19:39:06 -0400131 if (attrib.enabled)
132 {
133 gl::Buffer *bufferGL = binding.getBuffer().get();
134
135 if (bufferGL)
136 {
Jamie Madillda854a22017-11-30 17:24:21 -0500137 BufferVk *bufferVk = vk::GetImpl(bufferGL);
138 mCurrentArrayBufferResources[attribIndex] = bufferVk;
139 mCurrentArrayBufferHandles[attribIndex] = bufferVk->getVkBuffer().getHandle();
Jamie Madillbd159f02017-10-09 19:39:06 -0400140 }
141 else
142 {
Jamie Madillda854a22017-11-30 17:24:21 -0500143 mCurrentArrayBufferResources[attribIndex] = nullptr;
144 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
Jamie Madillbd159f02017-10-09 19:39:06 -0400145 }
Frank Henigman17448952017-01-05 15:48:26 -0500146 // TODO(jmadill): Offset handling. Assume zero for now.
147 mCurrentArrayBufferOffsets[attribIndex] = 0;
Jamie Madillbd159f02017-10-09 19:39:06 -0400148 }
149 else
150 {
151 UNIMPLEMENTED();
152 }
153 }
154}
155
Jamie Madillda854a22017-11-30 17:24:21 -0500156const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const
Jamie Madillbd159f02017-10-09 19:39:06 -0400157{
Jamie Madillda854a22017-11-30 17:24:21 -0500158 return mCurrentArrayBufferHandles;
Jamie Madillbd159f02017-10-09 19:39:06 -0400159}
160
Frank Henigman17448952017-01-05 15:48:26 -0500161const gl::AttribArray<VkDeviceSize> &VertexArrayVk::getCurrentArrayBufferOffsets() const
162{
163 return mCurrentArrayBufferOffsets;
164}
165
Jamie Madill49ac74b2017-12-21 14:42:33 -0500166void VertexArrayVk::updateDrawDependencies(vk::CommandBufferNode *readNode,
167 const gl::AttributesMask &activeAttribsMask,
168 Serial serial,
169 DrawType drawType)
Jamie Madillbd159f02017-10-09 19:39:06 -0400170{
Jamie Madillda854a22017-11-30 17:24:21 -0500171 // Handle the bound array buffers.
Jamie Madillbd159f02017-10-09 19:39:06 -0400172 for (auto attribIndex : activeAttribsMask)
173 {
Frank Henigman17448952017-01-05 15:48:26 -0500174 if (mCurrentArrayBufferResources[attribIndex])
175 mCurrentArrayBufferResources[attribIndex]->onReadResource(readNode, serial);
Jamie Madillda854a22017-11-30 17:24:21 -0500176 }
177
178 // Handle the bound element array buffer.
179 if (drawType == DrawType::Elements)
180 {
181 ASSERT(mCurrentElementArrayBufferResource);
Jamie Madill0e654542018-02-07 14:50:06 -0500182 mCurrentElementArrayBufferResource->onReadResource(readNode, serial);
Jamie Madillbd159f02017-10-09 19:39:06 -0400183 }
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400184}
185
Jamie Madill112a3a82018-01-23 13:04:06 -0500186void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400187{
Jamie Madill112a3a82018-01-23 13:04:06 -0500188 updatePackedInputDescriptions();
189 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400190}
191
Jamie Madill112a3a82018-01-23 13:04:06 -0500192void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400193{
Jamie Madill112a3a82018-01-23 13:04:06 -0500194 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400195 {
196 return;
197 }
198
199 const auto &attribs = mState.getVertexAttributes();
200 const auto &bindings = mState.getVertexBindings();
201
Jamie Madill112a3a82018-01-23 13:04:06 -0500202 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400203 {
204 const auto &attrib = attribs[attribIndex];
205 const auto &binding = bindings[attrib.bindingIndex];
206 if (attrib.enabled)
207 {
Jamie Madill112a3a82018-01-23 13:04:06 -0500208 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400209 }
210 else
211 {
212 UNIMPLEMENTED();
213 }
214 }
215
Jamie Madill112a3a82018-01-23 13:04:06 -0500216 mDirtyPackedInputs.reset();
217}
218
219void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
220 const gl::VertexBinding &binding,
221 const gl::VertexAttribute &attrib)
222{
223 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
224
225 size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
226 ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
227
228 bindingDesc.stride = static_cast<uint16_t>(attribSize);
229 bindingDesc.inputRate = static_cast<uint16_t>(
230 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
231
232 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
233 VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
234 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
235
236 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
237 attribDesc.format = static_cast<uint16_t>(vkFormat);
238 attribDesc.location = static_cast<uint16_t>(attribIndex);
239 attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
Jamie Madillebf72992017-10-13 14:09:45 -0400240}
241
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400242} // namespace rx