blob: f6ce42c9573167a19dbd02e3199769cea39d560d [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
Luc Ferrona9ab0f32018-05-17 17:03:55 -040029VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *renderer)
Jamie Madillbd159f02017-10-09 19:39:06 -040030 : 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),
Luc Ferrona9ab0f32018-05-17 17:03:55 -040039 mLineLoopHelper(renderer),
Jamie Madillb8e39662018-04-04 11:41:42 -040040 mDirtyLineLoopTranslation(true),
Jamie Madillc3755fc2018-04-05 08:39:13 -040041 mVertexBuffersDirty(false),
42 mIndexBufferDirty(false)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040043{
Jamie Madillda854a22017-11-30 17:24:21 -050044 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -050045 mCurrentArrayBufferOffsets.fill(0);
Jamie Madillda854a22017-11-30 17:24:21 -050046 mCurrentArrayBufferResources.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -050047
48 mPackedInputBindings.fill({0, 0});
49 mPackedInputAttributes.fill({0, 0, 0});
Jamie Madillc3755fc2018-04-05 08:39:13 -040050
Luc Ferrona9ab0f32018-05-17 17:03:55 -040051 mDynamicVertexData.init(1, renderer);
52 mDynamicIndexData.init(1, renderer);
Jamie Madill9e54b5a2016-05-25 12:57:39 -040053}
54
Jamie Madillacf2f3a2017-11-21 19:22:44 -050055VertexArrayVk::~VertexArrayVk()
56{
57}
58
Jamie Madill4928b7c2017-06-20 12:57:39 -040059void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040060{
Jamie Madillc3755fc2018-04-05 08:39:13 -040061 VkDevice device = vk::GetImpl(context)->getRenderer()->getDevice();
Jamie Madillc3755fc2018-04-05 08:39:13 -040062 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
Jamie Madillbcef3222018-04-13 15:19:11 -040073 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()));
Luc Ferron61859812018-05-09 14:17:39 -0400111 mDynamicVertexData.releaseRetainedBuffers(renderer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400112 return gl::NoError();
113}
114
115gl::Error VertexArrayVk::streamIndexData(RendererVk *renderer,
116 const gl::DrawCallParams &drawCallParams)
117{
118 ASSERT(!mState.getElementArrayBuffer().get());
119
120 uint32_t offset = 0;
121
122 const GLsizei amount = sizeof(GLushort) * drawCallParams.indexCount();
123 GLubyte *dst = nullptr;
124
125 ANGLE_TRY(mDynamicIndexData.allocate(renderer, amount, &dst, &mCurrentElementArrayBufferHandle,
126 &offset, nullptr));
127 if (drawCallParams.type() == GL_UNSIGNED_BYTE)
128 {
129 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
130 // memory to a GLushort.
131 const GLubyte *in = static_cast<const GLubyte *>(drawCallParams.indices());
132 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
133 for (GLsizei index = 0; index < drawCallParams.indexCount(); index++)
134 {
135 expandedDst[index] = static_cast<GLushort>(in[index]);
136 }
137 }
138 else
139 {
140 memcpy(dst, drawCallParams.indices(), amount);
141 }
142 ANGLE_TRY(mDynamicIndexData.flush(renderer->getDevice()));
Luc Ferron61859812018-05-09 14:17:39 -0400143 mDynamicIndexData.releaseRetainedBuffers(renderer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400144 mCurrentElementArrayBufferOffset = offset;
Frank Henigman17448952017-01-05 15:48:26 -0500145 return gl::NoError();
146}
147
Jamie Madilla56467e2018-04-11 16:19:41 -0400148#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
149 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
150 syncDirtyAttrib(attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
151 invalidatePipeline = true; \
152 break;
153
154#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
155 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
156 syncDirtyAttrib(attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
157 invalidatePipeline = true; \
158 break;
159
160#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
161 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
162 break;
163
Frank Henigman0af5b862018-03-27 20:19:33 -0400164gl::Error VertexArrayVk::syncState(const gl::Context *context,
165 const gl::VertexArray::DirtyBits &dirtyBits,
166 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
167 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400168{
169 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400170
Jamie Madillc3755fc2018-04-05 08:39:13 -0400171 bool invalidatePipeline = false;
172
Jamie Madillbd159f02017-10-09 19:39:06 -0400173 // Invalidate current pipeline.
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500174 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400175
176 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
177 // TODO(jmadill): Handle buffer storage changes.
178 const auto &attribs = mState.getVertexAttributes();
179 const auto &bindings = mState.getVertexBindings();
180
Jamie Madill09463932018-04-04 05:26:59 -0400181 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400182 {
Jamie Madill09463932018-04-04 05:26:59 -0400183 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500184 {
Jamie Madill09463932018-04-04 05:26:59 -0400185 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500186 {
Jamie Madill09463932018-04-04 05:26:59 -0400187 gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
188 if (bufferGL)
189 {
Jamie Madillc3755fc2018-04-05 08:39:13 -0400190 BufferVk *bufferVk = vk::GetImpl(bufferGL);
191 mCurrentElementArrayBufferResource = bufferVk;
192 mCurrentElementArrayBufferHandle = bufferVk->getVkBuffer().getHandle();
193 mCurrentElementArrayBufferOffset = 0;
Jamie Madill09463932018-04-04 05:26:59 -0400194 }
195 else
196 {
197 mCurrentElementArrayBufferResource = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400198 mCurrentElementArrayBufferHandle = VK_NULL_HANDLE;
199 mCurrentElementArrayBufferOffset = 0;
Jamie Madill09463932018-04-04 05:26:59 -0400200 }
Jamie Madillb8e39662018-04-04 11:41:42 -0400201 mIndexBufferDirty = true;
202 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400203 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500204 }
Jamie Madill09463932018-04-04 05:26:59 -0400205
206 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400207 mLineLoopBufferFirstIndex.reset();
208 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400209 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400210 break;
211
Jamie Madilla56467e2018-04-11 16:19:41 -0400212 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
213 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
214 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
215
Jamie Madill09463932018-04-04 05:26:59 -0400216 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400217 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400218 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400219 }
220 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400221
Jamie Madillc3755fc2018-04-05 08:39:13 -0400222 if (invalidatePipeline)
223 {
224 mVertexBuffersDirty = true;
225 contextVk->invalidateCurrentPipeline();
226 }
227
Frank Henigman0af5b862018-03-27 20:19:33 -0400228 return gl::NoError();
Jamie Madillbd159f02017-10-09 19:39:06 -0400229}
230
Jamie Madilla56467e2018-04-11 16:19:41 -0400231void VertexArrayVk::syncDirtyAttrib(const gl::VertexAttribute &attrib,
232 const gl::VertexBinding &binding,
233 size_t attribIndex)
234{
235 // Invalidate the input description for pipelines.
236 mDirtyPackedInputs.set(attribIndex);
237
238 if (attrib.enabled)
239 {
240 gl::Buffer *bufferGL = binding.getBuffer().get();
241
242 if (bufferGL)
243 {
244 BufferVk *bufferVk = vk::GetImpl(bufferGL);
245 mCurrentArrayBufferResources[attribIndex] = bufferVk;
246 mCurrentArrayBufferHandles[attribIndex] = bufferVk->getVkBuffer().getHandle();
Jamie Madilla56467e2018-04-11 16:19:41 -0400247 }
248 else
249 {
250 mCurrentArrayBufferResources[attribIndex] = nullptr;
251 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
Jamie Madilla56467e2018-04-11 16:19:41 -0400252 }
253 // TODO(jmadill): Offset handling. Assume zero for now.
254 mCurrentArrayBufferOffsets[attribIndex] = 0;
255 }
256 else
257 {
Jamie Madilla56467e2018-04-11 16:19:41 -0400258 UNIMPLEMENTED();
259 }
260}
261
Jamie Madillda854a22017-11-30 17:24:21 -0500262const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const
Jamie Madillbd159f02017-10-09 19:39:06 -0400263{
Jamie Madillda854a22017-11-30 17:24:21 -0500264 return mCurrentArrayBufferHandles;
Jamie Madillbd159f02017-10-09 19:39:06 -0400265}
266
Frank Henigman17448952017-01-05 15:48:26 -0500267const gl::AttribArray<VkDeviceSize> &VertexArrayVk::getCurrentArrayBufferOffsets() const
268{
269 return mCurrentArrayBufferOffsets;
270}
271
Jamie Madill9cceac42018-03-31 14:19:16 -0400272void VertexArrayVk::updateArrayBufferReadDependencies(vk::CommandGraphNode *readingNode,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400273 const gl::AttributesMask &activeAttribsMask,
274 Serial serial)
Jamie Madillbd159f02017-10-09 19:39:06 -0400275{
Jamie Madillda854a22017-11-30 17:24:21 -0500276 // Handle the bound array buffers.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400277 for (size_t attribIndex : activeAttribsMask)
Jamie Madillbd159f02017-10-09 19:39:06 -0400278 {
Frank Henigman17448952017-01-05 15:48:26 -0500279 if (mCurrentArrayBufferResources[attribIndex])
Jamie Madill9cceac42018-03-31 14:19:16 -0400280 mCurrentArrayBufferResources[attribIndex]->onReadResource(readingNode, serial);
Jamie Madillda854a22017-11-30 17:24:21 -0500281 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400282}
Jamie Madillda854a22017-11-30 17:24:21 -0500283
Jamie Madill9cceac42018-03-31 14:19:16 -0400284void VertexArrayVk::updateElementArrayBufferReadDependency(vk::CommandGraphNode *readingNode,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400285 Serial serial)
286{
Jamie Madillda854a22017-11-30 17:24:21 -0500287 // Handle the bound element array buffer.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400288 if (mCurrentElementArrayBufferResource)
Jamie Madillda854a22017-11-30 17:24:21 -0500289 {
Jamie Madill9cceac42018-03-31 14:19:16 -0400290 mCurrentElementArrayBufferResource->onReadResource(readingNode, serial);
Jamie Madillbd159f02017-10-09 19:39:06 -0400291 }
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400292}
293
Jamie Madill112a3a82018-01-23 13:04:06 -0500294void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400295{
Jamie Madill112a3a82018-01-23 13:04:06 -0500296 updatePackedInputDescriptions();
297 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400298}
299
Jamie Madill112a3a82018-01-23 13:04:06 -0500300void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400301{
Jamie Madill112a3a82018-01-23 13:04:06 -0500302 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400303 {
304 return;
305 }
306
307 const auto &attribs = mState.getVertexAttributes();
308 const auto &bindings = mState.getVertexBindings();
309
Jamie Madill112a3a82018-01-23 13:04:06 -0500310 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400311 {
312 const auto &attrib = attribs[attribIndex];
313 const auto &binding = bindings[attrib.bindingIndex];
314 if (attrib.enabled)
315 {
Jamie Madill112a3a82018-01-23 13:04:06 -0500316 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400317 }
318 else
319 {
320 UNIMPLEMENTED();
321 }
322 }
323
Jamie Madill112a3a82018-01-23 13:04:06 -0500324 mDirtyPackedInputs.reset();
325}
326
327void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
328 const gl::VertexBinding &binding,
329 const gl::VertexAttribute &attrib)
330{
331 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
332
333 size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
334 ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
335
Frank Henigmana8e868f2018-01-28 23:32:25 -0500336 bindingDesc.stride = static_cast<uint16_t>(binding.getStride());
Jamie Madill112a3a82018-01-23 13:04:06 -0500337 bindingDesc.inputRate = static_cast<uint16_t>(
338 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
339
340 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
341 VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
342 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
343
344 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
345 attribDesc.format = static_cast<uint16_t>(vkFormat);
346 attribDesc.location = static_cast<uint16_t>(attribIndex);
347 attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
Jamie Madillebf72992017-10-13 14:09:45 -0400348}
349
Jamie Madillc3755fc2018-04-05 08:39:13 -0400350gl::Error VertexArrayVk::drawArrays(const gl::Context *context,
351 RendererVk *renderer,
352 const gl::DrawCallParams &drawCallParams,
353 vk::CommandGraphNode *drawNode,
354 bool newCommandBuffer)
355{
356 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
357 ASSERT(commandBuffer->valid());
358
359 ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
360
Jamie Madill18e323a2018-05-11 16:54:17 -0400361 // Note: Vertex indexes can be arbitrarily large.
362 uint32_t clampedVertexCount = drawCallParams.getClampedVertexCount<uint32_t>();
363
Jamie Madillc3755fc2018-04-05 08:39:13 -0400364 if (drawCallParams.mode() != GL_LINE_LOOP)
365 {
Jamie Madill18e323a2018-05-11 16:54:17 -0400366 commandBuffer->draw(clampedVertexCount, 1, drawCallParams.firstVertex(), 0);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400367 return gl::NoError();
368 }
369
370 // Handle GL_LINE_LOOP drawArrays.
Jamie Madill18e323a2018-05-11 16:54:17 -0400371 size_t lastVertex = static_cast<size_t>(drawCallParams.firstVertex() + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400372 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 Madill18e323a2018-05-11 16:54:17 -0400387 vk::LineLoopHelper::Draw(clampedVertexCount, 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.
Jamie Madillb8e39662018-04-04 11:41:42 -0400409 if (mDirtyLineLoopTranslation)
410 {
Luc Ferrona9120462018-04-12 13:11:03 -0400411 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
412 VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
413
414 if (!elementArrayBuffer)
415 {
416 ANGLE_TRY(mLineLoopHelper.getIndexBufferForClientElementArray(
417 renderer, drawCallParams.indices(), indexType, drawCallParams.indexCount(),
418 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
419 }
420 else
421 {
Luc Ferrona4fa9c22018-04-13 07:00:56 -0400422 // When using an element array buffer, 'indices' is an offset to the first element.
423 intptr_t offset = reinterpret_cast<intptr_t>(drawCallParams.indices());
Luc Ferrona9120462018-04-12 13:11:03 -0400424 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
425 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Luc Ferrona4fa9c22018-04-13 07:00:56 -0400426 renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(), offset,
Luc Ferrona9120462018-04-12 13:11:03 -0400427 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
428 }
Jamie Madillb8e39662018-04-04 11:41:42 -0400429 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400430
431 ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
Jamie Madill22f12fe2018-04-08 14:23:40 -0400432 vk::LineLoopHelper::Draw(drawCallParams.indexCount(), commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400433
434 return gl::NoError();
435}
436
437gl::Error VertexArrayVk::onDraw(const gl::Context *context,
438 RendererVk *renderer,
439 const gl::DrawCallParams &drawCallParams,
440 vk::CommandGraphNode *drawNode,
441 bool newCommandBuffer)
442{
443 const gl::State &state = context->getGLState();
444 const gl::Program *programGL = state.getProgram();
Jamie Madillbcef3222018-04-13 15:19:11 -0400445 const gl::AttributesMask &clientAttribs = mState.getEnabledClientMemoryAttribsMask();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400446 const gl::AttributesMask &activeAttribs = programGL->getActiveAttribLocationsMask();
447 uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation();
448
Jamie Madillbcef3222018-04-13 15:19:11 -0400449 if (clientAttribs.any())
Jamie Madillc3755fc2018-04-05 08:39:13 -0400450 {
Jamie Madillbcef3222018-04-13 15:19:11 -0400451 const gl::AttributesMask &attribsToStream = (clientAttribs & activeAttribs);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400452 if (attribsToStream.any())
453 {
454 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
455 ANGLE_TRY(streamVertexData(renderer, attribsToStream, drawCallParams));
456 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
457 commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
458 mCurrentArrayBufferOffsets.data());
459 }
460 }
461 else if (mVertexBuffersDirty || newCommandBuffer)
462 {
Luc Ferron44162472018-04-06 13:20:45 -0400463 if (maxAttrib > 0)
464 {
465 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
466 commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
467 mCurrentArrayBufferOffsets.data());
468 updateArrayBufferReadDependencies(drawNode, activeAttribs,
469 renderer->getCurrentQueueSerial());
470 }
Luc Ferronc1e02682018-04-11 11:02:55 -0400471
Jamie Madillc3755fc2018-04-05 08:39:13 -0400472 mVertexBuffersDirty = false;
Luc Ferronc1e02682018-04-11 11:02:55 -0400473
474 // This forces the binding to happen if we follow a drawElement call from a drawArrays call.
475 mIndexBufferDirty = true;
Luc Ferron983c4292018-04-10 13:05:45 -0400476
477 // If we've had a drawElements call with a line loop before, we want to make sure this is
478 // invalidated the next time drawElements is called since we use the same index buffer for
479 // both calls.
480 mDirtyLineLoopTranslation = true;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400481 }
482
483 return gl::NoError();
484}
485
486gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
487 RendererVk *renderer,
488 const gl::DrawCallParams &drawCallParams,
489 vk::CommandGraphNode *drawNode,
490 bool newCommandBuffer)
491{
492 ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
493
Luc Ferrona9120462018-04-12 13:11:03 -0400494 if (!mState.getElementArrayBuffer().get() && drawCallParams.mode() != GL_LINE_LOOP)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400495 {
496 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
497 ANGLE_TRY(streamIndexData(renderer, drawCallParams));
498 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
499 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
500 mCurrentElementArrayBufferOffset,
501 gl_vk::GetIndexType(drawCallParams.type()));
502 }
503 else if (mIndexBufferDirty || newCommandBuffer)
504 {
505 if (drawCallParams.type() == GL_UNSIGNED_BYTE)
506 {
507 // TODO(fjhenigman): Index format translation.
508 UNIMPLEMENTED();
509 return gl::InternalError()
510 << "Unsigned byte translation is not implemented for indices in a buffer object";
511 }
512
513 vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
514 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
515 mCurrentElementArrayBufferOffset,
516 gl_vk::GetIndexType(drawCallParams.type()));
517 updateElementArrayBufferReadDependency(drawNode, renderer->getCurrentQueueSerial());
518 mIndexBufferDirty = false;
Luc Ferron983c4292018-04-10 13:05:45 -0400519
520 // If we've had a drawArrays call with a line loop before, we want to make sure this is
521 // invalidated the next time drawArrays is called since we use the same index buffer for
522 // both calls.
523 mLineLoopBufferFirstIndex.reset();
524 mLineLoopBufferLastIndex.reset();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400525 }
526
527 return gl::NoError();
528}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400529} // namespace rx