blob: ce991d0e81011c47409dcb7aa376fea6a5cb9b31 [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 Madill316c6062018-05-29 10:49:45 -040018#include "libANGLE/renderer/vulkan/FramebufferVk.h"
Jamie Madillc3755fc2018-04-05 08:39:13 -040019#include "libANGLE/renderer/vulkan/RendererVk.h"
Jamie Madill3c424b42018-01-19 12:35:09 -050020#include "libANGLE/renderer/vulkan/vk_format_utils.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040021
Jamie Madill9e54b5a2016-05-25 12:57:39 -040022namespace rx
23{
Jamie Madillc3755fc2018-04-05 08:39:13 -040024namespace
25{
26constexpr size_t kDynamicVertexDataSize = 1024 * 1024;
27constexpr size_t kDynamicIndexDataSize = 1024 * 8;
28} // anonymous namespace
Jamie Madill9e54b5a2016-05-25 12:57:39 -040029
Luc Ferrona9ab0f32018-05-17 17:03:55 -040030VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *renderer)
Jamie Madillbd159f02017-10-09 19:39:06 -040031 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050032 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050033 mCurrentArrayBufferOffsets{},
Jamie Madillda854a22017-11-30 17:24:21 -050034 mCurrentArrayBufferResources{},
Jamie Madillc3755fc2018-04-05 08:39:13 -040035 mCurrentElementArrayBufferHandle(VK_NULL_HANDLE),
36 mCurrentElementArrayBufferOffset(0),
37 mCurrentElementArrayBufferResource(nullptr),
38 mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
39 mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Luc Ferrona9ab0f32018-05-17 17:03:55 -040040 mLineLoopHelper(renderer),
Jamie Madillb8e39662018-04-04 11:41:42 -040041 mDirtyLineLoopTranslation(true),
Jamie Madillc3755fc2018-04-05 08:39:13 -040042 mVertexBuffersDirty(false),
43 mIndexBufferDirty(false)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040044{
Jamie Madillda854a22017-11-30 17:24:21 -050045 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -050046 mCurrentArrayBufferOffsets.fill(0);
Jamie Madillda854a22017-11-30 17:24:21 -050047 mCurrentArrayBufferResources.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -050048
49 mPackedInputBindings.fill({0, 0});
50 mPackedInputAttributes.fill({0, 0, 0});
Jamie Madillc3755fc2018-04-05 08:39:13 -040051
Luc Ferrona9ab0f32018-05-17 17:03:55 -040052 mDynamicVertexData.init(1, renderer);
53 mDynamicIndexData.init(1, renderer);
Jamie Madill9e54b5a2016-05-25 12:57:39 -040054}
55
Jamie Madillacf2f3a2017-11-21 19:22:44 -050056VertexArrayVk::~VertexArrayVk()
57{
58}
59
Jamie Madill4928b7c2017-06-20 12:57:39 -040060void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040061{
Jamie Madillc3755fc2018-04-05 08:39:13 -040062 VkDevice device = vk::GetImpl(context)->getRenderer()->getDevice();
Jamie Madillc3755fc2018-04-05 08:39:13 -040063 mDynamicVertexData.destroy(device);
64 mDynamicIndexData.destroy(device);
Jamie Madill22f12fe2018-04-08 14:23:40 -040065 mLineLoopHelper.destroy(device);
Jamie Madill9e54b5a2016-05-25 12:57:39 -040066}
67
Jamie Madillc3755fc2018-04-05 08:39:13 -040068gl::Error VertexArrayVk::streamVertexData(RendererVk *renderer,
69 const gl::AttributesMask &attribsToStream,
Jamie Madill32fd63b2018-03-31 11:20:35 -040070 const gl::DrawCallParams &drawCallParams)
Frank Henigman17448952017-01-05 15:48:26 -050071{
Jamie Madillc3755fc2018-04-05 08:39:13 -040072 ASSERT(!attribsToStream.none());
73
Jamie Madillbcef3222018-04-13 15:19:11 -040074 const auto &attribs = mState.getVertexAttributes();
75 const auto &bindings = mState.getVertexBindings();
Frank Henigman17448952017-01-05 15:48:26 -050076
Jamie Madill32fd63b2018-03-31 11:20:35 -040077 const size_t lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
78
Frank Henigman17448952017-01-05 15:48:26 -050079 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
80 // un-interleaved, wasting space and copying time. Consider improving on that.
Jamie Madillb8e39662018-04-04 11:41:42 -040081 for (size_t attribIndex : attribsToStream)
Frank Henigman17448952017-01-05 15:48:26 -050082 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050083 const gl::VertexAttribute &attrib = attribs[attribIndex];
84 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
85 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
Frank Henigman17448952017-01-05 15:48:26 -050086
Frank Henigman6dd4a922018-03-02 16:35:13 -050087 // TODO(fjhenigman): Work with more formats than just GL_FLOAT.
88 if (attrib.type != GL_FLOAT)
Frank Henigman17448952017-01-05 15:48:26 -050089 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050090 UNIMPLEMENTED();
91 return gl::InternalError();
Frank Henigman17448952017-01-05 15:48:26 -050092 }
Frank Henigman6dd4a922018-03-02 16:35:13 -050093
94 // Only [firstVertex, lastVertex] is needed by the upcoming draw so that
95 // is all we copy, but we allocate space for [0, lastVertex] so indexing
96 // will work. If we don't start at zero all the indices will be off.
97 // TODO(fjhenigman): See if we can account for indices being off by adjusting
98 // the offset, thus avoiding wasted memory.
Jamie Madill32fd63b2018-03-31 11:20:35 -040099 const size_t firstByte = drawCallParams.firstVertex() * binding.getStride();
Frank Henigman6dd4a922018-03-02 16:35:13 -0500100 const size_t lastByte =
101 lastVertex * binding.getStride() + gl::ComputeVertexAttributeTypeSize(attrib);
Jamie Madill493f9572018-05-24 19:52:15 -0400102 uint8_t *dst = nullptr;
Luc Ferron7a06ac12018-03-15 10:17:04 -0400103 uint32_t offset = 0;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400104 ANGLE_TRY(mDynamicVertexData.allocate(
105 renderer, lastByte, &dst, &mCurrentArrayBufferHandles[attribIndex], &offset, nullptr));
Luc Ferron7a06ac12018-03-15 10:17:04 -0400106 mCurrentArrayBufferOffsets[attribIndex] = static_cast<VkDeviceSize>(offset);
Frank Henigman6dd4a922018-03-02 16:35:13 -0500107 memcpy(dst + firstByte, static_cast<const uint8_t *>(attrib.pointer) + firstByte,
108 lastByte - firstByte);
Frank Henigman17448952017-01-05 15:48:26 -0500109 }
110
Jamie Madillc3755fc2018-04-05 08:39:13 -0400111 ANGLE_TRY(mDynamicVertexData.flush(renderer->getDevice()));
Luc Ferron61859812018-05-09 14:17:39 -0400112 mDynamicVertexData.releaseRetainedBuffers(renderer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400113 return gl::NoError();
114}
115
116gl::Error VertexArrayVk::streamIndexData(RendererVk *renderer,
117 const gl::DrawCallParams &drawCallParams)
118{
119 ASSERT(!mState.getElementArrayBuffer().get());
120
121 uint32_t offset = 0;
122
123 const GLsizei amount = sizeof(GLushort) * drawCallParams.indexCount();
124 GLubyte *dst = nullptr;
125
126 ANGLE_TRY(mDynamicIndexData.allocate(renderer, amount, &dst, &mCurrentElementArrayBufferHandle,
127 &offset, nullptr));
128 if (drawCallParams.type() == GL_UNSIGNED_BYTE)
129 {
130 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
131 // memory to a GLushort.
132 const GLubyte *in = static_cast<const GLubyte *>(drawCallParams.indices());
133 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
134 for (GLsizei index = 0; index < drawCallParams.indexCount(); index++)
135 {
136 expandedDst[index] = static_cast<GLushort>(in[index]);
137 }
138 }
139 else
140 {
141 memcpy(dst, drawCallParams.indices(), amount);
142 }
143 ANGLE_TRY(mDynamicIndexData.flush(renderer->getDevice()));
Luc Ferron61859812018-05-09 14:17:39 -0400144 mDynamicIndexData.releaseRetainedBuffers(renderer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400145 mCurrentElementArrayBufferOffset = offset;
Frank Henigman17448952017-01-05 15:48:26 -0500146 return gl::NoError();
147}
148
Jamie Madilla56467e2018-04-11 16:19:41 -0400149#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
150 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
151 syncDirtyAttrib(attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
152 invalidatePipeline = true; \
153 break;
154
155#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
156 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
157 syncDirtyAttrib(attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
158 invalidatePipeline = true; \
159 break;
160
161#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
162 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
163 break;
164
Frank Henigman0af5b862018-03-27 20:19:33 -0400165gl::Error VertexArrayVk::syncState(const gl::Context *context,
166 const gl::VertexArray::DirtyBits &dirtyBits,
167 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
168 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400169{
170 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400171
Jamie Madillc3755fc2018-04-05 08:39:13 -0400172 bool invalidatePipeline = false;
173
Jamie Madillbd159f02017-10-09 19:39:06 -0400174 // Invalidate current pipeline.
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500175 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400176
177 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
178 // TODO(jmadill): Handle buffer storage changes.
179 const auto &attribs = mState.getVertexAttributes();
180 const auto &bindings = mState.getVertexBindings();
181
Jamie Madill09463932018-04-04 05:26:59 -0400182 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400183 {
Jamie Madill09463932018-04-04 05:26:59 -0400184 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500185 {
Jamie Madill09463932018-04-04 05:26:59 -0400186 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500187 {
Jamie Madill09463932018-04-04 05:26:59 -0400188 gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
189 if (bufferGL)
190 {
Jamie Madillc3755fc2018-04-05 08:39:13 -0400191 BufferVk *bufferVk = vk::GetImpl(bufferGL);
192 mCurrentElementArrayBufferResource = bufferVk;
193 mCurrentElementArrayBufferHandle = bufferVk->getVkBuffer().getHandle();
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;
Jamie Madill09463932018-04-04 05:26:59 -0400199 }
Luc Ferron387b3b32018-05-28 10:11:57 -0400200
201 mCurrentElementArrayBufferOffset = 0;
202 mLineLoopBufferFirstIndex.reset();
203 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400204 mIndexBufferDirty = true;
205 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400206 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500207 }
Jamie Madill09463932018-04-04 05:26:59 -0400208
209 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400210 mLineLoopBufferFirstIndex.reset();
211 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400212 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400213 break;
214
Jamie Madilla56467e2018-04-11 16:19:41 -0400215 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
216 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
217 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
218
Jamie Madill09463932018-04-04 05:26:59 -0400219 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400220 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400221 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400222 }
223 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400224
Jamie Madillc3755fc2018-04-05 08:39:13 -0400225 if (invalidatePipeline)
226 {
227 mVertexBuffersDirty = true;
228 contextVk->invalidateCurrentPipeline();
229 }
230
Frank Henigman0af5b862018-03-27 20:19:33 -0400231 return gl::NoError();
Jamie Madillbd159f02017-10-09 19:39:06 -0400232}
233
Jamie Madilla56467e2018-04-11 16:19:41 -0400234void VertexArrayVk::syncDirtyAttrib(const gl::VertexAttribute &attrib,
235 const gl::VertexBinding &binding,
236 size_t attribIndex)
237{
238 // Invalidate the input description for pipelines.
239 mDirtyPackedInputs.set(attribIndex);
240
241 if (attrib.enabled)
242 {
243 gl::Buffer *bufferGL = binding.getBuffer().get();
244
245 if (bufferGL)
246 {
247 BufferVk *bufferVk = vk::GetImpl(bufferGL);
248 mCurrentArrayBufferResources[attribIndex] = bufferVk;
249 mCurrentArrayBufferHandles[attribIndex] = bufferVk->getVkBuffer().getHandle();
Jamie Madilla56467e2018-04-11 16:19:41 -0400250 }
251 else
252 {
253 mCurrentArrayBufferResources[attribIndex] = nullptr;
254 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
Jamie Madilla56467e2018-04-11 16:19:41 -0400255 }
256 // TODO(jmadill): Offset handling. Assume zero for now.
257 mCurrentArrayBufferOffsets[attribIndex] = 0;
258 }
259 else
260 {
Jamie Madilla56467e2018-04-11 16:19:41 -0400261 UNIMPLEMENTED();
262 }
263}
264
Jamie Madillda854a22017-11-30 17:24:21 -0500265const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const
Jamie Madillbd159f02017-10-09 19:39:06 -0400266{
Jamie Madillda854a22017-11-30 17:24:21 -0500267 return mCurrentArrayBufferHandles;
Jamie Madillbd159f02017-10-09 19:39:06 -0400268}
269
Frank Henigman17448952017-01-05 15:48:26 -0500270const gl::AttribArray<VkDeviceSize> &VertexArrayVk::getCurrentArrayBufferOffsets() const
271{
272 return mCurrentArrayBufferOffsets;
273}
274
Jamie Madill316c6062018-05-29 10:49:45 -0400275void VertexArrayVk::updateArrayBufferReadDependencies(vk::CommandGraphResource *drawFramebuffer,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400276 const gl::AttributesMask &activeAttribsMask,
277 Serial serial)
Jamie Madillbd159f02017-10-09 19:39:06 -0400278{
Jamie Madillda854a22017-11-30 17:24:21 -0500279 // Handle the bound array buffers.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400280 for (size_t attribIndex : activeAttribsMask)
Jamie Madillbd159f02017-10-09 19:39:06 -0400281 {
Frank Henigman17448952017-01-05 15:48:26 -0500282 if (mCurrentArrayBufferResources[attribIndex])
Jamie Madill316c6062018-05-29 10:49:45 -0400283 mCurrentArrayBufferResources[attribIndex]->addReadDependency(drawFramebuffer);
Jamie Madillda854a22017-11-30 17:24:21 -0500284 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400285}
Jamie Madillda854a22017-11-30 17:24:21 -0500286
Jamie Madill316c6062018-05-29 10:49:45 -0400287void VertexArrayVk::updateElementArrayBufferReadDependency(
288 vk::CommandGraphResource *drawFramebuffer,
289 Serial serial)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400290{
Jamie Madillda854a22017-11-30 17:24:21 -0500291 // Handle the bound element array buffer.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400292 if (mCurrentElementArrayBufferResource)
Jamie Madillda854a22017-11-30 17:24:21 -0500293 {
Jamie Madill316c6062018-05-29 10:49:45 -0400294 mCurrentElementArrayBufferResource->addReadDependency(drawFramebuffer);
Jamie Madillbd159f02017-10-09 19:39:06 -0400295 }
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400296}
297
Jamie Madill112a3a82018-01-23 13:04:06 -0500298void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400299{
Jamie Madill112a3a82018-01-23 13:04:06 -0500300 updatePackedInputDescriptions();
301 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400302}
303
Jamie Madill112a3a82018-01-23 13:04:06 -0500304void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400305{
Jamie Madill112a3a82018-01-23 13:04:06 -0500306 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400307 {
308 return;
309 }
310
311 const auto &attribs = mState.getVertexAttributes();
312 const auto &bindings = mState.getVertexBindings();
313
Jamie Madill112a3a82018-01-23 13:04:06 -0500314 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400315 {
316 const auto &attrib = attribs[attribIndex];
317 const auto &binding = bindings[attrib.bindingIndex];
318 if (attrib.enabled)
319 {
Jamie Madill112a3a82018-01-23 13:04:06 -0500320 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400321 }
322 else
323 {
324 UNIMPLEMENTED();
325 }
326 }
327
Jamie Madill112a3a82018-01-23 13:04:06 -0500328 mDirtyPackedInputs.reset();
329}
330
331void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
332 const gl::VertexBinding &binding,
333 const gl::VertexAttribute &attrib)
334{
335 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
336
337 size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
338 ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
339
Frank Henigmana8e868f2018-01-28 23:32:25 -0500340 bindingDesc.stride = static_cast<uint16_t>(binding.getStride());
Jamie Madill112a3a82018-01-23 13:04:06 -0500341 bindingDesc.inputRate = static_cast<uint16_t>(
342 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
343
344 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
345 VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
346 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
347
348 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
349 attribDesc.format = static_cast<uint16_t>(vkFormat);
350 attribDesc.location = static_cast<uint16_t>(attribIndex);
351 attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
Jamie Madillebf72992017-10-13 14:09:45 -0400352}
353
Jamie Madillc3755fc2018-04-05 08:39:13 -0400354gl::Error VertexArrayVk::drawArrays(const gl::Context *context,
355 RendererVk *renderer,
356 const gl::DrawCallParams &drawCallParams,
Jamie Madill316c6062018-05-29 10:49:45 -0400357 vk::CommandBuffer *commandBuffer,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400358 bool newCommandBuffer)
359{
Jamie Madillc3755fc2018-04-05 08:39:13 -0400360 ASSERT(commandBuffer->valid());
361
Jamie Madill316c6062018-05-29 10:49:45 -0400362 ANGLE_TRY(onDraw(context, renderer, drawCallParams, commandBuffer, newCommandBuffer));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400363
Jamie Madill18e323a2018-05-11 16:54:17 -0400364 // Note: Vertex indexes can be arbitrarily large.
365 uint32_t clampedVertexCount = drawCallParams.getClampedVertexCount<uint32_t>();
366
Jamie Madill493f9572018-05-24 19:52:15 -0400367 if (drawCallParams.mode() != gl::PrimitiveMode::LineLoop)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400368 {
Jamie Madill18e323a2018-05-11 16:54:17 -0400369 commandBuffer->draw(clampedVertexCount, 1, drawCallParams.firstVertex(), 0);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400370 return gl::NoError();
371 }
372
373 // Handle GL_LINE_LOOP drawArrays.
Jamie Madill18e323a2018-05-11 16:54:17 -0400374 size_t lastVertex = static_cast<size_t>(drawCallParams.firstVertex() + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400375 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
376 mLineLoopBufferFirstIndex != drawCallParams.firstVertex() ||
377 mLineLoopBufferLastIndex != lastVertex)
378 {
Jamie Madill22f12fe2018-04-08 14:23:40 -0400379 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(renderer, drawCallParams,
380 &mCurrentElementArrayBufferHandle,
381 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400382
383 mLineLoopBufferFirstIndex = drawCallParams.firstVertex();
384 mLineLoopBufferLastIndex = lastVertex;
385 }
386
387 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
388 mCurrentElementArrayBufferOffset, VK_INDEX_TYPE_UINT32);
389
Jamie Madill18e323a2018-05-11 16:54:17 -0400390 vk::LineLoopHelper::Draw(clampedVertexCount, commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400391
392 return gl::NoError();
393}
394
395gl::Error VertexArrayVk::drawElements(const gl::Context *context,
396 RendererVk *renderer,
397 const gl::DrawCallParams &drawCallParams,
Jamie Madill316c6062018-05-29 10:49:45 -0400398 vk::CommandBuffer *commandBuffer,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400399 bool newCommandBuffer)
400{
Jamie Madillc3755fc2018-04-05 08:39:13 -0400401 ASSERT(commandBuffer->valid());
402
Jamie Madill493f9572018-05-24 19:52:15 -0400403 if (drawCallParams.mode() != gl::PrimitiveMode::LineLoop)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400404 {
Jamie Madill316c6062018-05-29 10:49:45 -0400405 ANGLE_TRY(
406 onIndexedDraw(context, renderer, drawCallParams, commandBuffer, newCommandBuffer));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400407 commandBuffer->drawIndexed(drawCallParams.indexCount(), 1, 0, 0, 0);
408 return gl::NoError();
409 }
410
411 // Handle GL_LINE_LOOP drawElements.
Jamie Madillb8e39662018-04-04 11:41:42 -0400412 if (mDirtyLineLoopTranslation)
413 {
Luc Ferrona9120462018-04-12 13:11:03 -0400414 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
415 VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
416
417 if (!elementArrayBuffer)
418 {
419 ANGLE_TRY(mLineLoopHelper.getIndexBufferForClientElementArray(
420 renderer, drawCallParams.indices(), indexType, drawCallParams.indexCount(),
421 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
422 }
423 else
424 {
Luc Ferrona4fa9c22018-04-13 07:00:56 -0400425 // When using an element array buffer, 'indices' is an offset to the first element.
426 intptr_t offset = reinterpret_cast<intptr_t>(drawCallParams.indices());
Luc Ferrona9120462018-04-12 13:11:03 -0400427 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
428 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Luc Ferrona4fa9c22018-04-13 07:00:56 -0400429 renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(), offset,
Luc Ferrona9120462018-04-12 13:11:03 -0400430 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
431 }
Jamie Madillb8e39662018-04-04 11:41:42 -0400432 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400433
Jamie Madill316c6062018-05-29 10:49:45 -0400434 ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, commandBuffer, newCommandBuffer));
Jamie Madill22f12fe2018-04-08 14:23:40 -0400435 vk::LineLoopHelper::Draw(drawCallParams.indexCount(), commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400436
437 return gl::NoError();
438}
439
440gl::Error VertexArrayVk::onDraw(const gl::Context *context,
441 RendererVk *renderer,
442 const gl::DrawCallParams &drawCallParams,
Jamie Madill316c6062018-05-29 10:49:45 -0400443 vk::CommandBuffer *commandBuffer,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400444 bool newCommandBuffer)
445{
446 const gl::State &state = context->getGLState();
447 const gl::Program *programGL = state.getProgram();
Jamie Madillbcef3222018-04-13 15:19:11 -0400448 const gl::AttributesMask &clientAttribs = mState.getEnabledClientMemoryAttribsMask();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400449 const gl::AttributesMask &activeAttribs = programGL->getActiveAttribLocationsMask();
450 uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation();
451
Jamie Madillbcef3222018-04-13 15:19:11 -0400452 if (clientAttribs.any())
Jamie Madillc3755fc2018-04-05 08:39:13 -0400453 {
Jamie Madillbcef3222018-04-13 15:19:11 -0400454 const gl::AttributesMask &attribsToStream = (clientAttribs & activeAttribs);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400455 if (attribsToStream.any())
456 {
457 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
458 ANGLE_TRY(streamVertexData(renderer, attribsToStream, drawCallParams));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400459 commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
460 mCurrentArrayBufferOffsets.data());
461 }
462 }
463 else if (mVertexBuffersDirty || newCommandBuffer)
464 {
Luc Ferron44162472018-04-06 13:20:45 -0400465 if (maxAttrib > 0)
466 {
Luc Ferron44162472018-04-06 13:20:45 -0400467 commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
468 mCurrentArrayBufferOffsets.data());
Jamie Madill316c6062018-05-29 10:49:45 -0400469
470 vk::CommandGraphResource *drawFramebuffer = vk::GetImpl(state.getDrawFramebuffer());
471 updateArrayBufferReadDependencies(drawFramebuffer, activeAttribs,
Luc Ferron44162472018-04-06 13:20:45 -0400472 renderer->getCurrentQueueSerial());
473 }
Luc Ferronc1e02682018-04-11 11:02:55 -0400474
Jamie Madillc3755fc2018-04-05 08:39:13 -0400475 mVertexBuffersDirty = false;
Luc Ferronc1e02682018-04-11 11:02:55 -0400476
477 // This forces the binding to happen if we follow a drawElement call from a drawArrays call.
478 mIndexBufferDirty = true;
Luc Ferron983c4292018-04-10 13:05:45 -0400479
480 // If we've had a drawElements call with a line loop before, we want to make sure this is
481 // invalidated the next time drawElements is called since we use the same index buffer for
482 // both calls.
483 mDirtyLineLoopTranslation = true;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400484 }
485
486 return gl::NoError();
487}
488
489gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
490 RendererVk *renderer,
491 const gl::DrawCallParams &drawCallParams,
Jamie Madill316c6062018-05-29 10:49:45 -0400492 vk::CommandBuffer *commandBuffer,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400493 bool newCommandBuffer)
494{
Jamie Madill316c6062018-05-29 10:49:45 -0400495 ANGLE_TRY(onDraw(context, renderer, drawCallParams, commandBuffer, newCommandBuffer));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400496
Jamie Madill493f9572018-05-24 19:52:15 -0400497 if (!mState.getElementArrayBuffer().get() &&
498 drawCallParams.mode() != gl::PrimitiveMode::LineLoop)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400499 {
500 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
501 ANGLE_TRY(streamIndexData(renderer, drawCallParams));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400502 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
503 mCurrentElementArrayBufferOffset,
504 gl_vk::GetIndexType(drawCallParams.type()));
505 }
506 else if (mIndexBufferDirty || newCommandBuffer)
507 {
508 if (drawCallParams.type() == GL_UNSIGNED_BYTE)
509 {
510 // TODO(fjhenigman): Index format translation.
511 UNIMPLEMENTED();
512 return gl::InternalError()
513 << "Unsigned byte translation is not implemented for indices in a buffer object";
514 }
515
Jamie Madillc3755fc2018-04-05 08:39:13 -0400516 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
517 mCurrentElementArrayBufferOffset,
518 gl_vk::GetIndexType(drawCallParams.type()));
Jamie Madill316c6062018-05-29 10:49:45 -0400519
520 const gl::State &glState = context->getGLState();
521 vk::CommandGraphResource *drawFramebuffer = vk::GetImpl(glState.getDrawFramebuffer());
522 updateElementArrayBufferReadDependency(drawFramebuffer, renderer->getCurrentQueueSerial());
Jamie Madillc3755fc2018-04-05 08:39:13 -0400523 mIndexBufferDirty = false;
Luc Ferron983c4292018-04-10 13:05:45 -0400524
525 // If we've had a drawArrays call with a line loop before, we want to make sure this is
526 // invalidated the next time drawArrays is called since we use the same index buffer for
527 // both calls.
528 mLineLoopBufferFirstIndex.reset();
529 mLineLoopBufferLastIndex.reset();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400530 }
531
532 return gl::NoError();
533}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400534} // namespace rx