blob: 2b2c61fd5183a6d7ca8f244e032d9e99b4c59614 [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;
Shahbaz Youssefi254b32c2018-11-26 11:58:03 -050029constexpr VkBufferUsageFlags kVertexBufferUsageFlags =
30 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
31constexpr VkBufferUsageFlags kIndexBufferUsageFlags =
32 VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
Frank Henigmane4523822018-07-19 16:10:53 -040033
34bool BindingIsAligned(const gl::VertexBinding &binding, unsigned componentSize)
35{
36 return (binding.getOffset() % componentSize == 0) && (binding.getStride() % componentSize == 0);
37}
Jamie Madilla064c272018-08-30 16:18:34 -040038
39angle::Result StreamVertexData(ContextVk *contextVk,
40 vk::DynamicBuffer *dynamicBuffer,
41 const uint8_t *sourceData,
42 size_t bytesToAllocate,
43 size_t destOffset,
44 size_t vertexCount,
45 size_t stride,
46 VertexCopyFunction vertexLoadFunction,
47 VkBuffer *bufferHandleOut,
48 VkDeviceSize *bufferOffsetOut)
49{
50 uint8_t *dst = nullptr;
51 ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, bufferHandleOut,
52 bufferOffsetOut, nullptr));
53 dst += destOffset;
54 vertexLoadFunction(sourceData, stride, vertexCount, dst);
55
56 ANGLE_TRY(dynamicBuffer->flush(contextVk));
57 return angle::Result::Continue();
58}
jchen105dc0a6f2018-09-20 14:30:45 +080059
Jamie Madillc3755fc2018-04-05 08:39:13 -040060} // anonymous namespace
Jamie Madill9e54b5a2016-05-25 12:57:39 -040061
Shahbaz Youssefi254b32c2018-11-26 11:58:03 -050062#define INIT \
63 { \
64 kVertexBufferUsageFlags, 1024 * 8, true \
Frank Henigmane4523822018-07-19 16:10:53 -040065 }
66
Luc Ferrona9ab0f32018-05-17 17:03:55 -040067VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *renderer)
Jamie Madillbd159f02017-10-09 19:39:06 -040068 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050069 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050070 mCurrentArrayBufferOffsets{},
Jamie Madill03d1a5e2018-11-12 11:34:24 -050071 mCurrentArrayBuffers{},
Frank Henigman419acc82018-06-24 19:57:31 -040072 mCurrentArrayBufferFormats{},
73 mCurrentArrayBufferStrides{},
Frank Henigmane4523822018-07-19 16:10:53 -040074 mCurrentArrayBufferConversion{{
Jamie Madillb980c562018-11-27 11:34:27 -050075 INIT,
76 INIT,
77 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,
Frank Henigmane4523822018-07-19 16:10:53 -040090 INIT,
91 }},
92 mCurrentArrayBufferConversionCanRelease{},
Jamie Madillc3755fc2018-04-05 08:39:13 -040093 mCurrentElementArrayBufferOffset(0),
Jamie Madill03d1a5e2018-11-12 11:34:24 -050094 mCurrentElementArrayBuffer(nullptr),
Jamie Madill77b24362018-11-05 22:39:29 -050095 mPackedInputBindings{},
96 mPackedInputAttributes{},
Shahbaz Youssefi254b32c2018-11-26 11:58:03 -050097 mDynamicVertexData(kVertexBufferUsageFlags, kDynamicVertexDataSize, true),
98 mDynamicIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
99 mTranslatedByteIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
Luc Ferrona9ab0f32018-05-17 17:03:55 -0400100 mLineLoopHelper(renderer),
Jamie Madill88fc6da2018-08-30 16:18:36 -0400101 mDirtyLineLoopTranslation(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400102{
Jamie Madillda854a22017-11-30 17:24:21 -0500103 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -0500104 mCurrentArrayBufferOffsets.fill(0);
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500105 mCurrentArrayBuffers.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -0500106
Frank Henigmane4523822018-07-19 16:10:53 -0400107 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
108 {
jchen105dc0a6f2018-09-20 14:30:45 +0800109 buffer.init(kMaxVertexFormatAlignment, renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400110 }
jchen105dc0a6f2018-09-20 14:30:45 +0800111 mDynamicVertexData.init(kMaxVertexFormatAlignment, renderer);
Luc Ferrona9ab0f32018-05-17 17:03:55 -0400112 mDynamicIndexData.init(1, renderer);
Luc Ferron6ed167a2018-06-13 13:45:55 -0400113 mTranslatedByteIndexData.init(1, renderer);
Jamie Madill0a17e482018-08-31 17:19:11 -0400114
115 // Initially consider all inputs dirty.
116 mDirtyPackedInputs.set();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400117}
118
Jamie Madillb980c562018-11-27 11:34:27 -0500119VertexArrayVk::~VertexArrayVk() {}
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500120
Jamie Madill4928b7c2017-06-20 12:57:39 -0400121void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400122{
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500123 RendererVk *renderer = vk::GetImpl(context)->getRenderer();
124
Frank Henigmane4523822018-07-19 16:10:53 -0400125 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
126 {
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500127 buffer.release(renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400128 }
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500129 mDynamicVertexData.release(renderer);
130 mDynamicIndexData.release(renderer);
131 mTranslatedByteIndexData.release(renderer);
132 mLineLoopHelper.release(renderer);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400133}
134
Jamie Madill21061022018-07-12 23:56:30 -0400135angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500136 gl::DrawElementsType indexType,
Jamie Madill253038d2018-08-30 16:18:35 -0400137 size_t indexCount,
138 const void *sourcePointer,
139 vk::DynamicBuffer *dynamicBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400140{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500141 ASSERT(!mState.getElementArrayBuffer() || indexType == gl::DrawElementsType::UnsignedByte);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400142
Jamie Madill253038d2018-08-30 16:18:35 -0400143 dynamicBuffer->releaseRetainedBuffers(contextVk->getRenderer());
Jamie Madilla064c272018-08-30 16:18:34 -0400144
Jamie Madill253038d2018-08-30 16:18:35 -0400145 const size_t amount = sizeof(GLushort) * indexCount;
146 GLubyte *dst = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400147
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500148 ANGLE_TRY(dynamicBuffer->allocate(contextVk, amount, &dst, nullptr,
Jamie Madill253038d2018-08-30 16:18:35 -0400149 &mCurrentElementArrayBufferOffset, nullptr));
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500150 mCurrentElementArrayBuffer = dynamicBuffer->getCurrentBuffer();
Jamie Madill8dc27f92018-11-29 11:45:44 -0500151 if (indexType == gl::DrawElementsType::UnsignedByte)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400152 {
153 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
154 // memory to a GLushort.
Jamie Madill253038d2018-08-30 16:18:35 -0400155 const GLubyte *in = static_cast<const GLubyte *>(sourcePointer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400156 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
Jamie Madill253038d2018-08-30 16:18:35 -0400157 for (size_t index = 0; index < indexCount; index++)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400158 {
159 expandedDst[index] = static_cast<GLushort>(in[index]);
160 }
161 }
162 else
163 {
Jamie Madill253038d2018-08-30 16:18:35 -0400164 memcpy(dst, sourcePointer, amount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400165 }
Jamie Madill253038d2018-08-30 16:18:35 -0400166 ANGLE_TRY(dynamicBuffer->flush(contextVk));
Jamie Madill21061022018-07-12 23:56:30 -0400167 return angle::Result::Continue();
Frank Henigman17448952017-01-05 15:48:26 -0500168}
169
Frank Henigmane4523822018-07-19 16:10:53 -0400170// We assume the buffer is completely full of the same kind of data and convert
171// and/or align it as we copy it to a DynamicBuffer. The assumption could be wrong
172// but the alternative of copying it piecemeal on each draw would have a lot more
173// overhead.
Jamie Madilla064c272018-08-30 16:18:34 -0400174angle::Result VertexArrayVk::convertVertexBuffer(ContextVk *contextVk,
Frank Henigmane4523822018-07-19 16:10:53 -0400175 BufferVk *srcBuffer,
176 const gl::VertexBinding &binding,
177 size_t attribIndex)
178{
179
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400180 // Needed before reading buffer or we could get stale data.
Jamie Madilla064c272018-08-30 16:18:34 -0400181 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400182
183 unsigned srcFormatSize = mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes;
Jamie Madilla064c272018-08-30 16:18:34 -0400184 unsigned dstFormatSize = mCurrentArrayBufferStrides[attribIndex];
185
186 mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(contextVk->getRenderer());
Frank Henigmane4523822018-07-19 16:10:53 -0400187
188 // Bytes usable for vertex data.
189 GLint64 bytes = srcBuffer->getSize() - binding.getOffset();
190 if (bytes < srcFormatSize)
191 return angle::Result::Continue();
192
193 // Count the last vertex. It may occupy less than a full stride.
194 size_t numVertices = 1;
195 bytes -= srcFormatSize;
196
197 // Count how many strides fit remaining space.
198 if (bytes > 0)
199 numVertices += static_cast<size_t>(bytes) / binding.getStride();
200
Jamie Madill77abad82018-10-25 17:03:48 -0400201 void *src = nullptr;
Jamie Madilla064c272018-08-30 16:18:34 -0400202 ANGLE_TRY(srcBuffer->mapImpl(contextVk, &src));
203 const uint8_t *srcBytes = reinterpret_cast<const uint8_t *>(src);
204 srcBytes += binding.getOffset();
jchen105dc0a6f2018-09-20 14:30:45 +0800205 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
206 kMaxVertexFormatAlignment);
Jamie Madilla064c272018-08-30 16:18:34 -0400207 ANGLE_TRY(StreamVertexData(contextVk, &mCurrentArrayBufferConversion[attribIndex], srcBytes,
208 numVertices * dstFormatSize, 0, numVertices, binding.getStride(),
209 mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
210 &mCurrentArrayBufferHandles[attribIndex],
211 &mCurrentArrayBufferOffsets[attribIndex]));
212 ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400213
214 mCurrentArrayBufferConversionCanRelease[attribIndex] = true;
Frank Henigmane4523822018-07-19 16:10:53 -0400215
216 return angle::Result::Continue();
217}
218
219void VertexArrayVk::ensureConversionReleased(RendererVk *renderer, size_t attribIndex)
220{
221 if (mCurrentArrayBufferConversionCanRelease[attribIndex])
222 {
223 mCurrentArrayBufferConversion[attribIndex].release(renderer);
224 mCurrentArrayBufferConversionCanRelease[attribIndex] = false;
225 }
226}
227
228#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
229 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
230 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
231 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500232 invalidateContext = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400233 break;
234
Frank Henigmane4523822018-07-19 16:10:53 -0400235#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
236 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
237 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
238 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500239 invalidateContext = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400240 break;
241
Frank Henigmane4523822018-07-19 16:10:53 -0400242#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
243 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
244 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
245 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madilla56467e2018-04-11 16:19:41 -0400246 break;
247
Jamie Madill6f755b22018-10-09 12:48:54 -0400248angle::Result VertexArrayVk::syncState(const gl::Context *context,
249 const gl::VertexArray::DirtyBits &dirtyBits,
250 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
251 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400252{
253 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400254
Jamie Madillbc5834c2018-11-06 11:13:50 -0500255 bool invalidateContext = false;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400256
Jamie Madill5a4c9322018-07-16 11:01:58 -0400257 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400258
259 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
260 // TODO(jmadill): Handle buffer storage changes.
261 const auto &attribs = mState.getVertexAttributes();
262 const auto &bindings = mState.getVertexBindings();
263
Jamie Madill09463932018-04-04 05:26:59 -0400264 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400265 {
Jamie Madill09463932018-04-04 05:26:59 -0400266 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500267 {
Jamie Madill09463932018-04-04 05:26:59 -0400268 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500269 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400270 gl::Buffer *bufferGL = mState.getElementArrayBuffer();
Jamie Madill09463932018-04-04 05:26:59 -0400271 if (bufferGL)
272 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500273 BufferVk *bufferVk = vk::GetImpl(bufferGL);
274 mCurrentElementArrayBuffer = &bufferVk->getBuffer();
Jamie Madill09463932018-04-04 05:26:59 -0400275 }
276 else
277 {
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500278 mCurrentElementArrayBuffer = nullptr;
Jamie Madill09463932018-04-04 05:26:59 -0400279 }
Luc Ferron387b3b32018-05-28 10:11:57 -0400280
281 mCurrentElementArrayBufferOffset = 0;
282 mLineLoopBufferFirstIndex.reset();
283 mLineLoopBufferLastIndex.reset();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400284 contextVk->setIndexBufferDirty();
Jamie Madillb8e39662018-04-04 11:41:42 -0400285 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400286 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500287 }
Jamie Madill09463932018-04-04 05:26:59 -0400288
289 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400290 mLineLoopBufferFirstIndex.reset();
291 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400292 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400293 break;
294
Jamie Madilla56467e2018-04-11 16:19:41 -0400295 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
296 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
297 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
298
Jamie Madill09463932018-04-04 05:26:59 -0400299 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400300 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400301 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400302 }
303 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400304
Jamie Madillbc5834c2018-11-06 11:13:50 -0500305 if (invalidateContext)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400306 {
Jamie Madillbc5834c2018-11-06 11:13:50 -0500307 contextVk->invalidateVertexAndIndexBuffers();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400308 }
309
Jamie Madill6f755b22018-10-09 12:48:54 -0400310 return angle::Result::Continue();
Jamie Madillbd159f02017-10-09 19:39:06 -0400311}
312
Frank Henigmane4523822018-07-19 16:10:53 -0400313angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
314 const gl::VertexAttribute &attrib,
315 const gl::VertexBinding &binding,
316 size_t attribIndex)
Jamie Madilla56467e2018-04-11 16:19:41 -0400317{
318 // Invalidate the input description for pipelines.
319 mDirtyPackedInputs.set(attribIndex);
320
Frank Henigman67c388e2018-07-19 19:16:11 -0400321 RendererVk *renderer = contextVk->getRenderer();
Frank Henigmane4523822018-07-19 16:10:53 -0400322 bool releaseConversion = true;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400323
Jamie Madilla56467e2018-04-11 16:19:41 -0400324 if (attrib.enabled)
325 {
Frank Henigman67c388e2018-07-19 19:16:11 -0400326 gl::Buffer *bufferGL = binding.getBuffer().get();
Frank Henigman419acc82018-06-24 19:57:31 -0400327 mCurrentArrayBufferFormats[attribIndex] = &renderer->getFormat(GetVertexFormatID(attrib));
Frank Henigmane4523822018-07-19 16:10:53 -0400328
Jamie Madilla56467e2018-04-11 16:19:41 -0400329 if (bufferGL)
330 {
Frank Henigmane4523822018-07-19 16:10:53 -0400331 BufferVk *bufferVk = vk::GetImpl(bufferGL);
332 unsigned componentSize =
333 mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes / attrib.size;
Frank Henigman419acc82018-06-24 19:57:31 -0400334
Frank Henigmane4523822018-07-19 16:10:53 -0400335 if (mCurrentArrayBufferFormats[attribIndex]->vertexLoadRequiresConversion ||
336 !BindingIsAligned(binding, componentSize))
337 {
Jamie Madilla064c272018-08-30 16:18:34 -0400338 mCurrentArrayBufferStrides[attribIndex] =
339 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
340
Frank Henigmane4523822018-07-19 16:10:53 -0400341 ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex));
342
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500343 mCurrentArrayBuffers[attribIndex] = nullptr;
344 releaseConversion = false;
Frank Henigmane4523822018-07-19 16:10:53 -0400345 }
346 else
347 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500348 mCurrentArrayBuffers[attribIndex] = &bufferVk->getBuffer();
Jamie Madill2d03ff42018-09-27 15:04:26 -0400349 mCurrentArrayBufferHandles[attribIndex] =
350 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill77abad82018-10-25 17:03:48 -0400351 mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
352 mCurrentArrayBufferStrides[attribIndex] = binding.getStride();
Frank Henigmane4523822018-07-19 16:10:53 -0400353 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400354 }
355 else
356 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500357 mCurrentArrayBuffers[attribIndex] = nullptr;
358 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
359 mCurrentArrayBufferOffsets[attribIndex] = 0;
Frank Henigman419acc82018-06-24 19:57:31 -0400360 mCurrentArrayBufferStrides[attribIndex] =
Frank Henigmane4523822018-07-19 16:10:53 -0400361 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
Jamie Madilla56467e2018-04-11 16:19:41 -0400362 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400363 }
364 else
365 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400366 contextVk->invalidateDefaultAttribute(attribIndex);
367
368 // These will be filled out by the ContextVk.
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500369 mCurrentArrayBuffers[attribIndex] = nullptr;
370 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
371 mCurrentArrayBufferOffsets[attribIndex] = 0;
372 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400373 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400374 &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
Jamie Madilla56467e2018-04-11 16:19:41 -0400375 }
Frank Henigmane4523822018-07-19 16:10:53 -0400376
377 if (releaseConversion)
378 ensureConversionReleased(renderer, attribIndex);
379
380 return angle::Result::Continue();
Jamie Madilla56467e2018-04-11 16:19:41 -0400381}
382
Shahbaz Youssefic30f45d2018-11-12 16:37:59 -0500383void VertexArrayVk::getPackedInputDescriptions(vk::GraphicsPipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400384{
Frank Henigman419acc82018-06-24 19:57:31 -0400385 updatePackedInputDescriptions();
Jamie Madill112a3a82018-01-23 13:04:06 -0500386 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400387}
388
Frank Henigman419acc82018-06-24 19:57:31 -0400389void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400390{
Jamie Madill112a3a82018-01-23 13:04:06 -0500391 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400392 {
393 return;
394 }
395
396 const auto &attribs = mState.getVertexAttributes();
397 const auto &bindings = mState.getVertexBindings();
398
Jamie Madill112a3a82018-01-23 13:04:06 -0500399 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400400 {
401 const auto &attrib = attribs[attribIndex];
402 const auto &binding = bindings[attrib.bindingIndex];
403 if (attrib.enabled)
404 {
Frank Henigman419acc82018-06-24 19:57:31 -0400405 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400406 }
407 else
408 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400409 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
410 bindingDesc.stride = 0;
411 bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
412
Jamie Madill77b24362018-11-05 22:39:29 -0500413 mPackedInputAttributes.formats[attribIndex] =
414 static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
415 mPackedInputAttributes.offsets[attribIndex] = 0;
Jamie Madillebf72992017-10-13 14:09:45 -0400416 }
417 }
418
Jamie Madill112a3a82018-01-23 13:04:06 -0500419 mDirtyPackedInputs.reset();
420}
421
Frank Henigman419acc82018-06-24 19:57:31 -0400422void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
Jamie Madill112a3a82018-01-23 13:04:06 -0500423 const gl::VertexBinding &binding,
424 const gl::VertexAttribute &attrib)
425{
426 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
427
Frank Henigman419acc82018-06-24 19:57:31 -0400428 bindingDesc.stride = static_cast<uint16_t>(mCurrentArrayBufferStrides[attribIndex]);
Jamie Madill112a3a82018-01-23 13:04:06 -0500429 bindingDesc.inputRate = static_cast<uint16_t>(
430 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
431
Frank Henigman419acc82018-06-24 19:57:31 -0400432 VkFormat vkFormat = mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat;
Jamie Madill112a3a82018-01-23 13:04:06 -0500433 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
Frank Henigman8c379f32018-06-21 19:55:05 -0400434 if (vkFormat == VK_FORMAT_UNDEFINED)
435 {
Frank Henigman8c379f32018-06-21 19:55:05 -0400436 UNIMPLEMENTED();
437 }
Jamie Madill112a3a82018-01-23 13:04:06 -0500438
Jamie Madill77b24362018-11-05 22:39:29 -0500439 mPackedInputAttributes.formats[attribIndex] = static_cast<uint8_t>(vkFormat);
440 mPackedInputAttributes.offsets[attribIndex] = static_cast<uint16_t>(attrib.relativeOffset);
Jamie Madillebf72992017-10-13 14:09:45 -0400441}
442
Jamie Madill88fc6da2018-08-30 16:18:36 -0400443angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400444 GLint firstVertex,
445 GLsizei vertexOrIndexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500446 gl::DrawElementsType indexTypeOrInvalid,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400447 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400448{
Jamie Madill77abad82018-10-25 17:03:48 -0400449 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400450 const gl::AttributesMask &clientAttribs = context->getStateCache().getActiveClientAttribsMask();
Jamie Madill21061022018-07-12 23:56:30 -0400451
Jamie Madill88fc6da2018-08-30 16:18:36 -0400452 ASSERT(clientAttribs.any());
Jamie Madillc1fd7372018-10-26 22:48:39 -0400453
454 GLint startVertex;
455 size_t vertexCount;
Jamie Madill8dc27f92018-11-29 11:45:44 -0500456 ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrInvalid,
457 indices, 0, &startVertex, &vertexCount));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400458
459 mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
460
461 const auto &attribs = mState.getVertexAttributes();
462 const auto &bindings = mState.getVertexBindings();
463
464 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
465 // un-interleaved, wasting space and copying time. Consider improving on that.
466 for (size_t attribIndex : clientAttribs)
467 {
468 const gl::VertexAttribute &attrib = attribs[attribIndex];
469 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
470 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
471
472 const size_t bytesToAllocate =
Jamie Madillc1fd7372018-10-26 22:48:39 -0400473 (startVertex + vertexCount) * mCurrentArrayBufferStrides[attribIndex];
474 const uint8_t *src =
475 static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400476
Jamie Madillc1fd7372018-10-26 22:48:39 -0400477 size_t destOffset = startVertex * mCurrentArrayBufferStrides[attribIndex];
jchen105dc0a6f2018-09-20 14:30:45 +0800478 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
479 kMaxVertexFormatAlignment);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400480
481 // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400482 // We allocate space for startVertex + vertexCount so indexing will work. If we
Jamie Madill88fc6da2018-08-30 16:18:36 -0400483 // don't start at zero all the indices will be off.
484 // TODO(fjhenigman): See if we can account for indices being off by adjusting the
485 // offset, thus avoiding wasted memory.
Jamie Madillc1fd7372018-10-26 22:48:39 -0400486 ANGLE_TRY(StreamVertexData(
487 contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
488 binding.getStride(), mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
489 &mCurrentArrayBufferHandles[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400490 }
491
492 return angle::Result::Continue();
493}
494
495angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400496 GLint firstVertex,
497 GLsizei vertexOrIndexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500498 gl::DrawElementsType indexTypeOrInvalid,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400499 const void *indices)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400500{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500501 if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400502 {
503 // Handle GL_LINE_LOOP drawElements.
504 if (mDirtyLineLoopTranslation)
505 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400506 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400507
508 if (!elementArrayBuffer)
509 {
Frank Henigman85c4b432018-09-19 23:35:00 -0400510 ANGLE_TRY(mLineLoopHelper.streamIndices(
Jamie Madill8dc27f92018-11-29 11:45:44 -0500511 contextVk, indexTypeOrInvalid, vertexOrIndexCount,
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500512 reinterpret_cast<const uint8_t *>(indices), &mCurrentElementArrayBuffer,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400513 &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400514 }
515 else
516 {
517 // When using an element array buffer, 'indices' is an offset to the first element.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400518 intptr_t offset = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400519 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
520 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Jamie Madill8dc27f92018-11-29 11:45:44 -0500521 contextVk, elementArrayBufferVk, indexTypeOrInvalid, vertexOrIndexCount, offset,
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500522 &mCurrentElementArrayBuffer, &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400523 }
524 }
525
526 // If we've had a drawArrays call with a line loop before, we want to make sure this is
527 // invalidated the next time drawArrays is called since we use the same index buffer for
528 // both calls.
529 mLineLoopBufferFirstIndex.reset();
530 mLineLoopBufferLastIndex.reset();
531 return angle::Result::Continue();
532 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400533
Jamie Madill18e323a2018-05-11 16:54:17 -0400534 // Note: Vertex indexes can be arbitrarily large.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400535 uint32_t clampedVertexCount = gl::clampCast<uint32_t>(vertexOrIndexCount);
Jamie Madill18e323a2018-05-11 16:54:17 -0400536
Jamie Madillc3755fc2018-04-05 08:39:13 -0400537 // Handle GL_LINE_LOOP drawArrays.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400538 size_t lastVertex = static_cast<size_t>(firstVertex + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400539 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
Jamie Madillbfe31c42018-10-25 17:03:47 -0400540 mLineLoopBufferFirstIndex != firstVertex || mLineLoopBufferLastIndex != lastVertex)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400541 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400542 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(
Shahbaz Youssefi4abdf742018-11-28 14:41:10 -0500543 contextVk, clampedVertexCount, firstVertex, &mCurrentElementArrayBuffer,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400544 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400545
Jamie Madillbfe31c42018-10-25 17:03:47 -0400546 mLineLoopBufferFirstIndex = firstVertex;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400547 mLineLoopBufferLastIndex = lastVertex;
548 }
549
Jamie Madill88fc6da2018-08-30 16:18:36 -0400550 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400551}
552
Jamie Madill88fc6da2018-08-30 16:18:36 -0400553angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400554 GLsizei indexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500555 gl::DrawElementsType type,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400556 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400557{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500558 ASSERT(type != gl::DrawElementsType::InvalidEnum);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400559
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400560 gl::Buffer *glBuffer = mState.getElementArrayBuffer();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400561
Jamie Madill88fc6da2018-08-30 16:18:36 -0400562 if (!glBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400563 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400564 ANGLE_TRY(streamIndexData(contextVk, type, indexCount, indices, &mDynamicIndexData));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400565 }
Jamie Madill88fc6da2018-08-30 16:18:36 -0400566 else
Jamie Madillc3755fc2018-04-05 08:39:13 -0400567 {
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400568 // Needed before reading buffer or we could get stale data.
569 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
570
Jamie Madill8dc27f92018-11-29 11:45:44 -0500571 ASSERT(type == gl::DrawElementsType::UnsignedByte);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400572 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
573 // memory to a GLushort.
574 BufferVk *bufferVk = vk::GetImpl(glBuffer);
575 void *srcDataMapping = nullptr;
576 ASSERT(!glBuffer->isMapped());
577 ANGLE_TRY(bufferVk->mapImpl(contextVk, &srcDataMapping));
578 uint8_t *srcData = static_cast<uint8_t *>(srcDataMapping);
Jamie Madillbfe31c42018-10-25 17:03:47 -0400579 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400580 srcData += offsetIntoSrcData;
Jamie Madill253038d2018-08-30 16:18:35 -0400581
Jamie Madillbfe31c42018-10-25 17:03:47 -0400582 ANGLE_TRY(streamIndexData(contextVk, type,
Jamie Madill88fc6da2018-08-30 16:18:36 -0400583 static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData,
584 srcData, &mTranslatedByteIndexData));
Luc Ferron6ed167a2018-06-13 13:45:55 -0400585
Jamie Madill88fc6da2018-08-30 16:18:36 -0400586 ANGLE_TRY(bufferVk->unmapImpl(contextVk));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400587 }
588
Jamie Madill88fc6da2018-08-30 16:18:36 -0400589 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400590}
Jamie Madill5a4c9322018-07-16 11:01:58 -0400591
592void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
593 size_t attribIndex,
594 VkBuffer bufferHandle,
595 uint32_t offset)
596{
597 if (!mState.getEnabledAttributesMask().test(attribIndex))
598 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500599 mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
600 mCurrentArrayBufferOffsets[attribIndex] = offset;
601 mCurrentArrayBuffers[attribIndex] = nullptr;
602 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400603 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400604 &renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED);
Jamie Madill5a4c9322018-07-16 11:01:58 -0400605 mDirtyPackedInputs.set(attribIndex);
606 }
607}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400608} // namespace rx