blob: 369fcece44d9389c70bd27e4c4b4a478d057c3ba [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.
Jamie Madillb8e39662018-04-04 11:41:42 -0400370 // This test may be incorrect if the draw call switches from DrawArrays/DrawElements.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400371 int lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
372 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
373 mLineLoopBufferFirstIndex != drawCallParams.firstVertex() ||
374 mLineLoopBufferLastIndex != lastVertex)
375 {
Jamie Madill22f12fe2018-04-08 14:23:40 -0400376 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(renderer, drawCallParams,
377 &mCurrentElementArrayBufferHandle,
378 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400379
380 mLineLoopBufferFirstIndex = drawCallParams.firstVertex();
381 mLineLoopBufferLastIndex = lastVertex;
382 }
383
384 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
385 mCurrentElementArrayBufferOffset, VK_INDEX_TYPE_UINT32);
386
Jamie Madill22f12fe2018-04-08 14:23:40 -0400387 vk::LineLoopHelper::Draw(drawCallParams.vertexCount(), commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400388
389 return gl::NoError();
390}
391
392gl::Error VertexArrayVk::drawElements(const gl::Context *context,
393 RendererVk *renderer,
394 const gl::DrawCallParams &drawCallParams,
395 vk::CommandGraphNode *drawNode,
396 bool newCommandBuffer)
397{
398 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
399 ASSERT(commandBuffer->valid());
400
401 if (drawCallParams.mode() != GL_LINE_LOOP)
402 {
403 ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
404 commandBuffer->drawIndexed(drawCallParams.indexCount(), 1, 0, 0, 0);
405 return gl::NoError();
406 }
407
408 // Handle GL_LINE_LOOP drawElements.
409 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
410 if (!elementArrayBuffer)
411 {
412 UNIMPLEMENTED();
413 return gl::InternalError() << "Line loop indices in client memory not supported";
414 }
415
416 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
417
418 VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
419
Jamie Madillb8e39662018-04-04 11:41:42 -0400420 // This also doesn't check if the element type changed, which should trigger translation.
421 if (mDirtyLineLoopTranslation)
422 {
Jamie Madill22f12fe2018-04-08 14:23:40 -0400423 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Jamie Madillb8e39662018-04-04 11:41:42 -0400424 renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(),
425 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
426 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400427
428 ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
Jamie Madill22f12fe2018-04-08 14:23:40 -0400429 vk::LineLoopHelper::Draw(drawCallParams.indexCount(), commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400430
431 return gl::NoError();
432}
433
434gl::Error VertexArrayVk::onDraw(const gl::Context *context,
435 RendererVk *renderer,
436 const gl::DrawCallParams &drawCallParams,
437 vk::CommandGraphNode *drawNode,
438 bool newCommandBuffer)
439{
440 const gl::State &state = context->getGLState();
441 const gl::Program *programGL = state.getProgram();
442 const gl::AttributesMask &activeAttribs = programGL->getActiveAttribLocationsMask();
443 uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation();
444
445 if (mClientMemoryAttribs.any())
446 {
447 const gl::AttributesMask &attribsToStream = (mClientMemoryAttribs & activeAttribs);
448 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 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400467 mVertexBuffersDirty = false;
468 }
469
470 return gl::NoError();
471}
472
473gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
474 RendererVk *renderer,
475 const gl::DrawCallParams &drawCallParams,
476 vk::CommandGraphNode *drawNode,
477 bool newCommandBuffer)
478{
479 ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
480
481 if (!mState.getElementArrayBuffer().get())
482 {
483 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
484 ANGLE_TRY(streamIndexData(renderer, drawCallParams));
485 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
486 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
487 mCurrentElementArrayBufferOffset,
488 gl_vk::GetIndexType(drawCallParams.type()));
489 }
490 else if (mIndexBufferDirty || newCommandBuffer)
491 {
492 if (drawCallParams.type() == GL_UNSIGNED_BYTE)
493 {
494 // TODO(fjhenigman): Index format translation.
495 UNIMPLEMENTED();
496 return gl::InternalError()
497 << "Unsigned byte translation is not implemented for indices in a buffer object";
498 }
499
500 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
501 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
502 mCurrentElementArrayBufferOffset,
503 gl_vk::GetIndexType(drawCallParams.type()));
504 updateElementArrayBufferReadDependency(drawNode, renderer->getCurrentQueueSerial());
505 mIndexBufferDirty = false;
506 }
507
508 return gl::NoError();
509}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400510} // namespace rx