blob: 142b9cb3ce4063166b39df6ef6789f15db60e3d6 [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"
Jamie Madillbfe31c42018-10-25 17:03:47 -040013#include "common/utilities.h"
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{
Jamie Madill77abad82018-10-25 17:03:48 -040026constexpr size_t kDynamicVertexDataSize = 1024 * 1024;
27constexpr size_t kDynamicIndexDataSize = 1024 * 8;
jchen105dc0a6f2018-09-20 14:30:45 +080028constexpr size_t kMaxVertexFormatAlignment = 4;
Frank Henigmane4523822018-07-19 16:10:53 -040029
30bool BindingIsAligned(const gl::VertexBinding &binding, unsigned componentSize)
31{
32 return (binding.getOffset() % componentSize == 0) && (binding.getStride() % componentSize == 0);
33}
Jamie Madilla064c272018-08-30 16:18:34 -040034
35angle::Result StreamVertexData(ContextVk *contextVk,
36 vk::DynamicBuffer *dynamicBuffer,
37 const uint8_t *sourceData,
38 size_t bytesToAllocate,
39 size_t destOffset,
40 size_t vertexCount,
41 size_t stride,
42 VertexCopyFunction vertexLoadFunction,
43 VkBuffer *bufferHandleOut,
44 VkDeviceSize *bufferOffsetOut)
45{
46 uint8_t *dst = nullptr;
47 ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, bufferHandleOut,
48 bufferOffsetOut, nullptr));
49 dst += destOffset;
50 vertexLoadFunction(sourceData, stride, vertexCount, dst);
51
52 ANGLE_TRY(dynamicBuffer->flush(contextVk));
53 return angle::Result::Continue();
54}
jchen105dc0a6f2018-09-20 14:30:45 +080055
Jamie Madillc3755fc2018-04-05 08:39:13 -040056} // anonymous namespace
Jamie Madill9e54b5a2016-05-25 12:57:39 -040057
Frank Henigmane4523822018-07-19 16:10:53 -040058#define INIT \
59 { \
60 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 1024 * 8 \
61 }
62
Luc Ferrona9ab0f32018-05-17 17:03:55 -040063VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *renderer)
Jamie Madillbd159f02017-10-09 19:39:06 -040064 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050065 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050066 mCurrentArrayBufferOffsets{},
Jamie Madill03d1a5e2018-11-12 11:34:24 -050067 mCurrentArrayBuffers{},
Frank Henigman419acc82018-06-24 19:57:31 -040068 mCurrentArrayBufferFormats{},
69 mCurrentArrayBufferStrides{},
Frank Henigmane4523822018-07-19 16:10:53 -040070 mCurrentArrayBufferConversion{{
Jamie Madillb980c562018-11-27 11:34:27 -050071 INIT,
72 INIT,
73 INIT,
74 INIT,
75 INIT,
76 INIT,
77 INIT,
78 INIT,
79 INIT,
80 INIT,
81 INIT,
82 INIT,
83 INIT,
84 INIT,
85 INIT,
Frank Henigmane4523822018-07-19 16:10:53 -040086 INIT,
87 }},
88 mCurrentArrayBufferConversionCanRelease{},
Jamie Madillc3755fc2018-04-05 08:39:13 -040089 mCurrentElementArrayBufferHandle(VK_NULL_HANDLE),
90 mCurrentElementArrayBufferOffset(0),
Jamie Madill03d1a5e2018-11-12 11:34:24 -050091 mCurrentElementArrayBuffer(nullptr),
Jamie Madill77b24362018-11-05 22:39:29 -050092 mPackedInputBindings{},
93 mPackedInputAttributes{},
Jamie Madillc3755fc2018-04-05 08:39:13 -040094 mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
95 mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Luc Ferron6ed167a2018-06-13 13:45:55 -040096 mTranslatedByteIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Luc Ferrona9ab0f32018-05-17 17:03:55 -040097 mLineLoopHelper(renderer),
Jamie Madill88fc6da2018-08-30 16:18:36 -040098 mDirtyLineLoopTranslation(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040099{
Jamie Madillda854a22017-11-30 17:24:21 -0500100 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -0500101 mCurrentArrayBufferOffsets.fill(0);
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500102 mCurrentArrayBuffers.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -0500103
Frank Henigmane4523822018-07-19 16:10:53 -0400104 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
105 {
jchen105dc0a6f2018-09-20 14:30:45 +0800106 buffer.init(kMaxVertexFormatAlignment, renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400107 }
jchen105dc0a6f2018-09-20 14:30:45 +0800108 mDynamicVertexData.init(kMaxVertexFormatAlignment, renderer);
Luc Ferrona9ab0f32018-05-17 17:03:55 -0400109 mDynamicIndexData.init(1, renderer);
Luc Ferron6ed167a2018-06-13 13:45:55 -0400110 mTranslatedByteIndexData.init(1, renderer);
Jamie Madill0a17e482018-08-31 17:19:11 -0400111
112 // Initially consider all inputs dirty.
113 mDirtyPackedInputs.set();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400114}
115
Jamie Madillb980c562018-11-27 11:34:27 -0500116VertexArrayVk::~VertexArrayVk() {}
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500117
Jamie Madill4928b7c2017-06-20 12:57:39 -0400118void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400119{
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500120 RendererVk *renderer = vk::GetImpl(context)->getRenderer();
121
Frank Henigmane4523822018-07-19 16:10:53 -0400122 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
123 {
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500124 buffer.release(renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400125 }
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500126 mDynamicVertexData.release(renderer);
127 mDynamicIndexData.release(renderer);
128 mTranslatedByteIndexData.release(renderer);
129 mLineLoopHelper.release(renderer);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400130}
131
Jamie Madill21061022018-07-12 23:56:30 -0400132angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
Jamie Madill253038d2018-08-30 16:18:35 -0400133 GLenum indexType,
134 size_t indexCount,
135 const void *sourcePointer,
136 vk::DynamicBuffer *dynamicBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400137{
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400138 ASSERT(!mState.getElementArrayBuffer() || indexType == GL_UNSIGNED_BYTE);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400139
Jamie Madill253038d2018-08-30 16:18:35 -0400140 dynamicBuffer->releaseRetainedBuffers(contextVk->getRenderer());
Jamie Madilla064c272018-08-30 16:18:34 -0400141
Jamie Madill253038d2018-08-30 16:18:35 -0400142 const size_t amount = sizeof(GLushort) * indexCount;
143 GLubyte *dst = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400144
Jamie Madill253038d2018-08-30 16:18:35 -0400145 ANGLE_TRY(dynamicBuffer->allocate(contextVk, amount, &dst, &mCurrentElementArrayBufferHandle,
146 &mCurrentElementArrayBufferOffset, nullptr));
147 if (indexType == GL_UNSIGNED_BYTE)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400148 {
149 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
150 // memory to a GLushort.
Jamie Madill253038d2018-08-30 16:18:35 -0400151 const GLubyte *in = static_cast<const GLubyte *>(sourcePointer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400152 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
Jamie Madill253038d2018-08-30 16:18:35 -0400153 for (size_t index = 0; index < indexCount; index++)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400154 {
155 expandedDst[index] = static_cast<GLushort>(in[index]);
156 }
157 }
158 else
159 {
Jamie Madill253038d2018-08-30 16:18:35 -0400160 memcpy(dst, sourcePointer, amount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400161 }
Jamie Madill253038d2018-08-30 16:18:35 -0400162 ANGLE_TRY(dynamicBuffer->flush(contextVk));
Jamie Madill21061022018-07-12 23:56:30 -0400163 return angle::Result::Continue();
Frank Henigman17448952017-01-05 15:48:26 -0500164}
165
Frank Henigmane4523822018-07-19 16:10:53 -0400166// We assume the buffer is completely full of the same kind of data and convert
167// and/or align it as we copy it to a DynamicBuffer. The assumption could be wrong
168// but the alternative of copying it piecemeal on each draw would have a lot more
169// overhead.
Jamie Madilla064c272018-08-30 16:18:34 -0400170angle::Result VertexArrayVk::convertVertexBuffer(ContextVk *contextVk,
Frank Henigmane4523822018-07-19 16:10:53 -0400171 BufferVk *srcBuffer,
172 const gl::VertexBinding &binding,
173 size_t attribIndex)
174{
175
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400176 // Needed before reading buffer or we could get stale data.
Jamie Madilla064c272018-08-30 16:18:34 -0400177 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400178
179 unsigned srcFormatSize = mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes;
Jamie Madilla064c272018-08-30 16:18:34 -0400180 unsigned dstFormatSize = mCurrentArrayBufferStrides[attribIndex];
181
182 mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(contextVk->getRenderer());
Frank Henigmane4523822018-07-19 16:10:53 -0400183
184 // Bytes usable for vertex data.
185 GLint64 bytes = srcBuffer->getSize() - binding.getOffset();
186 if (bytes < srcFormatSize)
187 return angle::Result::Continue();
188
189 // Count the last vertex. It may occupy less than a full stride.
190 size_t numVertices = 1;
191 bytes -= srcFormatSize;
192
193 // Count how many strides fit remaining space.
194 if (bytes > 0)
195 numVertices += static_cast<size_t>(bytes) / binding.getStride();
196
Jamie Madill77abad82018-10-25 17:03:48 -0400197 void *src = nullptr;
Jamie Madilla064c272018-08-30 16:18:34 -0400198 ANGLE_TRY(srcBuffer->mapImpl(contextVk, &src));
199 const uint8_t *srcBytes = reinterpret_cast<const uint8_t *>(src);
200 srcBytes += binding.getOffset();
jchen105dc0a6f2018-09-20 14:30:45 +0800201 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
202 kMaxVertexFormatAlignment);
Jamie Madilla064c272018-08-30 16:18:34 -0400203 ANGLE_TRY(StreamVertexData(contextVk, &mCurrentArrayBufferConversion[attribIndex], srcBytes,
204 numVertices * dstFormatSize, 0, numVertices, binding.getStride(),
205 mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
206 &mCurrentArrayBufferHandles[attribIndex],
207 &mCurrentArrayBufferOffsets[attribIndex]));
208 ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400209
210 mCurrentArrayBufferConversionCanRelease[attribIndex] = true;
Frank Henigmane4523822018-07-19 16:10:53 -0400211
212 return angle::Result::Continue();
213}
214
215void VertexArrayVk::ensureConversionReleased(RendererVk *renderer, size_t attribIndex)
216{
217 if (mCurrentArrayBufferConversionCanRelease[attribIndex])
218 {
219 mCurrentArrayBufferConversion[attribIndex].release(renderer);
220 mCurrentArrayBufferConversionCanRelease[attribIndex] = false;
221 }
222}
223
224#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
225 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
226 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
227 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500228 invalidateContext = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400229 break;
230
Frank Henigmane4523822018-07-19 16:10:53 -0400231#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
232 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
233 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
234 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500235 invalidateContext = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400236 break;
237
Frank Henigmane4523822018-07-19 16:10:53 -0400238#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
239 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
240 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
241 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madilla56467e2018-04-11 16:19:41 -0400242 break;
243
Jamie Madill6f755b22018-10-09 12:48:54 -0400244angle::Result VertexArrayVk::syncState(const gl::Context *context,
245 const gl::VertexArray::DirtyBits &dirtyBits,
246 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
247 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400248{
249 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400250
Jamie Madillbc5834c2018-11-06 11:13:50 -0500251 bool invalidateContext = false;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400252
Jamie Madill5a4c9322018-07-16 11:01:58 -0400253 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400254
255 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
256 // TODO(jmadill): Handle buffer storage changes.
257 const auto &attribs = mState.getVertexAttributes();
258 const auto &bindings = mState.getVertexBindings();
259
Jamie Madill09463932018-04-04 05:26:59 -0400260 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400261 {
Jamie Madill09463932018-04-04 05:26:59 -0400262 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500263 {
Jamie Madill09463932018-04-04 05:26:59 -0400264 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500265 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400266 gl::Buffer *bufferGL = mState.getElementArrayBuffer();
Jamie Madill09463932018-04-04 05:26:59 -0400267 if (bufferGL)
268 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500269 BufferVk *bufferVk = vk::GetImpl(bufferGL);
270 mCurrentElementArrayBuffer = &bufferVk->getBuffer();
Jamie Madill2d03ff42018-09-27 15:04:26 -0400271 mCurrentElementArrayBufferHandle =
272 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill09463932018-04-04 05:26:59 -0400273 }
274 else
275 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500276 mCurrentElementArrayBuffer = nullptr;
277 mCurrentElementArrayBufferHandle = VK_NULL_HANDLE;
Jamie Madill09463932018-04-04 05:26:59 -0400278 }
Luc Ferron387b3b32018-05-28 10:11:57 -0400279
280 mCurrentElementArrayBufferOffset = 0;
281 mLineLoopBufferFirstIndex.reset();
282 mLineLoopBufferLastIndex.reset();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400283 contextVk->setIndexBufferDirty();
Jamie Madillb8e39662018-04-04 11:41:42 -0400284 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400285 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500286 }
Jamie Madill09463932018-04-04 05:26:59 -0400287
288 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400289 mLineLoopBufferFirstIndex.reset();
290 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400291 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400292 break;
293
Jamie Madilla56467e2018-04-11 16:19:41 -0400294 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
295 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
296 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
297
Jamie Madill09463932018-04-04 05:26:59 -0400298 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400299 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400300 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400301 }
302 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400303
Jamie Madillbc5834c2018-11-06 11:13:50 -0500304 if (invalidateContext)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400305 {
Jamie Madillbc5834c2018-11-06 11:13:50 -0500306 contextVk->invalidateVertexAndIndexBuffers();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400307 }
308
Jamie Madill6f755b22018-10-09 12:48:54 -0400309 return angle::Result::Continue();
Jamie Madillbd159f02017-10-09 19:39:06 -0400310}
311
Frank Henigmane4523822018-07-19 16:10:53 -0400312angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
313 const gl::VertexAttribute &attrib,
314 const gl::VertexBinding &binding,
315 size_t attribIndex)
Jamie Madilla56467e2018-04-11 16:19:41 -0400316{
317 // Invalidate the input description for pipelines.
318 mDirtyPackedInputs.set(attribIndex);
319
Frank Henigman67c388e2018-07-19 19:16:11 -0400320 RendererVk *renderer = contextVk->getRenderer();
Frank Henigmane4523822018-07-19 16:10:53 -0400321 bool releaseConversion = true;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400322
Jamie Madilla56467e2018-04-11 16:19:41 -0400323 if (attrib.enabled)
324 {
Frank Henigman67c388e2018-07-19 19:16:11 -0400325 gl::Buffer *bufferGL = binding.getBuffer().get();
Frank Henigman419acc82018-06-24 19:57:31 -0400326 mCurrentArrayBufferFormats[attribIndex] = &renderer->getFormat(GetVertexFormatID(attrib));
Frank Henigmane4523822018-07-19 16:10:53 -0400327
Jamie Madilla56467e2018-04-11 16:19:41 -0400328 if (bufferGL)
329 {
Frank Henigmane4523822018-07-19 16:10:53 -0400330 BufferVk *bufferVk = vk::GetImpl(bufferGL);
331 unsigned componentSize =
332 mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes / attrib.size;
Frank Henigman419acc82018-06-24 19:57:31 -0400333
Frank Henigmane4523822018-07-19 16:10:53 -0400334 if (mCurrentArrayBufferFormats[attribIndex]->vertexLoadRequiresConversion ||
335 !BindingIsAligned(binding, componentSize))
336 {
Jamie Madilla064c272018-08-30 16:18:34 -0400337 mCurrentArrayBufferStrides[attribIndex] =
338 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
339
Frank Henigmane4523822018-07-19 16:10:53 -0400340 ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex));
341
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500342 mCurrentArrayBuffers[attribIndex] = nullptr;
343 releaseConversion = false;
Frank Henigmane4523822018-07-19 16:10:53 -0400344 }
345 else
346 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500347 mCurrentArrayBuffers[attribIndex] = &bufferVk->getBuffer();
Jamie Madill2d03ff42018-09-27 15:04:26 -0400348 mCurrentArrayBufferHandles[attribIndex] =
349 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill77abad82018-10-25 17:03:48 -0400350 mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
351 mCurrentArrayBufferStrides[attribIndex] = binding.getStride();
Frank Henigmane4523822018-07-19 16:10:53 -0400352 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400353 }
354 else
355 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500356 mCurrentArrayBuffers[attribIndex] = nullptr;
357 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
358 mCurrentArrayBufferOffsets[attribIndex] = 0;
Frank Henigman419acc82018-06-24 19:57:31 -0400359 mCurrentArrayBufferStrides[attribIndex] =
Frank Henigmane4523822018-07-19 16:10:53 -0400360 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
Jamie Madilla56467e2018-04-11 16:19:41 -0400361 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400362 }
363 else
364 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400365 contextVk->invalidateDefaultAttribute(attribIndex);
366
367 // These will be filled out by the ContextVk.
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500368 mCurrentArrayBuffers[attribIndex] = nullptr;
369 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
370 mCurrentArrayBufferOffsets[attribIndex] = 0;
371 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400372 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400373 &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
Jamie Madilla56467e2018-04-11 16:19:41 -0400374 }
Frank Henigmane4523822018-07-19 16:10:53 -0400375
376 if (releaseConversion)
377 ensureConversionReleased(renderer, attribIndex);
378
379 return angle::Result::Continue();
Jamie Madilla56467e2018-04-11 16:19:41 -0400380}
381
Shahbaz Youssefic30f45d2018-11-12 16:37:59 -0500382void VertexArrayVk::getPackedInputDescriptions(vk::GraphicsPipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400383{
Frank Henigman419acc82018-06-24 19:57:31 -0400384 updatePackedInputDescriptions();
Jamie Madill112a3a82018-01-23 13:04:06 -0500385 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400386}
387
Frank Henigman419acc82018-06-24 19:57:31 -0400388void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400389{
Jamie Madill112a3a82018-01-23 13:04:06 -0500390 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400391 {
392 return;
393 }
394
395 const auto &attribs = mState.getVertexAttributes();
396 const auto &bindings = mState.getVertexBindings();
397
Jamie Madill112a3a82018-01-23 13:04:06 -0500398 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400399 {
400 const auto &attrib = attribs[attribIndex];
401 const auto &binding = bindings[attrib.bindingIndex];
402 if (attrib.enabled)
403 {
Frank Henigman419acc82018-06-24 19:57:31 -0400404 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400405 }
406 else
407 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400408 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
409 bindingDesc.stride = 0;
410 bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
411
Jamie Madill77b24362018-11-05 22:39:29 -0500412 mPackedInputAttributes.formats[attribIndex] =
413 static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
414 mPackedInputAttributes.offsets[attribIndex] = 0;
Jamie Madillebf72992017-10-13 14:09:45 -0400415 }
416 }
417
Jamie Madill112a3a82018-01-23 13:04:06 -0500418 mDirtyPackedInputs.reset();
419}
420
Frank Henigman419acc82018-06-24 19:57:31 -0400421void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
Jamie Madill112a3a82018-01-23 13:04:06 -0500422 const gl::VertexBinding &binding,
423 const gl::VertexAttribute &attrib)
424{
425 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
426
Frank Henigman419acc82018-06-24 19:57:31 -0400427 bindingDesc.stride = static_cast<uint16_t>(mCurrentArrayBufferStrides[attribIndex]);
Jamie Madill112a3a82018-01-23 13:04:06 -0500428 bindingDesc.inputRate = static_cast<uint16_t>(
429 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
430
Frank Henigman419acc82018-06-24 19:57:31 -0400431 VkFormat vkFormat = mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat;
Jamie Madill112a3a82018-01-23 13:04:06 -0500432 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
Frank Henigman8c379f32018-06-21 19:55:05 -0400433 if (vkFormat == VK_FORMAT_UNDEFINED)
434 {
Frank Henigman8c379f32018-06-21 19:55:05 -0400435 UNIMPLEMENTED();
436 }
Jamie Madill112a3a82018-01-23 13:04:06 -0500437
Jamie Madill77b24362018-11-05 22:39:29 -0500438 mPackedInputAttributes.formats[attribIndex] = static_cast<uint8_t>(vkFormat);
439 mPackedInputAttributes.offsets[attribIndex] = static_cast<uint16_t>(attrib.relativeOffset);
Jamie Madillebf72992017-10-13 14:09:45 -0400440}
441
Jamie Madill88fc6da2018-08-30 16:18:36 -0400442angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400443 GLint firstVertex,
444 GLsizei vertexOrIndexCount,
445 GLenum indexTypeOrNone,
446 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400447{
Jamie Madill77abad82018-10-25 17:03:48 -0400448 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400449 const gl::AttributesMask &clientAttribs = context->getStateCache().getActiveClientAttribsMask();
Jamie Madill21061022018-07-12 23:56:30 -0400450
Jamie Madill88fc6da2018-08-30 16:18:36 -0400451 ASSERT(clientAttribs.any());
Jamie Madillc1fd7372018-10-26 22:48:39 -0400452
453 GLint startVertex;
454 size_t vertexCount;
Jamie Madillbfe31c42018-10-25 17:03:47 -0400455 ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrNone, indices,
456 0, &startVertex, &vertexCount));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400457
458 mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
459
460 const auto &attribs = mState.getVertexAttributes();
461 const auto &bindings = mState.getVertexBindings();
462
463 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
464 // un-interleaved, wasting space and copying time. Consider improving on that.
465 for (size_t attribIndex : clientAttribs)
466 {
467 const gl::VertexAttribute &attrib = attribs[attribIndex];
468 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
469 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
470
471 const size_t bytesToAllocate =
Jamie Madillc1fd7372018-10-26 22:48:39 -0400472 (startVertex + vertexCount) * mCurrentArrayBufferStrides[attribIndex];
473 const uint8_t *src =
474 static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400475
Jamie Madillc1fd7372018-10-26 22:48:39 -0400476 size_t destOffset = startVertex * mCurrentArrayBufferStrides[attribIndex];
jchen105dc0a6f2018-09-20 14:30:45 +0800477 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
478 kMaxVertexFormatAlignment);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400479
480 // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400481 // We allocate space for startVertex + vertexCount so indexing will work. If we
Jamie Madill88fc6da2018-08-30 16:18:36 -0400482 // don't start at zero all the indices will be off.
483 // TODO(fjhenigman): See if we can account for indices being off by adjusting the
484 // offset, thus avoiding wasted memory.
Jamie Madillc1fd7372018-10-26 22:48:39 -0400485 ANGLE_TRY(StreamVertexData(
486 contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
487 binding.getStride(), mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
488 &mCurrentArrayBufferHandles[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400489 }
490
491 return angle::Result::Continue();
492}
493
494angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400495 GLint firstVertex,
496 GLsizei vertexOrIndexCount,
497 GLenum indexTypeOrNone,
498 const void *indices)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400499{
Jamie Madillbfe31c42018-10-25 17:03:47 -0400500 if (indexTypeOrNone != GL_NONE)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400501 {
502 // Handle GL_LINE_LOOP drawElements.
503 if (mDirtyLineLoopTranslation)
504 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400505 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400506
507 if (!elementArrayBuffer)
508 {
Frank Henigman85c4b432018-09-19 23:35:00 -0400509 ANGLE_TRY(mLineLoopHelper.streamIndices(
Jamie Madillbfe31c42018-10-25 17:03:47 -0400510 contextVk, indexTypeOrNone, vertexOrIndexCount,
511 reinterpret_cast<const uint8_t *>(indices), &mCurrentElementArrayBufferHandle,
512 &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400513 }
514 else
515 {
516 // When using an element array buffer, 'indices' is an offset to the first element.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400517 intptr_t offset = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400518 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
519 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Jamie Madillbfe31c42018-10-25 17:03:47 -0400520 contextVk, elementArrayBufferVk, indexTypeOrNone, vertexOrIndexCount, offset,
521 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400522 }
523 }
524
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();
530 return angle::Result::Continue();
531 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400532
Jamie Madill18e323a2018-05-11 16:54:17 -0400533 // Note: Vertex indexes can be arbitrarily large.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400534 uint32_t clampedVertexCount = gl::clampCast<uint32_t>(vertexOrIndexCount);
Jamie Madill18e323a2018-05-11 16:54:17 -0400535
Jamie Madillc3755fc2018-04-05 08:39:13 -0400536 // Handle GL_LINE_LOOP drawArrays.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400537 size_t lastVertex = static_cast<size_t>(firstVertex + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400538 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
Jamie Madillbfe31c42018-10-25 17:03:47 -0400539 mLineLoopBufferFirstIndex != firstVertex || mLineLoopBufferLastIndex != lastVertex)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400540 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400541 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(
542 contextVk, clampedVertexCount, firstVertex, &mCurrentElementArrayBufferHandle,
543 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400544
Jamie Madillbfe31c42018-10-25 17:03:47 -0400545 mLineLoopBufferFirstIndex = firstVertex;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400546 mLineLoopBufferLastIndex = lastVertex;
547 }
548
Jamie Madill88fc6da2018-08-30 16:18:36 -0400549 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400550}
551
Jamie Madill88fc6da2018-08-30 16:18:36 -0400552angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400553 GLsizei indexCount,
554 GLenum type,
555 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400556{
Jamie Madillbfe31c42018-10-25 17:03:47 -0400557 ASSERT(type != GL_NONE);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400558
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400559 gl::Buffer *glBuffer = mState.getElementArrayBuffer();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400560
Jamie Madill88fc6da2018-08-30 16:18:36 -0400561 if (!glBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400562 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400563 ANGLE_TRY(streamIndexData(contextVk, type, indexCount, indices, &mDynamicIndexData));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400564 }
Jamie Madill88fc6da2018-08-30 16:18:36 -0400565 else
Jamie Madillc3755fc2018-04-05 08:39:13 -0400566 {
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400567 // Needed before reading buffer or we could get stale data.
568 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
569
Jamie Madillbfe31c42018-10-25 17:03:47 -0400570 ASSERT(type == GL_UNSIGNED_BYTE);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400571 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
572 // memory to a GLushort.
573 BufferVk *bufferVk = vk::GetImpl(glBuffer);
574 void *srcDataMapping = nullptr;
575 ASSERT(!glBuffer->isMapped());
576 ANGLE_TRY(bufferVk->mapImpl(contextVk, &srcDataMapping));
577 uint8_t *srcData = static_cast<uint8_t *>(srcDataMapping);
Jamie Madillbfe31c42018-10-25 17:03:47 -0400578 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400579 srcData += offsetIntoSrcData;
Jamie Madill253038d2018-08-30 16:18:35 -0400580
Jamie Madillbfe31c42018-10-25 17:03:47 -0400581 ANGLE_TRY(streamIndexData(contextVk, type,
Jamie Madill88fc6da2018-08-30 16:18:36 -0400582 static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData,
583 srcData, &mTranslatedByteIndexData));
Luc Ferron6ed167a2018-06-13 13:45:55 -0400584
Jamie Madill88fc6da2018-08-30 16:18:36 -0400585 ANGLE_TRY(bufferVk->unmapImpl(contextVk));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400586 }
587
Jamie Madill88fc6da2018-08-30 16:18:36 -0400588 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400589}
Jamie Madill5a4c9322018-07-16 11:01:58 -0400590
591void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
592 size_t attribIndex,
593 VkBuffer bufferHandle,
594 uint32_t offset)
595{
596 if (!mState.getEnabledAttributesMask().test(attribIndex))
597 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500598 mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
599 mCurrentArrayBufferOffsets[attribIndex] = offset;
600 mCurrentArrayBuffers[attribIndex] = nullptr;
601 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400602 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400603 &renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED);
Jamie Madill5a4c9322018-07-16 11:01:58 -0400604 mDirtyPackedInputs.set(attribIndex);
605 }
606}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400607} // namespace rx