blob: e032b1bf36f56abe8f51eaa6610b26f99ddba2d6 [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{
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -050026constexpr size_t kDynamicVertexDataSize = 1024 * 1024;
27constexpr size_t kDynamicIndexDataSize = 1024 * 8;
28constexpr size_t kMaxVertexFormatAlignment = 4;
29constexpr VkBufferUsageFlags kVertexBufferUsageFlags = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
30 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
31 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
32constexpr VkBufferUsageFlags kIndexBufferUsageFlags = VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
33 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
34 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
Frank Henigmane4523822018-07-19 16:10:53 -040035
36bool BindingIsAligned(const gl::VertexBinding &binding, unsigned componentSize)
37{
38 return (binding.getOffset() % componentSize == 0) && (binding.getStride() % componentSize == 0);
39}
Jamie Madilla064c272018-08-30 16:18:34 -040040
41angle::Result StreamVertexData(ContextVk *contextVk,
42 vk::DynamicBuffer *dynamicBuffer,
43 const uint8_t *sourceData,
44 size_t bytesToAllocate,
45 size_t destOffset,
46 size_t vertexCount,
47 size_t stride,
48 VertexCopyFunction vertexLoadFunction,
49 VkBuffer *bufferHandleOut,
50 VkDeviceSize *bufferOffsetOut)
51{
52 uint8_t *dst = nullptr;
53 ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, bufferHandleOut,
54 bufferOffsetOut, nullptr));
55 dst += destOffset;
56 vertexLoadFunction(sourceData, stride, vertexCount, dst);
57
58 ANGLE_TRY(dynamicBuffer->flush(contextVk));
59 return angle::Result::Continue();
60}
jchen105dc0a6f2018-09-20 14:30:45 +080061
Jamie Madillc3755fc2018-04-05 08:39:13 -040062} // anonymous namespace
Jamie Madill9e54b5a2016-05-25 12:57:39 -040063
Shahbaz Youssefi254b32c2018-11-26 11:58:03 -050064#define INIT \
65 { \
66 kVertexBufferUsageFlags, 1024 * 8, true \
Frank Henigmane4523822018-07-19 16:10:53 -040067 }
68
Luc Ferrona9ab0f32018-05-17 17:03:55 -040069VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *renderer)
Jamie Madillbd159f02017-10-09 19:39:06 -040070 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050071 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050072 mCurrentArrayBufferOffsets{},
Jamie Madill03d1a5e2018-11-12 11:34:24 -050073 mCurrentArrayBuffers{},
Frank Henigman419acc82018-06-24 19:57:31 -040074 mCurrentArrayBufferFormats{},
75 mCurrentArrayBufferStrides{},
Frank Henigmane4523822018-07-19 16:10:53 -040076 mCurrentArrayBufferConversion{{
Jamie Madillb980c562018-11-27 11:34:27 -050077 INIT,
78 INIT,
79 INIT,
80 INIT,
81 INIT,
82 INIT,
83 INIT,
84 INIT,
85 INIT,
86 INIT,
87 INIT,
88 INIT,
89 INIT,
90 INIT,
91 INIT,
Frank Henigmane4523822018-07-19 16:10:53 -040092 INIT,
93 }},
94 mCurrentArrayBufferConversionCanRelease{},
Jamie Madillc3755fc2018-04-05 08:39:13 -040095 mCurrentElementArrayBufferOffset(0),
Jamie Madill03d1a5e2018-11-12 11:34:24 -050096 mCurrentElementArrayBuffer(nullptr),
Jamie Madill77b24362018-11-05 22:39:29 -050097 mPackedInputBindings{},
98 mPackedInputAttributes{},
Shahbaz Youssefi254b32c2018-11-26 11:58:03 -050099 mDynamicVertexData(kVertexBufferUsageFlags, kDynamicVertexDataSize, true),
100 mDynamicIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
101 mTranslatedByteIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
Luc Ferrona9ab0f32018-05-17 17:03:55 -0400102 mLineLoopHelper(renderer),
Jamie Madill88fc6da2018-08-30 16:18:36 -0400103 mDirtyLineLoopTranslation(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400104{
Jamie Madillda854a22017-11-30 17:24:21 -0500105 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -0500106 mCurrentArrayBufferOffsets.fill(0);
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500107 mCurrentArrayBuffers.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -0500108
Frank Henigmane4523822018-07-19 16:10:53 -0400109 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
110 {
jchen105dc0a6f2018-09-20 14:30:45 +0800111 buffer.init(kMaxVertexFormatAlignment, renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400112 }
jchen105dc0a6f2018-09-20 14:30:45 +0800113 mDynamicVertexData.init(kMaxVertexFormatAlignment, renderer);
Luc Ferrona9ab0f32018-05-17 17:03:55 -0400114 mDynamicIndexData.init(1, renderer);
Luc Ferron6ed167a2018-06-13 13:45:55 -0400115 mTranslatedByteIndexData.init(1, renderer);
Jamie Madill0a17e482018-08-31 17:19:11 -0400116
117 // Initially consider all inputs dirty.
118 mDirtyPackedInputs.set();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400119}
120
Jamie Madillb980c562018-11-27 11:34:27 -0500121VertexArrayVk::~VertexArrayVk() {}
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500122
Jamie Madill4928b7c2017-06-20 12:57:39 -0400123void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400124{
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500125 RendererVk *renderer = vk::GetImpl(context)->getRenderer();
126
Frank Henigmane4523822018-07-19 16:10:53 -0400127 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
128 {
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500129 buffer.release(renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400130 }
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500131 mDynamicVertexData.release(renderer);
132 mDynamicIndexData.release(renderer);
133 mTranslatedByteIndexData.release(renderer);
134 mLineLoopHelper.release(renderer);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400135}
136
Jamie Madill21061022018-07-12 23:56:30 -0400137angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500138 gl::DrawElementsType indexType,
Jamie Madill253038d2018-08-30 16:18:35 -0400139 size_t indexCount,
140 const void *sourcePointer,
141 vk::DynamicBuffer *dynamicBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400142{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500143 ASSERT(!mState.getElementArrayBuffer() || indexType == gl::DrawElementsType::UnsignedByte);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400144
Jamie Madill253038d2018-08-30 16:18:35 -0400145 dynamicBuffer->releaseRetainedBuffers(contextVk->getRenderer());
Jamie Madilla064c272018-08-30 16:18:34 -0400146
Jamie Madill253038d2018-08-30 16:18:35 -0400147 const size_t amount = sizeof(GLushort) * indexCount;
148 GLubyte *dst = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400149
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500150 ANGLE_TRY(dynamicBuffer->allocate(contextVk, amount, &dst, nullptr,
Jamie Madill253038d2018-08-30 16:18:35 -0400151 &mCurrentElementArrayBufferOffset, nullptr));
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500152 mCurrentElementArrayBuffer = dynamicBuffer->getCurrentBuffer();
Jamie Madill8dc27f92018-11-29 11:45:44 -0500153 if (indexType == gl::DrawElementsType::UnsignedByte)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400154 {
155 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
156 // memory to a GLushort.
Jamie Madill253038d2018-08-30 16:18:35 -0400157 const GLubyte *in = static_cast<const GLubyte *>(sourcePointer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400158 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
Jamie Madill253038d2018-08-30 16:18:35 -0400159 for (size_t index = 0; index < indexCount; index++)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400160 {
161 expandedDst[index] = static_cast<GLushort>(in[index]);
162 }
163 }
164 else
165 {
Jamie Madill253038d2018-08-30 16:18:35 -0400166 memcpy(dst, sourcePointer, amount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400167 }
Jamie Madill253038d2018-08-30 16:18:35 -0400168 ANGLE_TRY(dynamicBuffer->flush(contextVk));
Jamie Madill21061022018-07-12 23:56:30 -0400169 return angle::Result::Continue();
Frank Henigman17448952017-01-05 15:48:26 -0500170}
171
Frank Henigmane4523822018-07-19 16:10:53 -0400172// We assume the buffer is completely full of the same kind of data and convert
173// and/or align it as we copy it to a DynamicBuffer. The assumption could be wrong
174// but the alternative of copying it piecemeal on each draw would have a lot more
175// overhead.
Jamie Madilla064c272018-08-30 16:18:34 -0400176angle::Result VertexArrayVk::convertVertexBuffer(ContextVk *contextVk,
Frank Henigmane4523822018-07-19 16:10:53 -0400177 BufferVk *srcBuffer,
178 const gl::VertexBinding &binding,
179 size_t attribIndex)
180{
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400181 // Needed before reading buffer or we could get stale data.
Jamie Madilla064c272018-08-30 16:18:34 -0400182 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400183
184 unsigned srcFormatSize = mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes;
Jamie Madilla064c272018-08-30 16:18:34 -0400185 unsigned dstFormatSize = mCurrentArrayBufferStrides[attribIndex];
186
187 mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(contextVk->getRenderer());
Frank Henigmane4523822018-07-19 16:10:53 -0400188
189 // Bytes usable for vertex data.
190 GLint64 bytes = srcBuffer->getSize() - binding.getOffset();
191 if (bytes < srcFormatSize)
192 return angle::Result::Continue();
193
194 // Count the last vertex. It may occupy less than a full stride.
195 size_t numVertices = 1;
196 bytes -= srcFormatSize;
197
198 // Count how many strides fit remaining space.
199 if (bytes > 0)
200 numVertices += static_cast<size_t>(bytes) / binding.getStride();
201
Jamie Madill77abad82018-10-25 17:03:48 -0400202 void *src = nullptr;
Jamie Madilla064c272018-08-30 16:18:34 -0400203 ANGLE_TRY(srcBuffer->mapImpl(contextVk, &src));
204 const uint8_t *srcBytes = reinterpret_cast<const uint8_t *>(src);
205 srcBytes += binding.getOffset();
jchen105dc0a6f2018-09-20 14:30:45 +0800206 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
207 kMaxVertexFormatAlignment);
Jamie Madilla064c272018-08-30 16:18:34 -0400208 ANGLE_TRY(StreamVertexData(contextVk, &mCurrentArrayBufferConversion[attribIndex], srcBytes,
209 numVertices * dstFormatSize, 0, numVertices, binding.getStride(),
210 mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
211 &mCurrentArrayBufferHandles[attribIndex],
212 &mCurrentArrayBufferOffsets[attribIndex]));
213 ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400214
215 mCurrentArrayBufferConversionCanRelease[attribIndex] = true;
Frank Henigmane4523822018-07-19 16:10:53 -0400216
217 return angle::Result::Continue();
218}
219
220void VertexArrayVk::ensureConversionReleased(RendererVk *renderer, size_t attribIndex)
221{
222 if (mCurrentArrayBufferConversionCanRelease[attribIndex])
223 {
224 mCurrentArrayBufferConversion[attribIndex].release(renderer);
225 mCurrentArrayBufferConversionCanRelease[attribIndex] = false;
226 }
227}
228
229#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
230 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
231 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
232 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500233 invalidateContext = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400234 break;
235
Frank Henigmane4523822018-07-19 16:10:53 -0400236#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
237 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
238 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
239 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500240 invalidateContext = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400241 break;
242
Frank Henigmane4523822018-07-19 16:10:53 -0400243#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
244 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
245 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
246 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madilla56467e2018-04-11 16:19:41 -0400247 break;
248
Jamie Madill6f755b22018-10-09 12:48:54 -0400249angle::Result VertexArrayVk::syncState(const gl::Context *context,
250 const gl::VertexArray::DirtyBits &dirtyBits,
251 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
252 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400253{
254 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400255
Jamie Madillbc5834c2018-11-06 11:13:50 -0500256 bool invalidateContext = false;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400257
Jamie Madill5a4c9322018-07-16 11:01:58 -0400258 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400259
260 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
261 // TODO(jmadill): Handle buffer storage changes.
262 const auto &attribs = mState.getVertexAttributes();
263 const auto &bindings = mState.getVertexBindings();
264
Jamie Madill09463932018-04-04 05:26:59 -0400265 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400266 {
Jamie Madill09463932018-04-04 05:26:59 -0400267 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500268 {
Jamie Madill09463932018-04-04 05:26:59 -0400269 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500270 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400271 gl::Buffer *bufferGL = mState.getElementArrayBuffer();
Jamie Madill09463932018-04-04 05:26:59 -0400272 if (bufferGL)
273 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500274 BufferVk *bufferVk = vk::GetImpl(bufferGL);
275 mCurrentElementArrayBuffer = &bufferVk->getBuffer();
Jamie Madill09463932018-04-04 05:26:59 -0400276 }
277 else
278 {
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500279 mCurrentElementArrayBuffer = nullptr;
Jamie Madill09463932018-04-04 05:26:59 -0400280 }
Luc Ferron387b3b32018-05-28 10:11:57 -0400281
282 mCurrentElementArrayBufferOffset = 0;
283 mLineLoopBufferFirstIndex.reset();
284 mLineLoopBufferLastIndex.reset();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400285 contextVk->setIndexBufferDirty();
Jamie Madillb8e39662018-04-04 11:41:42 -0400286 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400287 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500288 }
Jamie Madill09463932018-04-04 05:26:59 -0400289
290 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400291 mLineLoopBufferFirstIndex.reset();
292 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400293 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400294 break;
295
Jamie Madilla56467e2018-04-11 16:19:41 -0400296 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
297 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
298 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
299
Jamie Madill09463932018-04-04 05:26:59 -0400300 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400301 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400302 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400303 }
304 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400305
Jamie Madillbc5834c2018-11-06 11:13:50 -0500306 if (invalidateContext)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400307 {
Jamie Madillbc5834c2018-11-06 11:13:50 -0500308 contextVk->invalidateVertexAndIndexBuffers();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400309 }
310
Jamie Madill6f755b22018-10-09 12:48:54 -0400311 return angle::Result::Continue();
Jamie Madillbd159f02017-10-09 19:39:06 -0400312}
313
Frank Henigmane4523822018-07-19 16:10:53 -0400314angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
315 const gl::VertexAttribute &attrib,
316 const gl::VertexBinding &binding,
317 size_t attribIndex)
Jamie Madilla56467e2018-04-11 16:19:41 -0400318{
319 // Invalidate the input description for pipelines.
320 mDirtyPackedInputs.set(attribIndex);
321
Frank Henigman67c388e2018-07-19 19:16:11 -0400322 RendererVk *renderer = contextVk->getRenderer();
Frank Henigmane4523822018-07-19 16:10:53 -0400323 bool releaseConversion = true;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400324
Jamie Madilla56467e2018-04-11 16:19:41 -0400325 if (attrib.enabled)
326 {
Frank Henigman67c388e2018-07-19 19:16:11 -0400327 gl::Buffer *bufferGL = binding.getBuffer().get();
Frank Henigman419acc82018-06-24 19:57:31 -0400328 mCurrentArrayBufferFormats[attribIndex] = &renderer->getFormat(GetVertexFormatID(attrib));
Frank Henigmane4523822018-07-19 16:10:53 -0400329
Jamie Madilla56467e2018-04-11 16:19:41 -0400330 if (bufferGL)
331 {
Frank Henigmane4523822018-07-19 16:10:53 -0400332 BufferVk *bufferVk = vk::GetImpl(bufferGL);
333 unsigned componentSize =
334 mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes / attrib.size;
Frank Henigman419acc82018-06-24 19:57:31 -0400335
Frank Henigmane4523822018-07-19 16:10:53 -0400336 if (mCurrentArrayBufferFormats[attribIndex]->vertexLoadRequiresConversion ||
337 !BindingIsAligned(binding, componentSize))
338 {
Jamie Madilla064c272018-08-30 16:18:34 -0400339 mCurrentArrayBufferStrides[attribIndex] =
340 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
341
Frank Henigmane4523822018-07-19 16:10:53 -0400342 ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex));
343
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500344 mCurrentArrayBuffers[attribIndex] = nullptr;
345 releaseConversion = false;
Frank Henigmane4523822018-07-19 16:10:53 -0400346 }
347 else
348 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500349 mCurrentArrayBuffers[attribIndex] = &bufferVk->getBuffer();
Jamie Madill2d03ff42018-09-27 15:04:26 -0400350 mCurrentArrayBufferHandles[attribIndex] =
351 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill77abad82018-10-25 17:03:48 -0400352 mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
353 mCurrentArrayBufferStrides[attribIndex] = binding.getStride();
Frank Henigmane4523822018-07-19 16:10:53 -0400354 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400355 }
356 else
357 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500358 mCurrentArrayBuffers[attribIndex] = nullptr;
359 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
360 mCurrentArrayBufferOffsets[attribIndex] = 0;
Frank Henigman419acc82018-06-24 19:57:31 -0400361 mCurrentArrayBufferStrides[attribIndex] =
Frank Henigmane4523822018-07-19 16:10:53 -0400362 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
Jamie Madilla56467e2018-04-11 16:19:41 -0400363 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400364 }
365 else
366 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400367 contextVk->invalidateDefaultAttribute(attribIndex);
368
369 // These will be filled out by the ContextVk.
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500370 mCurrentArrayBuffers[attribIndex] = nullptr;
371 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
372 mCurrentArrayBufferOffsets[attribIndex] = 0;
373 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400374 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400375 &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
Jamie Madilla56467e2018-04-11 16:19:41 -0400376 }
Frank Henigmane4523822018-07-19 16:10:53 -0400377
378 if (releaseConversion)
379 ensureConversionReleased(renderer, attribIndex);
380
381 return angle::Result::Continue();
Jamie Madilla56467e2018-04-11 16:19:41 -0400382}
383
Shahbaz Youssefic30f45d2018-11-12 16:37:59 -0500384void VertexArrayVk::getPackedInputDescriptions(vk::GraphicsPipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400385{
Frank Henigman419acc82018-06-24 19:57:31 -0400386 updatePackedInputDescriptions();
Jamie Madill112a3a82018-01-23 13:04:06 -0500387 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400388}
389
Frank Henigman419acc82018-06-24 19:57:31 -0400390void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400391{
Jamie Madill112a3a82018-01-23 13:04:06 -0500392 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400393 {
394 return;
395 }
396
397 const auto &attribs = mState.getVertexAttributes();
398 const auto &bindings = mState.getVertexBindings();
399
Jamie Madill112a3a82018-01-23 13:04:06 -0500400 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400401 {
402 const auto &attrib = attribs[attribIndex];
403 const auto &binding = bindings[attrib.bindingIndex];
404 if (attrib.enabled)
405 {
Frank Henigman419acc82018-06-24 19:57:31 -0400406 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400407 }
408 else
409 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400410 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
411 bindingDesc.stride = 0;
412 bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
413
Jamie Madill77b24362018-11-05 22:39:29 -0500414 mPackedInputAttributes.formats[attribIndex] =
415 static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
416 mPackedInputAttributes.offsets[attribIndex] = 0;
Jamie Madillebf72992017-10-13 14:09:45 -0400417 }
418 }
419
Jamie Madill112a3a82018-01-23 13:04:06 -0500420 mDirtyPackedInputs.reset();
421}
422
Frank Henigman419acc82018-06-24 19:57:31 -0400423void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
Jamie Madill112a3a82018-01-23 13:04:06 -0500424 const gl::VertexBinding &binding,
425 const gl::VertexAttribute &attrib)
426{
427 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
428
Frank Henigman419acc82018-06-24 19:57:31 -0400429 bindingDesc.stride = static_cast<uint16_t>(mCurrentArrayBufferStrides[attribIndex]);
Jamie Madill112a3a82018-01-23 13:04:06 -0500430 bindingDesc.inputRate = static_cast<uint16_t>(
431 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
432
Frank Henigman419acc82018-06-24 19:57:31 -0400433 VkFormat vkFormat = mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat;
Jamie Madill112a3a82018-01-23 13:04:06 -0500434 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
Frank Henigman8c379f32018-06-21 19:55:05 -0400435 if (vkFormat == VK_FORMAT_UNDEFINED)
436 {
Frank Henigman8c379f32018-06-21 19:55:05 -0400437 UNIMPLEMENTED();
438 }
Jamie Madill112a3a82018-01-23 13:04:06 -0500439
Jamie Madill77b24362018-11-05 22:39:29 -0500440 mPackedInputAttributes.formats[attribIndex] = static_cast<uint8_t>(vkFormat);
441 mPackedInputAttributes.offsets[attribIndex] = static_cast<uint16_t>(attrib.relativeOffset);
Jamie Madillebf72992017-10-13 14:09:45 -0400442}
443
Jamie Madill88fc6da2018-08-30 16:18:36 -0400444angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400445 GLint firstVertex,
446 GLsizei vertexOrIndexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500447 gl::DrawElementsType indexTypeOrInvalid,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400448 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400449{
Jamie Madill77abad82018-10-25 17:03:48 -0400450 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400451 const gl::AttributesMask &clientAttribs = context->getStateCache().getActiveClientAttribsMask();
Jamie Madill21061022018-07-12 23:56:30 -0400452
Jamie Madill88fc6da2018-08-30 16:18:36 -0400453 ASSERT(clientAttribs.any());
Jamie Madillc1fd7372018-10-26 22:48:39 -0400454
455 GLint startVertex;
456 size_t vertexCount;
Jamie Madill8dc27f92018-11-29 11:45:44 -0500457 ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrInvalid,
458 indices, 0, &startVertex, &vertexCount));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400459
460 mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
461
462 const auto &attribs = mState.getVertexAttributes();
463 const auto &bindings = mState.getVertexBindings();
464
465 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
466 // un-interleaved, wasting space and copying time. Consider improving on that.
467 for (size_t attribIndex : clientAttribs)
468 {
469 const gl::VertexAttribute &attrib = attribs[attribIndex];
470 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
471 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
472
473 const size_t bytesToAllocate =
Jamie Madillc1fd7372018-10-26 22:48:39 -0400474 (startVertex + vertexCount) * mCurrentArrayBufferStrides[attribIndex];
475 const uint8_t *src =
476 static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400477
Jamie Madillc1fd7372018-10-26 22:48:39 -0400478 size_t destOffset = startVertex * mCurrentArrayBufferStrides[attribIndex];
jchen105dc0a6f2018-09-20 14:30:45 +0800479 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
480 kMaxVertexFormatAlignment);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400481
482 // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400483 // We allocate space for startVertex + vertexCount so indexing will work. If we
Jamie Madill88fc6da2018-08-30 16:18:36 -0400484 // don't start at zero all the indices will be off.
485 // TODO(fjhenigman): See if we can account for indices being off by adjusting the
486 // offset, thus avoiding wasted memory.
Jamie Madillc1fd7372018-10-26 22:48:39 -0400487 ANGLE_TRY(StreamVertexData(
488 contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
489 binding.getStride(), mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
490 &mCurrentArrayBufferHandles[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400491 }
492
493 return angle::Result::Continue();
494}
495
496angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400497 GLint firstVertex,
498 GLsizei vertexOrIndexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500499 gl::DrawElementsType indexTypeOrInvalid,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400500 const void *indices)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400501{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500502 if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400503 {
504 // Handle GL_LINE_LOOP drawElements.
505 if (mDirtyLineLoopTranslation)
506 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400507 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400508
509 if (!elementArrayBuffer)
510 {
Frank Henigman85c4b432018-09-19 23:35:00 -0400511 ANGLE_TRY(mLineLoopHelper.streamIndices(
Jamie Madill8dc27f92018-11-29 11:45:44 -0500512 contextVk, indexTypeOrInvalid, vertexOrIndexCount,
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500513 reinterpret_cast<const uint8_t *>(indices), &mCurrentElementArrayBuffer,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400514 &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400515 }
516 else
517 {
518 // When using an element array buffer, 'indices' is an offset to the first element.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400519 intptr_t offset = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400520 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
521 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Jamie Madill8dc27f92018-11-29 11:45:44 -0500522 contextVk, elementArrayBufferVk, indexTypeOrInvalid, vertexOrIndexCount, offset,
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500523 &mCurrentElementArrayBuffer, &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400524 }
525 }
526
527 // If we've had a drawArrays call with a line loop before, we want to make sure this is
528 // invalidated the next time drawArrays is called since we use the same index buffer for
529 // both calls.
530 mLineLoopBufferFirstIndex.reset();
531 mLineLoopBufferLastIndex.reset();
532 return angle::Result::Continue();
533 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400534
Jamie Madill18e323a2018-05-11 16:54:17 -0400535 // Note: Vertex indexes can be arbitrarily large.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400536 uint32_t clampedVertexCount = gl::clampCast<uint32_t>(vertexOrIndexCount);
Jamie Madill18e323a2018-05-11 16:54:17 -0400537
Jamie Madillc3755fc2018-04-05 08:39:13 -0400538 // Handle GL_LINE_LOOP drawArrays.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400539 size_t lastVertex = static_cast<size_t>(firstVertex + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400540 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
Jamie Madillbfe31c42018-10-25 17:03:47 -0400541 mLineLoopBufferFirstIndex != firstVertex || mLineLoopBufferLastIndex != lastVertex)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400542 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400543 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500544 contextVk, clampedVertexCount, firstVertex, &mCurrentElementArrayBuffer,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400545 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400546
Jamie Madillbfe31c42018-10-25 17:03:47 -0400547 mLineLoopBufferFirstIndex = firstVertex;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400548 mLineLoopBufferLastIndex = lastVertex;
549 }
550
Jamie Madill88fc6da2018-08-30 16:18:36 -0400551 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400552}
553
Jamie Madill88fc6da2018-08-30 16:18:36 -0400554angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400555 GLsizei indexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500556 gl::DrawElementsType type,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400557 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400558{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500559 ASSERT(type != gl::DrawElementsType::InvalidEnum);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400560
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500561 RendererVk *renderer = contextVk->getRenderer();
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400562 gl::Buffer *glBuffer = mState.getElementArrayBuffer();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400563
Jamie Madill88fc6da2018-08-30 16:18:36 -0400564 if (!glBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400565 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400566 ANGLE_TRY(streamIndexData(contextVk, type, indexCount, indices, &mDynamicIndexData));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400567 }
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500568 else if (renderer->getFormat(angle::FormatID::R16_UINT).vkSupportsStorageBuffer)
569 {
570 BufferVk *bufferVk = vk::GetImpl(glBuffer);
571
572 ASSERT(type == gl::DrawElementsType::UnsignedByte);
573
574 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
575 size_t srcDataSize = static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData;
576
577 mTranslatedByteIndexData.releaseRetainedBuffers(renderer);
578
579 ANGLE_TRY(mTranslatedByteIndexData.allocate(contextVk, sizeof(GLushort) * srcDataSize,
580 nullptr, nullptr,
581 &mCurrentElementArrayBufferOffset, nullptr));
582 mCurrentElementArrayBuffer = mTranslatedByteIndexData.getCurrentBuffer();
583
584 vk::BufferHelper *dest = mTranslatedByteIndexData.getCurrentBuffer();
585 vk::BufferHelper *src = &bufferVk->getBuffer();
586
587 ANGLE_TRY(src->initBufferView(contextVk, renderer->getFormat(angle::FormatID::R8_UINT)));
588 ANGLE_TRY(dest->initBufferView(contextVk, renderer->getFormat(angle::FormatID::R16_UINT)));
589
590 // Copy relevant section of the source into destination at allocated offset. Note that the
591 // offset returned by allocate() above is in bytes, while our allocated array is of
592 // GLushorts.
593 DispatchUtilsVk::CopyParameters params = {};
594 params.destOffset =
595 static_cast<size_t>(mCurrentElementArrayBufferOffset) / sizeof(GLushort);
596 params.srcOffset = offsetIntoSrcData;
597 params.size = srcDataSize;
598
599 // Note: this is a copy, which implicitly converts between formats. Once support for
600 // primitive restart is added, a specialized shader is likely needed to special case 0xFF ->
601 // 0xFFFF.
602 ANGLE_TRY(renderer->getDispatchUtils()->copyBuffer(contextVk, dest, src, params));
603 }
Jamie Madill88fc6da2018-08-30 16:18:36 -0400604 else
Jamie Madillc3755fc2018-04-05 08:39:13 -0400605 {
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500606 // If it's not possible to convert the buffer with compute, opt for a CPU read back for now.
607 // TODO(syoussefi): R8G8B8A8_UINT is required to have storage texel buffer support, so a
608 // specialized shader code can be made to read two ubyte indices and output them in R and B
609 // (or A and G based on endianness?) with 0 on the other channels. If specialized, we might
610 // as well support the ubyte to ushort case with correct handling of primitive restart.
611 // http://anglebug.com/3003
612
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400613 // Needed before reading buffer or we could get stale data.
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500614 ANGLE_TRY(renderer->finish(contextVk));
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400615
Jamie Madill8dc27f92018-11-29 11:45:44 -0500616 ASSERT(type == gl::DrawElementsType::UnsignedByte);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400617 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
618 // memory to a GLushort.
619 BufferVk *bufferVk = vk::GetImpl(glBuffer);
620 void *srcDataMapping = nullptr;
621 ASSERT(!glBuffer->isMapped());
622 ANGLE_TRY(bufferVk->mapImpl(contextVk, &srcDataMapping));
623 uint8_t *srcData = static_cast<uint8_t *>(srcDataMapping);
Jamie Madillbfe31c42018-10-25 17:03:47 -0400624 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400625 srcData += offsetIntoSrcData;
Jamie Madill253038d2018-08-30 16:18:35 -0400626
Jamie Madillbfe31c42018-10-25 17:03:47 -0400627 ANGLE_TRY(streamIndexData(contextVk, type,
Jamie Madill88fc6da2018-08-30 16:18:36 -0400628 static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData,
629 srcData, &mTranslatedByteIndexData));
Luc Ferron6ed167a2018-06-13 13:45:55 -0400630
Jamie Madill88fc6da2018-08-30 16:18:36 -0400631 ANGLE_TRY(bufferVk->unmapImpl(contextVk));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400632 }
633
Jamie Madill88fc6da2018-08-30 16:18:36 -0400634 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400635}
Jamie Madill5a4c9322018-07-16 11:01:58 -0400636
637void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
638 size_t attribIndex,
639 VkBuffer bufferHandle,
640 uint32_t offset)
641{
642 if (!mState.getEnabledAttributesMask().test(attribIndex))
643 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500644 mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
645 mCurrentArrayBufferOffsets[attribIndex] = offset;
646 mCurrentArrayBuffers[attribIndex] = nullptr;
647 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400648 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400649 &renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED);
Jamie Madill5a4c9322018-07-16 11:01:58 -0400650 mDirtyPackedInputs.set(attribIndex);
651 }
652}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400653} // namespace rx