blob: d13e6aa9c83cab845add84b956eceb379cc92b1d [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 Madill1f46bc12018-02-20 16:09:43 -050016#include "libANGLE/renderer/vulkan/CommandGraph.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040017#include "libANGLE/renderer/vulkan/ContextVk.h"
Jamie Madillc3755fc2018-04-05 08:39:13 -040018#include "libANGLE/renderer/vulkan/RendererVk.h"
Jamie Madill3c424b42018-01-19 12:35:09 -050019#include "libANGLE/renderer/vulkan/vk_format_utils.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040020
Jamie Madill9e54b5a2016-05-25 12:57:39 -040021namespace rx
22{
Jamie Madillc3755fc2018-04-05 08:39:13 -040023namespace
24{
25constexpr size_t kDynamicVertexDataSize = 1024 * 1024;
26constexpr size_t kDynamicIndexDataSize = 1024 * 8;
27} // anonymous namespace
Jamie Madill9e54b5a2016-05-25 12:57:39 -040028
Jamie Madillbd159f02017-10-09 19:39:06 -040029VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state)
30 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050031 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050032 mCurrentArrayBufferOffsets{},
Jamie Madillda854a22017-11-30 17:24:21 -050033 mCurrentArrayBufferResources{},
Jamie Madillc3755fc2018-04-05 08:39:13 -040034 mCurrentElementArrayBufferHandle(VK_NULL_HANDLE),
35 mCurrentElementArrayBufferOffset(0),
36 mCurrentElementArrayBufferResource(nullptr),
37 mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
38 mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Jamie Madillb8e39662018-04-04 11:41:42 -040039 mDirtyLineLoopTranslation(true),
Jamie Madillc3755fc2018-04-05 08:39:13 -040040 mVertexBuffersDirty(false),
41 mIndexBufferDirty(false)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040042{
Jamie Madillda854a22017-11-30 17:24:21 -050043 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -050044 mCurrentArrayBufferOffsets.fill(0);
Jamie Madillda854a22017-11-30 17:24:21 -050045 mCurrentArrayBufferResources.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -050046
47 mPackedInputBindings.fill({0, 0});
48 mPackedInputAttributes.fill({0, 0, 0});
Jamie Madillc3755fc2018-04-05 08:39:13 -040049
50 mDynamicVertexData.init(1);
51 mDynamicIndexData.init(1);
Jamie Madill9e54b5a2016-05-25 12:57:39 -040052}
53
Jamie Madillacf2f3a2017-11-21 19:22:44 -050054VertexArrayVk::~VertexArrayVk()
55{
56}
57
Jamie Madill4928b7c2017-06-20 12:57:39 -040058void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040059{
Jamie Madillc3755fc2018-04-05 08:39:13 -040060 VkDevice device = vk::GetImpl(context)->getRenderer()->getDevice();
61
62 mDynamicVertexData.destroy(device);
63 mDynamicIndexData.destroy(device);
Jamie Madill22f12fe2018-04-08 14:23:40 -040064 mLineLoopHelper.destroy(device);
Jamie Madill9e54b5a2016-05-25 12:57:39 -040065}
66
Jamie Madillc3755fc2018-04-05 08:39:13 -040067gl::Error VertexArrayVk::streamVertexData(RendererVk *renderer,
68 const gl::AttributesMask &attribsToStream,
Jamie Madill32fd63b2018-03-31 11:20:35 -040069 const gl::DrawCallParams &drawCallParams)
Frank Henigman17448952017-01-05 15:48:26 -050070{
Jamie Madillc3755fc2018-04-05 08:39:13 -040071 ASSERT(!attribsToStream.none());
72
Frank Henigman17448952017-01-05 15:48:26 -050073 const auto &attribs = mState.getVertexAttributes();
74 const auto &bindings = mState.getVertexBindings();
Frank Henigman17448952017-01-05 15:48:26 -050075
Jamie Madill32fd63b2018-03-31 11:20:35 -040076 const size_t lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
77
Frank Henigman17448952017-01-05 15:48:26 -050078 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
79 // un-interleaved, wasting space and copying time. Consider improving on that.
Jamie Madillb8e39662018-04-04 11:41:42 -040080 for (size_t attribIndex : attribsToStream)
Frank Henigman17448952017-01-05 15:48:26 -050081 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050082 const gl::VertexAttribute &attrib = attribs[attribIndex];
83 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
84 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
Frank Henigman17448952017-01-05 15:48:26 -050085
Frank Henigman6dd4a922018-03-02 16:35:13 -050086 // TODO(fjhenigman): Work with more formats than just GL_FLOAT.
87 if (attrib.type != GL_FLOAT)
Frank Henigman17448952017-01-05 15:48:26 -050088 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050089 UNIMPLEMENTED();
90 return gl::InternalError();
Frank Henigman17448952017-01-05 15:48:26 -050091 }
Frank Henigman6dd4a922018-03-02 16:35:13 -050092
93 // Only [firstVertex, lastVertex] is needed by the upcoming draw so that
94 // is all we copy, but we allocate space for [0, lastVertex] so indexing
95 // will work. If we don't start at zero all the indices will be off.
96 // TODO(fjhenigman): See if we can account for indices being off by adjusting
97 // the offset, thus avoiding wasted memory.
Jamie Madill32fd63b2018-03-31 11:20:35 -040098 const size_t firstByte = drawCallParams.firstVertex() * binding.getStride();
Frank Henigman6dd4a922018-03-02 16:35:13 -050099 const size_t lastByte =
100 lastVertex * binding.getStride() + gl::ComputeVertexAttributeTypeSize(attrib);
101 uint8_t *dst = nullptr;
Luc Ferron7a06ac12018-03-15 10:17:04 -0400102 uint32_t offset = 0;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400103 ANGLE_TRY(mDynamicVertexData.allocate(
104 renderer, lastByte, &dst, &mCurrentArrayBufferHandles[attribIndex], &offset, nullptr));
Luc Ferron7a06ac12018-03-15 10:17:04 -0400105 mCurrentArrayBufferOffsets[attribIndex] = static_cast<VkDeviceSize>(offset);
Frank Henigman6dd4a922018-03-02 16:35:13 -0500106 memcpy(dst + firstByte, static_cast<const uint8_t *>(attrib.pointer) + firstByte,
107 lastByte - firstByte);
Frank Henigman17448952017-01-05 15:48:26 -0500108 }
109
Jamie Madillc3755fc2018-04-05 08:39:13 -0400110 ANGLE_TRY(mDynamicVertexData.flush(renderer->getDevice()));
111 return gl::NoError();
112}
113
114gl::Error VertexArrayVk::streamIndexData(RendererVk *renderer,
115 const gl::DrawCallParams &drawCallParams)
116{
117 ASSERT(!mState.getElementArrayBuffer().get());
118
119 uint32_t offset = 0;
120
121 const GLsizei amount = sizeof(GLushort) * drawCallParams.indexCount();
122 GLubyte *dst = nullptr;
123
124 ANGLE_TRY(mDynamicIndexData.allocate(renderer, amount, &dst, &mCurrentElementArrayBufferHandle,
125 &offset, nullptr));
126 if (drawCallParams.type() == GL_UNSIGNED_BYTE)
127 {
128 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
129 // memory to a GLushort.
130 const GLubyte *in = static_cast<const GLubyte *>(drawCallParams.indices());
131 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
132 for (GLsizei index = 0; index < drawCallParams.indexCount(); index++)
133 {
134 expandedDst[index] = static_cast<GLushort>(in[index]);
135 }
136 }
137 else
138 {
139 memcpy(dst, drawCallParams.indices(), amount);
140 }
141 ANGLE_TRY(mDynamicIndexData.flush(renderer->getDevice()));
142
143 mCurrentElementArrayBufferOffset = offset;
Frank Henigman17448952017-01-05 15:48:26 -0500144 return gl::NoError();
145}
146
Jamie Madilla56467e2018-04-11 16:19:41 -0400147#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
148 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
149 syncDirtyAttrib(attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
150 invalidatePipeline = true; \
151 break;
152
153#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
154 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
155 syncDirtyAttrib(attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
156 invalidatePipeline = true; \
157 break;
158
159#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
160 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
161 break;
162
Frank Henigman0af5b862018-03-27 20:19:33 -0400163gl::Error VertexArrayVk::syncState(const gl::Context *context,
164 const gl::VertexArray::DirtyBits &dirtyBits,
165 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
166 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400167{
168 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400169
Jamie Madillc3755fc2018-04-05 08:39:13 -0400170 bool invalidatePipeline = false;
171
Jamie Madillbd159f02017-10-09 19:39:06 -0400172 // Invalidate current pipeline.
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500173 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400174
175 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
176 // TODO(jmadill): Handle buffer storage changes.
177 const auto &attribs = mState.getVertexAttributes();
178 const auto &bindings = mState.getVertexBindings();
179
Jamie Madill09463932018-04-04 05:26:59 -0400180 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400181 {
Jamie Madill09463932018-04-04 05:26:59 -0400182 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500183 {
Jamie Madill09463932018-04-04 05:26:59 -0400184 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500185 {
Jamie Madill09463932018-04-04 05:26:59 -0400186 gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
187 if (bufferGL)
188 {
Jamie Madillc3755fc2018-04-05 08:39:13 -0400189 BufferVk *bufferVk = vk::GetImpl(bufferGL);
190 mCurrentElementArrayBufferResource = bufferVk;
191 mCurrentElementArrayBufferHandle = bufferVk->getVkBuffer().getHandle();
192 mCurrentElementArrayBufferOffset = 0;
Jamie Madill09463932018-04-04 05:26:59 -0400193 }
194 else
195 {
196 mCurrentElementArrayBufferResource = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400197 mCurrentElementArrayBufferHandle = VK_NULL_HANDLE;
198 mCurrentElementArrayBufferOffset = 0;
Jamie Madill09463932018-04-04 05:26:59 -0400199 }
Jamie Madillb8e39662018-04-04 11:41:42 -0400200 mIndexBufferDirty = true;
201 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400202 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500203 }
Jamie Madill09463932018-04-04 05:26:59 -0400204
205 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400206 mLineLoopBufferFirstIndex.reset();
207 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400208 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400209 break;
210
Jamie Madilla56467e2018-04-11 16:19:41 -0400211 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
212 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
213 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
214
Jamie Madill09463932018-04-04 05:26:59 -0400215 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400216 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400217 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400218 }
219 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400220
Jamie Madillc3755fc2018-04-05 08:39:13 -0400221 if (invalidatePipeline)
222 {
223 mVertexBuffersDirty = true;
224 contextVk->invalidateCurrentPipeline();
225 }
226
Frank Henigman0af5b862018-03-27 20:19:33 -0400227 return gl::NoError();
Jamie Madillbd159f02017-10-09 19:39:06 -0400228}
229
Jamie Madilla56467e2018-04-11 16:19:41 -0400230void VertexArrayVk::syncDirtyAttrib(const gl::VertexAttribute &attrib,
231 const gl::VertexBinding &binding,
232 size_t attribIndex)
233{
234 // Invalidate the input description for pipelines.
235 mDirtyPackedInputs.set(attribIndex);
236
237 if (attrib.enabled)
238 {
239 gl::Buffer *bufferGL = binding.getBuffer().get();
240
241 if (bufferGL)
242 {
243 BufferVk *bufferVk = vk::GetImpl(bufferGL);
244 mCurrentArrayBufferResources[attribIndex] = bufferVk;
245 mCurrentArrayBufferHandles[attribIndex] = bufferVk->getVkBuffer().getHandle();
246 mClientMemoryAttribs.reset(attribIndex);
247 }
248 else
249 {
250 mCurrentArrayBufferResources[attribIndex] = nullptr;
251 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
252 mClientMemoryAttribs.set(attribIndex);
253 }
254 // TODO(jmadill): Offset handling. Assume zero for now.
255 mCurrentArrayBufferOffsets[attribIndex] = 0;
256 }
257 else
258 {
259 mClientMemoryAttribs.reset(attribIndex);
260 UNIMPLEMENTED();
261 }
262}
263
Jamie Madillda854a22017-11-30 17:24:21 -0500264const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const
Jamie Madillbd159f02017-10-09 19:39:06 -0400265{
Jamie Madillda854a22017-11-30 17:24:21 -0500266 return mCurrentArrayBufferHandles;
Jamie Madillbd159f02017-10-09 19:39:06 -0400267}
268
Frank Henigman17448952017-01-05 15:48:26 -0500269const gl::AttribArray<VkDeviceSize> &VertexArrayVk::getCurrentArrayBufferOffsets() const
270{
271 return mCurrentArrayBufferOffsets;
272}
273
Jamie Madill9cceac42018-03-31 14:19:16 -0400274void VertexArrayVk::updateArrayBufferReadDependencies(vk::CommandGraphNode *readingNode,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400275 const gl::AttributesMask &activeAttribsMask,
276 Serial serial)
Jamie Madillbd159f02017-10-09 19:39:06 -0400277{
Jamie Madillda854a22017-11-30 17:24:21 -0500278 // Handle the bound array buffers.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400279 for (size_t attribIndex : activeAttribsMask)
Jamie Madillbd159f02017-10-09 19:39:06 -0400280 {
Frank Henigman17448952017-01-05 15:48:26 -0500281 if (mCurrentArrayBufferResources[attribIndex])
Jamie Madill9cceac42018-03-31 14:19:16 -0400282 mCurrentArrayBufferResources[attribIndex]->onReadResource(readingNode, serial);
Jamie Madillda854a22017-11-30 17:24:21 -0500283 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400284}
Jamie Madillda854a22017-11-30 17:24:21 -0500285
Jamie Madill9cceac42018-03-31 14:19:16 -0400286void VertexArrayVk::updateElementArrayBufferReadDependency(vk::CommandGraphNode *readingNode,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400287 Serial serial)
288{
Jamie Madillda854a22017-11-30 17:24:21 -0500289 // Handle the bound element array buffer.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400290 if (mCurrentElementArrayBufferResource)
Jamie Madillda854a22017-11-30 17:24:21 -0500291 {
Jamie Madill9cceac42018-03-31 14:19:16 -0400292 mCurrentElementArrayBufferResource->onReadResource(readingNode, serial);
Jamie Madillbd159f02017-10-09 19:39:06 -0400293 }
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400294}
295
Jamie Madill112a3a82018-01-23 13:04:06 -0500296void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400297{
Jamie Madill112a3a82018-01-23 13:04:06 -0500298 updatePackedInputDescriptions();
299 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400300}
301
Jamie Madill112a3a82018-01-23 13:04:06 -0500302void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400303{
Jamie Madill112a3a82018-01-23 13:04:06 -0500304 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400305 {
306 return;
307 }
308
309 const auto &attribs = mState.getVertexAttributes();
310 const auto &bindings = mState.getVertexBindings();
311
Jamie Madill112a3a82018-01-23 13:04:06 -0500312 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400313 {
314 const auto &attrib = attribs[attribIndex];
315 const auto &binding = bindings[attrib.bindingIndex];
316 if (attrib.enabled)
317 {
Jamie Madill112a3a82018-01-23 13:04:06 -0500318 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400319 }
320 else
321 {
322 UNIMPLEMENTED();
323 }
324 }
325
Jamie Madill112a3a82018-01-23 13:04:06 -0500326 mDirtyPackedInputs.reset();
327}
328
329void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
330 const gl::VertexBinding &binding,
331 const gl::VertexAttribute &attrib)
332{
333 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
334
335 size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
336 ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
337
Frank Henigmana8e868f2018-01-28 23:32:25 -0500338 bindingDesc.stride = static_cast<uint16_t>(binding.getStride());
Jamie Madill112a3a82018-01-23 13:04:06 -0500339 bindingDesc.inputRate = static_cast<uint16_t>(
340 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
341
342 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
343 VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
344 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
345
346 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
347 attribDesc.format = static_cast<uint16_t>(vkFormat);
348 attribDesc.location = static_cast<uint16_t>(attribIndex);
349 attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
Jamie Madillebf72992017-10-13 14:09:45 -0400350}
351
Jamie Madillc3755fc2018-04-05 08:39:13 -0400352gl::Error VertexArrayVk::drawArrays(const gl::Context *context,
353 RendererVk *renderer,
354 const gl::DrawCallParams &drawCallParams,
355 vk::CommandGraphNode *drawNode,
356 bool newCommandBuffer)
357{
358 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
359 ASSERT(commandBuffer->valid());
360
361 ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
362
363 if (drawCallParams.mode() != GL_LINE_LOOP)
364 {
365 commandBuffer->draw(drawCallParams.vertexCount(), 1, drawCallParams.firstVertex(), 0);
366 return gl::NoError();
367 }
368
369 // Handle GL_LINE_LOOP drawArrays.
370 int lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
371 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
372 mLineLoopBufferFirstIndex != drawCallParams.firstVertex() ||
373 mLineLoopBufferLastIndex != lastVertex)
374 {
Jamie Madill22f12fe2018-04-08 14:23:40 -0400375 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(renderer, drawCallParams,
376 &mCurrentElementArrayBufferHandle,
377 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400378
379 mLineLoopBufferFirstIndex = drawCallParams.firstVertex();
380 mLineLoopBufferLastIndex = lastVertex;
381 }
382
383 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
384 mCurrentElementArrayBufferOffset, VK_INDEX_TYPE_UINT32);
385
Jamie Madill22f12fe2018-04-08 14:23:40 -0400386 vk::LineLoopHelper::Draw(drawCallParams.vertexCount(), commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400387
388 return gl::NoError();
389}
390
391gl::Error VertexArrayVk::drawElements(const gl::Context *context,
392 RendererVk *renderer,
393 const gl::DrawCallParams &drawCallParams,
394 vk::CommandGraphNode *drawNode,
395 bool newCommandBuffer)
396{
397 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
398 ASSERT(commandBuffer->valid());
399
400 if (drawCallParams.mode() != GL_LINE_LOOP)
401 {
402 ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
403 commandBuffer->drawIndexed(drawCallParams.indexCount(), 1, 0, 0, 0);
404 return gl::NoError();
405 }
406
407 // Handle GL_LINE_LOOP drawElements.
408 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
409 if (!elementArrayBuffer)
410 {
411 UNIMPLEMENTED();
412 return gl::InternalError() << "Line loop indices in client memory not supported";
413 }
414
415 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
416
417 VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
418
Jamie Madillb8e39662018-04-04 11:41:42 -0400419 if (mDirtyLineLoopTranslation)
420 {
Jamie Madill22f12fe2018-04-08 14:23:40 -0400421 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Jamie Madillb8e39662018-04-04 11:41:42 -0400422 renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(),
423 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
424 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400425
426 ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
Jamie Madill22f12fe2018-04-08 14:23:40 -0400427 vk::LineLoopHelper::Draw(drawCallParams.indexCount(), commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400428
429 return gl::NoError();
430}
431
432gl::Error VertexArrayVk::onDraw(const gl::Context *context,
433 RendererVk *renderer,
434 const gl::DrawCallParams &drawCallParams,
435 vk::CommandGraphNode *drawNode,
436 bool newCommandBuffer)
437{
438 const gl::State &state = context->getGLState();
439 const gl::Program *programGL = state.getProgram();
440 const gl::AttributesMask &activeAttribs = programGL->getActiveAttribLocationsMask();
441 uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation();
442
443 if (mClientMemoryAttribs.any())
444 {
445 const gl::AttributesMask &attribsToStream = (mClientMemoryAttribs & activeAttribs);
446 if (attribsToStream.any())
447 {
448 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
449 ANGLE_TRY(streamVertexData(renderer, attribsToStream, drawCallParams));
450 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
451 commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
452 mCurrentArrayBufferOffsets.data());
453 }
454 }
455 else if (mVertexBuffersDirty || newCommandBuffer)
456 {
Luc Ferron44162472018-04-06 13:20:45 -0400457 if (maxAttrib > 0)
458 {
459 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
460 commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
461 mCurrentArrayBufferOffsets.data());
462 updateArrayBufferReadDependencies(drawNode, activeAttribs,
463 renderer->getCurrentQueueSerial());
464 }
Luc Ferronc1e02682018-04-11 11:02:55 -0400465
Jamie Madillc3755fc2018-04-05 08:39:13 -0400466 mVertexBuffersDirty = false;
Luc Ferronc1e02682018-04-11 11:02:55 -0400467
468 // This forces the binding to happen if we follow a drawElement call from a drawArrays call.
469 mIndexBufferDirty = true;
Luc Ferron983c4292018-04-10 13:05:45 -0400470
471 // If we've had a drawElements call with a line loop before, we want to make sure this is
472 // invalidated the next time drawElements is called since we use the same index buffer for
473 // both calls.
474 mDirtyLineLoopTranslation = true;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400475 }
476
477 return gl::NoError();
478}
479
480gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
481 RendererVk *renderer,
482 const gl::DrawCallParams &drawCallParams,
483 vk::CommandGraphNode *drawNode,
484 bool newCommandBuffer)
485{
486 ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
487
488 if (!mState.getElementArrayBuffer().get())
489 {
490 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
491 ANGLE_TRY(streamIndexData(renderer, drawCallParams));
492 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
493 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
494 mCurrentElementArrayBufferOffset,
495 gl_vk::GetIndexType(drawCallParams.type()));
496 }
497 else if (mIndexBufferDirty || newCommandBuffer)
498 {
499 if (drawCallParams.type() == GL_UNSIGNED_BYTE)
500 {
501 // TODO(fjhenigman): Index format translation.
502 UNIMPLEMENTED();
503 return gl::InternalError()
504 << "Unsigned byte translation is not implemented for indices in a buffer object";
505 }
506
507 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
508 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
509 mCurrentElementArrayBufferOffset,
510 gl_vk::GetIndexType(drawCallParams.type()));
511 updateElementArrayBufferReadDependency(drawNode, renderer->getCurrentQueueSerial());
512 mIndexBufferDirty = false;
Luc Ferron983c4292018-04-10 13:05:45 -0400513
514 // If we've had a drawArrays call with a line loop before, we want to make sure this is
515 // invalidated the next time drawArrays is called since we use the same index buffer for
516 // both calls.
517 mLineLoopBufferFirstIndex.reset();
518 mLineLoopBufferLastIndex.reset();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400519 }
520
521 return gl::NoError();
522}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400523} // namespace rx