blob: 5cd018ddf8aa529731121ef39e0695254dddacce [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 Youssefi611bbaa2018-12-06 01:59:53 +010026constexpr size_t kDynamicVertexDataSize = 1024 * 1024;
27constexpr size_t kDynamicIndexDataSize = 1024 * 8;
28constexpr size_t kMaxVertexFormatAlignment = 4;
29constexpr VkBufferUsageFlags kVertexBufferUsageFlags =
30 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -050031constexpr VkBufferUsageFlags kIndexBufferUsageFlags = VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
32 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
33 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
Frank Henigmane4523822018-07-19 16:10:53 -040034
35bool BindingIsAligned(const gl::VertexBinding &binding, unsigned componentSize)
36{
37 return (binding.getOffset() % componentSize == 0) && (binding.getStride() % componentSize == 0);
38}
Jamie Madilla064c272018-08-30 16:18:34 -040039
40angle::Result StreamVertexData(ContextVk *contextVk,
41 vk::DynamicBuffer *dynamicBuffer,
42 const uint8_t *sourceData,
43 size_t bytesToAllocate,
44 size_t destOffset,
45 size_t vertexCount,
46 size_t stride,
47 VertexCopyFunction vertexLoadFunction,
Shahbaz Youssefiec063052018-12-06 01:58:06 +010048 vk::BufferHelper **bufferOut,
Jamie Madilla064c272018-08-30 16:18:34 -040049 VkDeviceSize *bufferOffsetOut)
50{
51 uint8_t *dst = nullptr;
Shahbaz Youssefiec063052018-12-06 01:58:06 +010052 ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, nullptr, bufferOffsetOut,
53 nullptr));
54 *bufferOut = dynamicBuffer->getCurrentBuffer();
Jamie Madilla064c272018-08-30 16:18:34 -040055 dst += destOffset;
56 vertexLoadFunction(sourceData, stride, vertexCount, dst);
57
58 ANGLE_TRY(dynamicBuffer->flush(contextVk));
Jamie Madill7c985f52018-11-29 18:16:17 -050059 return angle::Result::Continue;
Jamie Madilla064c272018-08-30 16:18:34 -040060}
jchen105dc0a6f2018-09-20 14:30:45 +080061
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +010062size_t GetVertexCount(BufferVk *srcBuffer, const gl::VertexBinding &binding, uint32_t srcFormatSize)
63{
64 // Bytes usable for vertex data.
65 GLint64 bytes = srcBuffer->getSize() - binding.getOffset();
66 if (bytes < srcFormatSize)
67 return 0;
68
69 // Count the last vertex. It may occupy less than a full stride.
70 size_t numVertices = 1;
71 bytes -= srcFormatSize;
72
73 // Count how many strides fit remaining space.
74 if (bytes > 0)
75 numVertices += static_cast<size_t>(bytes) / binding.getStride();
76
77 return numVertices;
78}
Jamie Madillc3755fc2018-04-05 08:39:13 -040079} // anonymous namespace
Jamie Madill9e54b5a2016-05-25 12:57:39 -040080
Shahbaz Youssefi254b32c2018-11-26 11:58:03 -050081#define INIT \
82 { \
83 kVertexBufferUsageFlags, 1024 * 8, true \
Frank Henigmane4523822018-07-19 16:10:53 -040084 }
85
Luc Ferrona9ab0f32018-05-17 17:03:55 -040086VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *renderer)
Jamie Madillbd159f02017-10-09 19:39:06 -040087 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050088 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050089 mCurrentArrayBufferOffsets{},
Jamie Madill03d1a5e2018-11-12 11:34:24 -050090 mCurrentArrayBuffers{},
Frank Henigman419acc82018-06-24 19:57:31 -040091 mCurrentArrayBufferFormats{},
92 mCurrentArrayBufferStrides{},
Frank Henigmane4523822018-07-19 16:10:53 -040093 mCurrentArrayBufferConversion{{
Jamie Madillb980c562018-11-27 11:34:27 -050094 INIT,
95 INIT,
96 INIT,
97 INIT,
98 INIT,
99 INIT,
100 INIT,
101 INIT,
102 INIT,
103 INIT,
104 INIT,
105 INIT,
106 INIT,
107 INIT,
108 INIT,
Frank Henigmane4523822018-07-19 16:10:53 -0400109 INIT,
110 }},
111 mCurrentArrayBufferConversionCanRelease{},
Jamie Madillc3755fc2018-04-05 08:39:13 -0400112 mCurrentElementArrayBufferOffset(0),
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500113 mCurrentElementArrayBuffer(nullptr),
Jamie Madill77b24362018-11-05 22:39:29 -0500114 mPackedInputBindings{},
115 mPackedInputAttributes{},
Shahbaz Youssefi254b32c2018-11-26 11:58:03 -0500116 mDynamicVertexData(kVertexBufferUsageFlags, kDynamicVertexDataSize, true),
117 mDynamicIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
118 mTranslatedByteIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
Luc Ferrona9ab0f32018-05-17 17:03:55 -0400119 mLineLoopHelper(renderer),
Jamie Madill88fc6da2018-08-30 16:18:36 -0400120 mDirtyLineLoopTranslation(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400121{
Jamie Madillda854a22017-11-30 17:24:21 -0500122 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -0500123 mCurrentArrayBufferOffsets.fill(0);
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500124 mCurrentArrayBuffers.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -0500125
Frank Henigmane4523822018-07-19 16:10:53 -0400126 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
127 {
jchen105dc0a6f2018-09-20 14:30:45 +0800128 buffer.init(kMaxVertexFormatAlignment, renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400129 }
jchen105dc0a6f2018-09-20 14:30:45 +0800130 mDynamicVertexData.init(kMaxVertexFormatAlignment, renderer);
Luc Ferrona9ab0f32018-05-17 17:03:55 -0400131 mDynamicIndexData.init(1, renderer);
Luc Ferron6ed167a2018-06-13 13:45:55 -0400132 mTranslatedByteIndexData.init(1, renderer);
Jamie Madill0a17e482018-08-31 17:19:11 -0400133
134 // Initially consider all inputs dirty.
135 mDirtyPackedInputs.set();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400136}
137
Jamie Madillb980c562018-11-27 11:34:27 -0500138VertexArrayVk::~VertexArrayVk() {}
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500139
Jamie Madill4928b7c2017-06-20 12:57:39 -0400140void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400141{
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500142 RendererVk *renderer = vk::GetImpl(context)->getRenderer();
143
Frank Henigmane4523822018-07-19 16:10:53 -0400144 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
145 {
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500146 buffer.release(renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400147 }
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500148 mDynamicVertexData.release(renderer);
149 mDynamicIndexData.release(renderer);
150 mTranslatedByteIndexData.release(renderer);
151 mLineLoopHelper.release(renderer);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400152}
153
Jamie Madill21061022018-07-12 23:56:30 -0400154angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500155 gl::DrawElementsType indexType,
Jamie Madill253038d2018-08-30 16:18:35 -0400156 size_t indexCount,
157 const void *sourcePointer,
158 vk::DynamicBuffer *dynamicBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400159{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500160 ASSERT(!mState.getElementArrayBuffer() || indexType == gl::DrawElementsType::UnsignedByte);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400161
Jamie Madill253038d2018-08-30 16:18:35 -0400162 dynamicBuffer->releaseRetainedBuffers(contextVk->getRenderer());
Jamie Madilla064c272018-08-30 16:18:34 -0400163
Jamie Madill253038d2018-08-30 16:18:35 -0400164 const size_t amount = sizeof(GLushort) * indexCount;
165 GLubyte *dst = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400166
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500167 ANGLE_TRY(dynamicBuffer->allocate(contextVk, amount, &dst, nullptr,
Jamie Madill253038d2018-08-30 16:18:35 -0400168 &mCurrentElementArrayBufferOffset, nullptr));
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500169 mCurrentElementArrayBuffer = dynamicBuffer->getCurrentBuffer();
Jamie Madill8dc27f92018-11-29 11:45:44 -0500170 if (indexType == gl::DrawElementsType::UnsignedByte)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400171 {
172 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
173 // memory to a GLushort.
Jamie Madill253038d2018-08-30 16:18:35 -0400174 const GLubyte *in = static_cast<const GLubyte *>(sourcePointer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400175 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
Jamie Madill253038d2018-08-30 16:18:35 -0400176 for (size_t index = 0; index < indexCount; index++)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400177 {
178 expandedDst[index] = static_cast<GLushort>(in[index]);
179 }
180 }
181 else
182 {
Jamie Madill253038d2018-08-30 16:18:35 -0400183 memcpy(dst, sourcePointer, amount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400184 }
Jamie Madill253038d2018-08-30 16:18:35 -0400185 ANGLE_TRY(dynamicBuffer->flush(contextVk));
Jamie Madill7c985f52018-11-29 18:16:17 -0500186 return angle::Result::Continue;
Frank Henigman17448952017-01-05 15:48:26 -0500187}
188
Frank Henigmane4523822018-07-19 16:10:53 -0400189// We assume the buffer is completely full of the same kind of data and convert
190// and/or align it as we copy it to a DynamicBuffer. The assumption could be wrong
191// but the alternative of copying it piecemeal on each draw would have a lot more
192// overhead.
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100193angle::Result VertexArrayVk::convertVertexBufferGpu(ContextVk *contextVk,
194 BufferVk *srcBuffer,
195 const gl::VertexBinding &binding,
196 size_t attribIndex)
197{
198 RendererVk *renderer = contextVk->getRenderer();
199
200 const angle::Format &srcFormat = mCurrentArrayBufferFormats[attribIndex]->angleFormat();
201 const angle::Format &destFormat = mCurrentArrayBufferFormats[attribIndex]->bufferFormat();
202
203 ASSERT(binding.getStride() % (srcFormat.pixelBytes / srcFormat.channelCount()) == 0);
204
205 unsigned srcFormatSize = srcFormat.pixelBytes;
206 unsigned destFormatSize = destFormat.pixelBytes;
207
208 size_t numVertices = GetVertexCount(srcBuffer, binding, srcFormatSize);
209 if (numVertices == 0)
210 {
211 return angle::Result::Continue;
212 }
213
214 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
215 kMaxVertexFormatAlignment);
216
217 // Allocate buffer for results
218 mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(renderer);
219 ANGLE_TRY(mCurrentArrayBufferConversion[attribIndex].allocate(
220 contextVk, numVertices * destFormatSize, nullptr, nullptr,
221 &mCurrentArrayBufferOffsets[attribIndex], nullptr));
222 mCurrentArrayBuffers[attribIndex] =
223 mCurrentArrayBufferConversion[attribIndex].getCurrentBuffer();
224
225 DispatchUtilsVk::ConvertVertexParameters params;
226 params.vertexCount = numVertices;
227 params.srcFormat = &srcFormat;
228 params.destFormat = &destFormat;
229 params.srcStride = binding.getStride();
230 params.srcOffset = binding.getOffset();
231 params.destOffset = static_cast<size_t>(mCurrentArrayBufferOffsets[attribIndex]);
232
233 ANGLE_TRY(renderer->getDispatchUtils().convertVertexBuffer(
234 contextVk, mCurrentArrayBuffers[attribIndex], &srcBuffer->getBuffer(), params));
235
236 mCurrentArrayBufferHandles[attribIndex] =
237 mCurrentArrayBuffers[attribIndex]->getBuffer().getHandle();
238 mCurrentArrayBufferConversionCanRelease[attribIndex] = true;
239
240 return angle::Result::Continue;
241}
242
243angle::Result VertexArrayVk::convertVertexBufferCpu(ContextVk *contextVk,
244 BufferVk *srcBuffer,
245 const gl::VertexBinding &binding,
246 size_t attribIndex)
Frank Henigmane4523822018-07-19 16:10:53 -0400247{
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400248 // Needed before reading buffer or we could get stale data.
Jamie Madilla064c272018-08-30 16:18:34 -0400249 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400250
251 unsigned srcFormatSize = mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes;
Jamie Madilla064c272018-08-30 16:18:34 -0400252 unsigned dstFormatSize = mCurrentArrayBufferStrides[attribIndex];
253
254 mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(contextVk->getRenderer());
Frank Henigmane4523822018-07-19 16:10:53 -0400255
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100256 size_t numVertices = GetVertexCount(srcBuffer, binding, srcFormatSize);
257 if (numVertices == 0)
258 {
Jamie Madill7c985f52018-11-29 18:16:17 -0500259 return angle::Result::Continue;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100260 }
Frank Henigmane4523822018-07-19 16:10:53 -0400261
Jamie Madill77abad82018-10-25 17:03:48 -0400262 void *src = nullptr;
Jamie Madilla064c272018-08-30 16:18:34 -0400263 ANGLE_TRY(srcBuffer->mapImpl(contextVk, &src));
264 const uint8_t *srcBytes = reinterpret_cast<const uint8_t *>(src);
265 srcBytes += binding.getOffset();
jchen105dc0a6f2018-09-20 14:30:45 +0800266 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
267 kMaxVertexFormatAlignment);
Jamie Madilla064c272018-08-30 16:18:34 -0400268 ANGLE_TRY(StreamVertexData(contextVk, &mCurrentArrayBufferConversion[attribIndex], srcBytes,
269 numVertices * dstFormatSize, 0, numVertices, binding.getStride(),
270 mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
Shahbaz Youssefiec063052018-12-06 01:58:06 +0100271 &mCurrentArrayBuffers[attribIndex],
Jamie Madilla064c272018-08-30 16:18:34 -0400272 &mCurrentArrayBufferOffsets[attribIndex]));
273 ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400274
Shahbaz Youssefiec063052018-12-06 01:58:06 +0100275 mCurrentArrayBufferHandles[attribIndex] =
276 mCurrentArrayBuffers[attribIndex]->getBuffer().getHandle();
Frank Henigmane4523822018-07-19 16:10:53 -0400277 mCurrentArrayBufferConversionCanRelease[attribIndex] = true;
Frank Henigmane4523822018-07-19 16:10:53 -0400278
Jamie Madill7c985f52018-11-29 18:16:17 -0500279 return angle::Result::Continue;
Frank Henigmane4523822018-07-19 16:10:53 -0400280}
281
282void VertexArrayVk::ensureConversionReleased(RendererVk *renderer, size_t attribIndex)
283{
284 if (mCurrentArrayBufferConversionCanRelease[attribIndex])
285 {
286 mCurrentArrayBufferConversion[attribIndex].release(renderer);
287 mCurrentArrayBufferConversionCanRelease[attribIndex] = false;
288 }
289}
290
291#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
292 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
293 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
294 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500295 invalidateContext = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400296 break;
297
Frank Henigmane4523822018-07-19 16:10:53 -0400298#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
299 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
300 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
301 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500302 invalidateContext = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400303 break;
304
Frank Henigmane4523822018-07-19 16:10:53 -0400305#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
306 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
307 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
308 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madilla56467e2018-04-11 16:19:41 -0400309 break;
310
Jamie Madill6f755b22018-10-09 12:48:54 -0400311angle::Result VertexArrayVk::syncState(const gl::Context *context,
312 const gl::VertexArray::DirtyBits &dirtyBits,
313 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
314 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400315{
316 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400317
Jamie Madillbc5834c2018-11-06 11:13:50 -0500318 bool invalidateContext = false;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400319
Jamie Madill5a4c9322018-07-16 11:01:58 -0400320 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400321
322 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
323 // TODO(jmadill): Handle buffer storage changes.
324 const auto &attribs = mState.getVertexAttributes();
325 const auto &bindings = mState.getVertexBindings();
326
Jamie Madill09463932018-04-04 05:26:59 -0400327 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400328 {
Jamie Madill09463932018-04-04 05:26:59 -0400329 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500330 {
Jamie Madill09463932018-04-04 05:26:59 -0400331 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500332 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400333 gl::Buffer *bufferGL = mState.getElementArrayBuffer();
Jamie Madill09463932018-04-04 05:26:59 -0400334 if (bufferGL)
335 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500336 BufferVk *bufferVk = vk::GetImpl(bufferGL);
337 mCurrentElementArrayBuffer = &bufferVk->getBuffer();
Jamie Madill09463932018-04-04 05:26:59 -0400338 }
339 else
340 {
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500341 mCurrentElementArrayBuffer = nullptr;
Jamie Madill09463932018-04-04 05:26:59 -0400342 }
Luc Ferron387b3b32018-05-28 10:11:57 -0400343
344 mCurrentElementArrayBufferOffset = 0;
345 mLineLoopBufferFirstIndex.reset();
346 mLineLoopBufferLastIndex.reset();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400347 contextVk->setIndexBufferDirty();
Jamie Madillb8e39662018-04-04 11:41:42 -0400348 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400349 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500350 }
Jamie Madill09463932018-04-04 05:26:59 -0400351
352 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400353 mLineLoopBufferFirstIndex.reset();
354 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400355 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400356 break;
357
Jamie Madilla56467e2018-04-11 16:19:41 -0400358 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
359 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
360 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
361
Jamie Madill09463932018-04-04 05:26:59 -0400362 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400363 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400364 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400365 }
366 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400367
Jamie Madillbc5834c2018-11-06 11:13:50 -0500368 if (invalidateContext)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400369 {
Jamie Madillbc5834c2018-11-06 11:13:50 -0500370 contextVk->invalidateVertexAndIndexBuffers();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400371 }
372
Jamie Madill7c985f52018-11-29 18:16:17 -0500373 return angle::Result::Continue;
Jamie Madillbd159f02017-10-09 19:39:06 -0400374}
375
Frank Henigmane4523822018-07-19 16:10:53 -0400376angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
377 const gl::VertexAttribute &attrib,
378 const gl::VertexBinding &binding,
379 size_t attribIndex)
Jamie Madilla56467e2018-04-11 16:19:41 -0400380{
381 // Invalidate the input description for pipelines.
382 mDirtyPackedInputs.set(attribIndex);
383
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100384 RendererVk *renderer = contextVk->getRenderer();
385 bool releaseConversion = true;
386 bool anyVertexBufferConvertedOnGpu = false;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400387
Jamie Madilla56467e2018-04-11 16:19:41 -0400388 if (attrib.enabled)
389 {
Frank Henigman67c388e2018-07-19 19:16:11 -0400390 gl::Buffer *bufferGL = binding.getBuffer().get();
Frank Henigman419acc82018-06-24 19:57:31 -0400391 mCurrentArrayBufferFormats[attribIndex] = &renderer->getFormat(GetVertexFormatID(attrib));
Frank Henigmane4523822018-07-19 16:10:53 -0400392
Jamie Madilla56467e2018-04-11 16:19:41 -0400393 if (bufferGL)
394 {
Frank Henigmane4523822018-07-19 16:10:53 -0400395 BufferVk *bufferVk = vk::GetImpl(bufferGL);
396 unsigned componentSize =
397 mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes / attrib.size;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100398 bool bindingIsAligned = BindingIsAligned(binding, componentSize);
Frank Henigman419acc82018-06-24 19:57:31 -0400399
Frank Henigmane4523822018-07-19 16:10:53 -0400400 if (mCurrentArrayBufferFormats[attribIndex]->vertexLoadRequiresConversion ||
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100401 !bindingIsAligned)
Frank Henigmane4523822018-07-19 16:10:53 -0400402 {
Jamie Madilla064c272018-08-30 16:18:34 -0400403 mCurrentArrayBufferStrides[attribIndex] =
404 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
405
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100406 if (bindingIsAligned)
407 {
408 ANGLE_TRY(convertVertexBufferGpu(contextVk, bufferVk, binding, attribIndex));
409 anyVertexBufferConvertedOnGpu = true;
410 }
411 else
412 {
413 // TODO(syoussefi): Implement unaligned vertex buffer conversions in compute.
414 // http://anglebug.com/3009
415 ANGLE_TRY(convertVertexBufferCpu(contextVk, bufferVk, binding, attribIndex));
416 }
Frank Henigmane4523822018-07-19 16:10:53 -0400417
Jamie Madill7c985f52018-11-29 18:16:17 -0500418 releaseConversion = false;
Frank Henigmane4523822018-07-19 16:10:53 -0400419 }
420 else
421 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500422 mCurrentArrayBuffers[attribIndex] = &bufferVk->getBuffer();
Jamie Madill2d03ff42018-09-27 15:04:26 -0400423 mCurrentArrayBufferHandles[attribIndex] =
424 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill77abad82018-10-25 17:03:48 -0400425 mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
426 mCurrentArrayBufferStrides[attribIndex] = binding.getStride();
Frank Henigmane4523822018-07-19 16:10:53 -0400427 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400428 }
429 else
430 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500431 mCurrentArrayBuffers[attribIndex] = nullptr;
432 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
433 mCurrentArrayBufferOffsets[attribIndex] = 0;
Frank Henigman419acc82018-06-24 19:57:31 -0400434 mCurrentArrayBufferStrides[attribIndex] =
Frank Henigmane4523822018-07-19 16:10:53 -0400435 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
Jamie Madilla56467e2018-04-11 16:19:41 -0400436 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400437 }
438 else
439 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400440 contextVk->invalidateDefaultAttribute(attribIndex);
441
442 // These will be filled out by the ContextVk.
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500443 mCurrentArrayBuffers[attribIndex] = nullptr;
444 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
445 mCurrentArrayBufferOffsets[attribIndex] = 0;
446 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400447 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400448 &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
Jamie Madilla56467e2018-04-11 16:19:41 -0400449 }
Frank Henigmane4523822018-07-19 16:10:53 -0400450
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100451 if (anyVertexBufferConvertedOnGpu && renderer->getFeatures().flushAfterVertexConversion)
452 {
453 ANGLE_TRY(renderer->flush(contextVk));
454 }
455
Frank Henigmane4523822018-07-19 16:10:53 -0400456 if (releaseConversion)
457 ensureConversionReleased(renderer, attribIndex);
458
Jamie Madill7c985f52018-11-29 18:16:17 -0500459 return angle::Result::Continue;
Jamie Madilla56467e2018-04-11 16:19:41 -0400460}
461
Shahbaz Youssefic30f45d2018-11-12 16:37:59 -0500462void VertexArrayVk::getPackedInputDescriptions(vk::GraphicsPipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400463{
Frank Henigman419acc82018-06-24 19:57:31 -0400464 updatePackedInputDescriptions();
Jamie Madill112a3a82018-01-23 13:04:06 -0500465 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400466}
467
Frank Henigman419acc82018-06-24 19:57:31 -0400468void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400469{
Jamie Madill112a3a82018-01-23 13:04:06 -0500470 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400471 {
472 return;
473 }
474
475 const auto &attribs = mState.getVertexAttributes();
476 const auto &bindings = mState.getVertexBindings();
477
Jamie Madill112a3a82018-01-23 13:04:06 -0500478 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400479 {
480 const auto &attrib = attribs[attribIndex];
481 const auto &binding = bindings[attrib.bindingIndex];
482 if (attrib.enabled)
483 {
Frank Henigman419acc82018-06-24 19:57:31 -0400484 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400485 }
486 else
487 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400488 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
489 bindingDesc.stride = 0;
490 bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
491
Jamie Madill77b24362018-11-05 22:39:29 -0500492 mPackedInputAttributes.formats[attribIndex] =
493 static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
494 mPackedInputAttributes.offsets[attribIndex] = 0;
Jamie Madillebf72992017-10-13 14:09:45 -0400495 }
496 }
497
Jamie Madill112a3a82018-01-23 13:04:06 -0500498 mDirtyPackedInputs.reset();
499}
500
Frank Henigman419acc82018-06-24 19:57:31 -0400501void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
Jamie Madill112a3a82018-01-23 13:04:06 -0500502 const gl::VertexBinding &binding,
503 const gl::VertexAttribute &attrib)
504{
505 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
506
Frank Henigman419acc82018-06-24 19:57:31 -0400507 bindingDesc.stride = static_cast<uint16_t>(mCurrentArrayBufferStrides[attribIndex]);
Jamie Madill112a3a82018-01-23 13:04:06 -0500508 bindingDesc.inputRate = static_cast<uint16_t>(
509 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
510
Frank Henigman419acc82018-06-24 19:57:31 -0400511 VkFormat vkFormat = mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat;
Jamie Madill112a3a82018-01-23 13:04:06 -0500512 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
Frank Henigman8c379f32018-06-21 19:55:05 -0400513 if (vkFormat == VK_FORMAT_UNDEFINED)
514 {
Frank Henigman8c379f32018-06-21 19:55:05 -0400515 UNIMPLEMENTED();
516 }
Jamie Madill112a3a82018-01-23 13:04:06 -0500517
Jamie Madill77b24362018-11-05 22:39:29 -0500518 mPackedInputAttributes.formats[attribIndex] = static_cast<uint8_t>(vkFormat);
519 mPackedInputAttributes.offsets[attribIndex] = static_cast<uint16_t>(attrib.relativeOffset);
Jamie Madillebf72992017-10-13 14:09:45 -0400520}
521
Jamie Madill88fc6da2018-08-30 16:18:36 -0400522angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400523 GLint firstVertex,
524 GLsizei vertexOrIndexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500525 gl::DrawElementsType indexTypeOrInvalid,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400526 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400527{
Jamie Madill77abad82018-10-25 17:03:48 -0400528 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400529 const gl::AttributesMask &clientAttribs = context->getStateCache().getActiveClientAttribsMask();
Jamie Madill21061022018-07-12 23:56:30 -0400530
Jamie Madill88fc6da2018-08-30 16:18:36 -0400531 ASSERT(clientAttribs.any());
Jamie Madillc1fd7372018-10-26 22:48:39 -0400532
533 GLint startVertex;
534 size_t vertexCount;
Jamie Madill8dc27f92018-11-29 11:45:44 -0500535 ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrInvalid,
536 indices, 0, &startVertex, &vertexCount));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400537
538 mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
539
540 const auto &attribs = mState.getVertexAttributes();
541 const auto &bindings = mState.getVertexBindings();
542
543 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
544 // un-interleaved, wasting space and copying time. Consider improving on that.
545 for (size_t attribIndex : clientAttribs)
546 {
547 const gl::VertexAttribute &attrib = attribs[attribIndex];
548 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
549 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
550
551 const size_t bytesToAllocate =
Jamie Madillc1fd7372018-10-26 22:48:39 -0400552 (startVertex + vertexCount) * mCurrentArrayBufferStrides[attribIndex];
553 const uint8_t *src =
554 static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400555
Jamie Madillc1fd7372018-10-26 22:48:39 -0400556 size_t destOffset = startVertex * mCurrentArrayBufferStrides[attribIndex];
jchen105dc0a6f2018-09-20 14:30:45 +0800557 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
558 kMaxVertexFormatAlignment);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400559
560 // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400561 // We allocate space for startVertex + vertexCount so indexing will work. If we
Jamie Madill88fc6da2018-08-30 16:18:36 -0400562 // don't start at zero all the indices will be off.
563 // TODO(fjhenigman): See if we can account for indices being off by adjusting the
564 // offset, thus avoiding wasted memory.
Jamie Madillc1fd7372018-10-26 22:48:39 -0400565 ANGLE_TRY(StreamVertexData(
566 contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
567 binding.getStride(), mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
Shahbaz Youssefiec063052018-12-06 01:58:06 +0100568 &mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
569 mCurrentArrayBufferHandles[attribIndex] =
570 mCurrentArrayBuffers[attribIndex]->getBuffer().getHandle();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400571 }
572
Jamie Madill7c985f52018-11-29 18:16:17 -0500573 return angle::Result::Continue;
Jamie Madill88fc6da2018-08-30 16:18:36 -0400574}
575
576angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400577 GLint firstVertex,
578 GLsizei vertexOrIndexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500579 gl::DrawElementsType indexTypeOrInvalid,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400580 const void *indices)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400581{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500582 if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400583 {
584 // Handle GL_LINE_LOOP drawElements.
585 if (mDirtyLineLoopTranslation)
586 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400587 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400588
589 if (!elementArrayBuffer)
590 {
Frank Henigman85c4b432018-09-19 23:35:00 -0400591 ANGLE_TRY(mLineLoopHelper.streamIndices(
Jamie Madill8dc27f92018-11-29 11:45:44 -0500592 contextVk, indexTypeOrInvalid, vertexOrIndexCount,
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500593 reinterpret_cast<const uint8_t *>(indices), &mCurrentElementArrayBuffer,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400594 &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400595 }
596 else
597 {
598 // When using an element array buffer, 'indices' is an offset to the first element.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400599 intptr_t offset = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400600 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
601 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Jamie Madill8dc27f92018-11-29 11:45:44 -0500602 contextVk, elementArrayBufferVk, indexTypeOrInvalid, vertexOrIndexCount, offset,
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500603 &mCurrentElementArrayBuffer, &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400604 }
605 }
606
607 // If we've had a drawArrays call with a line loop before, we want to make sure this is
608 // invalidated the next time drawArrays is called since we use the same index buffer for
609 // both calls.
610 mLineLoopBufferFirstIndex.reset();
611 mLineLoopBufferLastIndex.reset();
Jamie Madill7c985f52018-11-29 18:16:17 -0500612 return angle::Result::Continue;
Jamie Madill88fc6da2018-08-30 16:18:36 -0400613 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400614
Jamie Madill18e323a2018-05-11 16:54:17 -0400615 // Note: Vertex indexes can be arbitrarily large.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400616 uint32_t clampedVertexCount = gl::clampCast<uint32_t>(vertexOrIndexCount);
Jamie Madill18e323a2018-05-11 16:54:17 -0400617
Jamie Madillc3755fc2018-04-05 08:39:13 -0400618 // Handle GL_LINE_LOOP drawArrays.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400619 size_t lastVertex = static_cast<size_t>(firstVertex + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400620 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
Jamie Madillbfe31c42018-10-25 17:03:47 -0400621 mLineLoopBufferFirstIndex != firstVertex || mLineLoopBufferLastIndex != lastVertex)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400622 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400623 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500624 contextVk, clampedVertexCount, firstVertex, &mCurrentElementArrayBuffer,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400625 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400626
Jamie Madillbfe31c42018-10-25 17:03:47 -0400627 mLineLoopBufferFirstIndex = firstVertex;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400628 mLineLoopBufferLastIndex = lastVertex;
629 }
630
Jamie Madill7c985f52018-11-29 18:16:17 -0500631 return angle::Result::Continue;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400632}
633
Jamie Madill88fc6da2018-08-30 16:18:36 -0400634angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400635 GLsizei indexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500636 gl::DrawElementsType type,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400637 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400638{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500639 ASSERT(type != gl::DrawElementsType::InvalidEnum);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400640
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500641 RendererVk *renderer = contextVk->getRenderer();
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400642 gl::Buffer *glBuffer = mState.getElementArrayBuffer();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400643
Jamie Madill88fc6da2018-08-30 16:18:36 -0400644 if (!glBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400645 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400646 ANGLE_TRY(streamIndexData(contextVk, type, indexCount, indices, &mDynamicIndexData));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400647 }
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500648 else if (renderer->getFormat(angle::FormatID::R16_UINT).vkSupportsStorageBuffer)
649 {
650 BufferVk *bufferVk = vk::GetImpl(glBuffer);
651
652 ASSERT(type == gl::DrawElementsType::UnsignedByte);
653
654 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
655 size_t srcDataSize = static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData;
656
657 mTranslatedByteIndexData.releaseRetainedBuffers(renderer);
658
659 ANGLE_TRY(mTranslatedByteIndexData.allocate(contextVk, sizeof(GLushort) * srcDataSize,
660 nullptr, nullptr,
661 &mCurrentElementArrayBufferOffset, nullptr));
662 mCurrentElementArrayBuffer = mTranslatedByteIndexData.getCurrentBuffer();
663
664 vk::BufferHelper *dest = mTranslatedByteIndexData.getCurrentBuffer();
665 vk::BufferHelper *src = &bufferVk->getBuffer();
666
667 ANGLE_TRY(src->initBufferView(contextVk, renderer->getFormat(angle::FormatID::R8_UINT)));
668 ANGLE_TRY(dest->initBufferView(contextVk, renderer->getFormat(angle::FormatID::R16_UINT)));
669
670 // Copy relevant section of the source into destination at allocated offset. Note that the
671 // offset returned by allocate() above is in bytes, while our allocated array is of
672 // GLushorts.
673 DispatchUtilsVk::CopyParameters params = {};
674 params.destOffset =
675 static_cast<size_t>(mCurrentElementArrayBufferOffset) / sizeof(GLushort);
676 params.srcOffset = offsetIntoSrcData;
677 params.size = srcDataSize;
678
679 // Note: this is a copy, which implicitly converts between formats. Once support for
680 // primitive restart is added, a specialized shader is likely needed to special case 0xFF ->
681 // 0xFFFF.
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100682 ANGLE_TRY(renderer->getDispatchUtils().copyBuffer(contextVk, dest, src, params));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500683 }
Jamie Madill88fc6da2018-08-30 16:18:36 -0400684 else
Jamie Madillc3755fc2018-04-05 08:39:13 -0400685 {
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500686 // If it's not possible to convert the buffer with compute, opt for a CPU read back for now.
687 // TODO(syoussefi): R8G8B8A8_UINT is required to have storage texel buffer support, so a
688 // specialized shader code can be made to read two ubyte indices and output them in R and B
689 // (or A and G based on endianness?) with 0 on the other channels. If specialized, we might
690 // as well support the ubyte to ushort case with correct handling of primitive restart.
691 // http://anglebug.com/3003
692
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400693 // Needed before reading buffer or we could get stale data.
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500694 ANGLE_TRY(renderer->finish(contextVk));
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400695
Jamie Madill8dc27f92018-11-29 11:45:44 -0500696 ASSERT(type == gl::DrawElementsType::UnsignedByte);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400697 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
698 // memory to a GLushort.
699 BufferVk *bufferVk = vk::GetImpl(glBuffer);
700 void *srcDataMapping = nullptr;
701 ASSERT(!glBuffer->isMapped());
702 ANGLE_TRY(bufferVk->mapImpl(contextVk, &srcDataMapping));
703 uint8_t *srcData = static_cast<uint8_t *>(srcDataMapping);
Jamie Madillbfe31c42018-10-25 17:03:47 -0400704 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400705 srcData += offsetIntoSrcData;
Jamie Madill253038d2018-08-30 16:18:35 -0400706
Jamie Madillbfe31c42018-10-25 17:03:47 -0400707 ANGLE_TRY(streamIndexData(contextVk, type,
Jamie Madill88fc6da2018-08-30 16:18:36 -0400708 static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData,
709 srcData, &mTranslatedByteIndexData));
Luc Ferron6ed167a2018-06-13 13:45:55 -0400710
Jamie Madill88fc6da2018-08-30 16:18:36 -0400711 ANGLE_TRY(bufferVk->unmapImpl(contextVk));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400712 }
713
Jamie Madill7c985f52018-11-29 18:16:17 -0500714 return angle::Result::Continue;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400715}
Jamie Madill5a4c9322018-07-16 11:01:58 -0400716
717void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
718 size_t attribIndex,
719 VkBuffer bufferHandle,
720 uint32_t offset)
721{
722 if (!mState.getEnabledAttributesMask().test(attribIndex))
723 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500724 mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
725 mCurrentArrayBufferOffsets[attribIndex] = offset;
726 mCurrentArrayBuffers[attribIndex] = nullptr;
727 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400728 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400729 &renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED);
Jamie Madill5a4c9322018-07-16 11:01:58 -0400730 mDirtyPackedInputs.set(attribIndex);
731 }
732}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400733} // namespace rx