blob: 5972339f03783bf684bd54d476fbe478c223162f [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();
Jamie Madillc3755fc2018-04-05 08:39:13 -040061 mDynamicVertexData.destroy(device);
62 mDynamicIndexData.destroy(device);
Jamie Madill22f12fe2018-04-08 14:23:40 -040063 mLineLoopHelper.destroy(device);
Jamie Madill9e54b5a2016-05-25 12:57:39 -040064}
65
Jamie Madillc3755fc2018-04-05 08:39:13 -040066gl::Error VertexArrayVk::streamVertexData(RendererVk *renderer,
67 const gl::AttributesMask &attribsToStream,
Jamie Madill32fd63b2018-03-31 11:20:35 -040068 const gl::DrawCallParams &drawCallParams)
Frank Henigman17448952017-01-05 15:48:26 -050069{
Jamie Madillc3755fc2018-04-05 08:39:13 -040070 ASSERT(!attribsToStream.none());
71
Jamie Madillbcef3222018-04-13 15:19:11 -040072 const auto &attribs = mState.getVertexAttributes();
73 const auto &bindings = mState.getVertexBindings();
Frank Henigman17448952017-01-05 15:48:26 -050074
Jamie Madill32fd63b2018-03-31 11:20:35 -040075 const size_t lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
76
Frank Henigman17448952017-01-05 15:48:26 -050077 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
78 // un-interleaved, wasting space and copying time. Consider improving on that.
Jamie Madillb8e39662018-04-04 11:41:42 -040079 for (size_t attribIndex : attribsToStream)
Frank Henigman17448952017-01-05 15:48:26 -050080 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050081 const gl::VertexAttribute &attrib = attribs[attribIndex];
82 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
83 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
Frank Henigman17448952017-01-05 15:48:26 -050084
Frank Henigman6dd4a922018-03-02 16:35:13 -050085 // TODO(fjhenigman): Work with more formats than just GL_FLOAT.
86 if (attrib.type != GL_FLOAT)
Frank Henigman17448952017-01-05 15:48:26 -050087 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050088 UNIMPLEMENTED();
89 return gl::InternalError();
Frank Henigman17448952017-01-05 15:48:26 -050090 }
Frank Henigman6dd4a922018-03-02 16:35:13 -050091
92 // Only [firstVertex, lastVertex] is needed by the upcoming draw so that
93 // is all we copy, but we allocate space for [0, lastVertex] so indexing
94 // will work. If we don't start at zero all the indices will be off.
95 // TODO(fjhenigman): See if we can account for indices being off by adjusting
96 // the offset, thus avoiding wasted memory.
Jamie Madill32fd63b2018-03-31 11:20:35 -040097 const size_t firstByte = drawCallParams.firstVertex() * binding.getStride();
Frank Henigman6dd4a922018-03-02 16:35:13 -050098 const size_t lastByte =
99 lastVertex * binding.getStride() + gl::ComputeVertexAttributeTypeSize(attrib);
100 uint8_t *dst = nullptr;
Luc Ferron7a06ac12018-03-15 10:17:04 -0400101 uint32_t offset = 0;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400102 ANGLE_TRY(mDynamicVertexData.allocate(
103 renderer, lastByte, &dst, &mCurrentArrayBufferHandles[attribIndex], &offset, nullptr));
Luc Ferron7a06ac12018-03-15 10:17:04 -0400104 mCurrentArrayBufferOffsets[attribIndex] = static_cast<VkDeviceSize>(offset);
Frank Henigman6dd4a922018-03-02 16:35:13 -0500105 memcpy(dst + firstByte, static_cast<const uint8_t *>(attrib.pointer) + firstByte,
106 lastByte - firstByte);
Frank Henigman17448952017-01-05 15:48:26 -0500107 }
108
Jamie Madillc3755fc2018-04-05 08:39:13 -0400109 ANGLE_TRY(mDynamicVertexData.flush(renderer->getDevice()));
Luc Ferron61859812018-05-09 14:17:39 -0400110 mDynamicVertexData.releaseRetainedBuffers(renderer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400111 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()));
Luc Ferron61859812018-05-09 14:17:39 -0400142 mDynamicIndexData.releaseRetainedBuffers(renderer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400143 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();
Jamie Madilla56467e2018-04-11 16:19:41 -0400246 }
247 else
248 {
249 mCurrentArrayBufferResources[attribIndex] = nullptr;
250 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
Jamie Madilla56467e2018-04-11 16:19:41 -0400251 }
252 // TODO(jmadill): Offset handling. Assume zero for now.
253 mCurrentArrayBufferOffsets[attribIndex] = 0;
254 }
255 else
256 {
Jamie Madilla56467e2018-04-11 16:19:41 -0400257 UNIMPLEMENTED();
258 }
259}
260
Jamie Madillda854a22017-11-30 17:24:21 -0500261const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const
Jamie Madillbd159f02017-10-09 19:39:06 -0400262{
Jamie Madillda854a22017-11-30 17:24:21 -0500263 return mCurrentArrayBufferHandles;
Jamie Madillbd159f02017-10-09 19:39:06 -0400264}
265
Frank Henigman17448952017-01-05 15:48:26 -0500266const gl::AttribArray<VkDeviceSize> &VertexArrayVk::getCurrentArrayBufferOffsets() const
267{
268 return mCurrentArrayBufferOffsets;
269}
270
Jamie Madill9cceac42018-03-31 14:19:16 -0400271void VertexArrayVk::updateArrayBufferReadDependencies(vk::CommandGraphNode *readingNode,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400272 const gl::AttributesMask &activeAttribsMask,
273 Serial serial)
Jamie Madillbd159f02017-10-09 19:39:06 -0400274{
Jamie Madillda854a22017-11-30 17:24:21 -0500275 // Handle the bound array buffers.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400276 for (size_t attribIndex : activeAttribsMask)
Jamie Madillbd159f02017-10-09 19:39:06 -0400277 {
Frank Henigman17448952017-01-05 15:48:26 -0500278 if (mCurrentArrayBufferResources[attribIndex])
Jamie Madill9cceac42018-03-31 14:19:16 -0400279 mCurrentArrayBufferResources[attribIndex]->onReadResource(readingNode, serial);
Jamie Madillda854a22017-11-30 17:24:21 -0500280 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400281}
Jamie Madillda854a22017-11-30 17:24:21 -0500282
Jamie Madill9cceac42018-03-31 14:19:16 -0400283void VertexArrayVk::updateElementArrayBufferReadDependency(vk::CommandGraphNode *readingNode,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400284 Serial serial)
285{
Jamie Madillda854a22017-11-30 17:24:21 -0500286 // Handle the bound element array buffer.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400287 if (mCurrentElementArrayBufferResource)
Jamie Madillda854a22017-11-30 17:24:21 -0500288 {
Jamie Madill9cceac42018-03-31 14:19:16 -0400289 mCurrentElementArrayBufferResource->onReadResource(readingNode, serial);
Jamie Madillbd159f02017-10-09 19:39:06 -0400290 }
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400291}
292
Jamie Madill112a3a82018-01-23 13:04:06 -0500293void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400294{
Jamie Madill112a3a82018-01-23 13:04:06 -0500295 updatePackedInputDescriptions();
296 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400297}
298
Jamie Madill112a3a82018-01-23 13:04:06 -0500299void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400300{
Jamie Madill112a3a82018-01-23 13:04:06 -0500301 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400302 {
303 return;
304 }
305
306 const auto &attribs = mState.getVertexAttributes();
307 const auto &bindings = mState.getVertexBindings();
308
Jamie Madill112a3a82018-01-23 13:04:06 -0500309 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400310 {
311 const auto &attrib = attribs[attribIndex];
312 const auto &binding = bindings[attrib.bindingIndex];
313 if (attrib.enabled)
314 {
Jamie Madill112a3a82018-01-23 13:04:06 -0500315 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400316 }
317 else
318 {
319 UNIMPLEMENTED();
320 }
321 }
322
Jamie Madill112a3a82018-01-23 13:04:06 -0500323 mDirtyPackedInputs.reset();
324}
325
326void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
327 const gl::VertexBinding &binding,
328 const gl::VertexAttribute &attrib)
329{
330 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
331
332 size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
333 ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
334
Frank Henigmana8e868f2018-01-28 23:32:25 -0500335 bindingDesc.stride = static_cast<uint16_t>(binding.getStride());
Jamie Madill112a3a82018-01-23 13:04:06 -0500336 bindingDesc.inputRate = static_cast<uint16_t>(
337 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
338
339 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
340 VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
341 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
342
343 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
344 attribDesc.format = static_cast<uint16_t>(vkFormat);
345 attribDesc.location = static_cast<uint16_t>(attribIndex);
346 attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
Jamie Madillebf72992017-10-13 14:09:45 -0400347}
348
Jamie Madillc3755fc2018-04-05 08:39:13 -0400349gl::Error VertexArrayVk::drawArrays(const gl::Context *context,
350 RendererVk *renderer,
351 const gl::DrawCallParams &drawCallParams,
352 vk::CommandGraphNode *drawNode,
353 bool newCommandBuffer)
354{
355 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
356 ASSERT(commandBuffer->valid());
357
358 ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
359
360 if (drawCallParams.mode() != GL_LINE_LOOP)
361 {
362 commandBuffer->draw(drawCallParams.vertexCount(), 1, drawCallParams.firstVertex(), 0);
363 return gl::NoError();
364 }
365
366 // Handle GL_LINE_LOOP drawArrays.
367 int lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
368 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
369 mLineLoopBufferFirstIndex != drawCallParams.firstVertex() ||
370 mLineLoopBufferLastIndex != lastVertex)
371 {
Jamie Madill22f12fe2018-04-08 14:23:40 -0400372 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(renderer, drawCallParams,
373 &mCurrentElementArrayBufferHandle,
374 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400375
376 mLineLoopBufferFirstIndex = drawCallParams.firstVertex();
377 mLineLoopBufferLastIndex = lastVertex;
378 }
379
380 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
381 mCurrentElementArrayBufferOffset, VK_INDEX_TYPE_UINT32);
382
Jamie Madill22f12fe2018-04-08 14:23:40 -0400383 vk::LineLoopHelper::Draw(drawCallParams.vertexCount(), commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400384
385 return gl::NoError();
386}
387
388gl::Error VertexArrayVk::drawElements(const gl::Context *context,
389 RendererVk *renderer,
390 const gl::DrawCallParams &drawCallParams,
391 vk::CommandGraphNode *drawNode,
392 bool newCommandBuffer)
393{
394 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
395 ASSERT(commandBuffer->valid());
396
397 if (drawCallParams.mode() != GL_LINE_LOOP)
398 {
399 ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
400 commandBuffer->drawIndexed(drawCallParams.indexCount(), 1, 0, 0, 0);
401 return gl::NoError();
402 }
403
404 // Handle GL_LINE_LOOP drawElements.
Jamie Madillb8e39662018-04-04 11:41:42 -0400405 if (mDirtyLineLoopTranslation)
406 {
Luc Ferrona9120462018-04-12 13:11:03 -0400407 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
408 VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
409
410 if (!elementArrayBuffer)
411 {
412 ANGLE_TRY(mLineLoopHelper.getIndexBufferForClientElementArray(
413 renderer, drawCallParams.indices(), indexType, drawCallParams.indexCount(),
414 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
415 }
416 else
417 {
Luc Ferrona4fa9c22018-04-13 07:00:56 -0400418 // When using an element array buffer, 'indices' is an offset to the first element.
419 intptr_t offset = reinterpret_cast<intptr_t>(drawCallParams.indices());
Luc Ferrona9120462018-04-12 13:11:03 -0400420 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
421 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Luc Ferrona4fa9c22018-04-13 07:00:56 -0400422 renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(), offset,
Luc Ferrona9120462018-04-12 13:11:03 -0400423 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
424 }
Jamie Madillb8e39662018-04-04 11:41:42 -0400425 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400426
427 ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
Jamie Madill22f12fe2018-04-08 14:23:40 -0400428 vk::LineLoopHelper::Draw(drawCallParams.indexCount(), commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400429
430 return gl::NoError();
431}
432
433gl::Error VertexArrayVk::onDraw(const gl::Context *context,
434 RendererVk *renderer,
435 const gl::DrawCallParams &drawCallParams,
436 vk::CommandGraphNode *drawNode,
437 bool newCommandBuffer)
438{
439 const gl::State &state = context->getGLState();
440 const gl::Program *programGL = state.getProgram();
Jamie Madillbcef3222018-04-13 15:19:11 -0400441 const gl::AttributesMask &clientAttribs = mState.getEnabledClientMemoryAttribsMask();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400442 const gl::AttributesMask &activeAttribs = programGL->getActiveAttribLocationsMask();
443 uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation();
444
Jamie Madillbcef3222018-04-13 15:19:11 -0400445 if (clientAttribs.any())
Jamie Madillc3755fc2018-04-05 08:39:13 -0400446 {
Jamie Madillbcef3222018-04-13 15:19:11 -0400447 const gl::AttributesMask &attribsToStream = (clientAttribs & activeAttribs);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400448 if (attribsToStream.any())
449 {
450 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
451 ANGLE_TRY(streamVertexData(renderer, attribsToStream, drawCallParams));
452 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
453 commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
454 mCurrentArrayBufferOffsets.data());
455 }
456 }
457 else if (mVertexBuffersDirty || newCommandBuffer)
458 {
Luc Ferron44162472018-04-06 13:20:45 -0400459 if (maxAttrib > 0)
460 {
461 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
462 commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
463 mCurrentArrayBufferOffsets.data());
464 updateArrayBufferReadDependencies(drawNode, activeAttribs,
465 renderer->getCurrentQueueSerial());
466 }
Luc Ferronc1e02682018-04-11 11:02:55 -0400467
Jamie Madillc3755fc2018-04-05 08:39:13 -0400468 mVertexBuffersDirty = false;
Luc Ferronc1e02682018-04-11 11:02:55 -0400469
470 // This forces the binding to happen if we follow a drawElement call from a drawArrays call.
471 mIndexBufferDirty = true;
Luc Ferron983c4292018-04-10 13:05:45 -0400472
473 // If we've had a drawElements call with a line loop before, we want to make sure this is
474 // invalidated the next time drawElements is called since we use the same index buffer for
475 // both calls.
476 mDirtyLineLoopTranslation = true;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400477 }
478
479 return gl::NoError();
480}
481
482gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
483 RendererVk *renderer,
484 const gl::DrawCallParams &drawCallParams,
485 vk::CommandGraphNode *drawNode,
486 bool newCommandBuffer)
487{
488 ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
489
Luc Ferrona9120462018-04-12 13:11:03 -0400490 if (!mState.getElementArrayBuffer().get() && drawCallParams.mode() != GL_LINE_LOOP)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400491 {
492 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
493 ANGLE_TRY(streamIndexData(renderer, drawCallParams));
494 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
495 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
496 mCurrentElementArrayBufferOffset,
497 gl_vk::GetIndexType(drawCallParams.type()));
498 }
499 else if (mIndexBufferDirty || newCommandBuffer)
500 {
501 if (drawCallParams.type() == GL_UNSIGNED_BYTE)
502 {
503 // TODO(fjhenigman): Index format translation.
504 UNIMPLEMENTED();
505 return gl::InternalError()
506 << "Unsigned byte translation is not implemented for indices in a buffer object";
507 }
508
509 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
510 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
511 mCurrentElementArrayBufferOffset,
512 gl_vk::GetIndexType(drawCallParams.type()));
513 updateElementArrayBufferReadDependency(drawNode, renderer->getCurrentQueueSerial());
514 mIndexBufferDirty = false;
Luc Ferron983c4292018-04-10 13:05:45 -0400515
516 // If we've had a drawArrays call with a line loop before, we want to make sure this is
517 // invalidated the next time drawArrays is called since we use the same index buffer for
518 // both calls.
519 mLineLoopBufferFirstIndex.reset();
520 mLineLoopBufferLastIndex.reset();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400521 }
522
523 return gl::NoError();
524}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400525} // namespace rx