blob: 3bacd451cc60eaef13ac5e10c757b07bcd5ea6e0 [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 mCurrentElementArrayBufferHandle(VK_NULL_HANDLE),
94 mCurrentElementArrayBufferOffset(0),
Jamie Madill03d1a5e2018-11-12 11:34:24 -050095 mCurrentElementArrayBuffer(nullptr),
Jamie Madill77b24362018-11-05 22:39:29 -050096 mPackedInputBindings{},
97 mPackedInputAttributes{},
Shahbaz Youssefi254b32c2018-11-26 11:58:03 -050098 mDynamicVertexData(kVertexBufferUsageFlags, kDynamicVertexDataSize, true),
99 mDynamicIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
100 mTranslatedByteIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
Luc Ferrona9ab0f32018-05-17 17:03:55 -0400101 mLineLoopHelper(renderer),
Jamie Madill88fc6da2018-08-30 16:18:36 -0400102 mDirtyLineLoopTranslation(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400103{
Jamie Madillda854a22017-11-30 17:24:21 -0500104 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -0500105 mCurrentArrayBufferOffsets.fill(0);
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500106 mCurrentArrayBuffers.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -0500107
Frank Henigmane4523822018-07-19 16:10:53 -0400108 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
109 {
jchen105dc0a6f2018-09-20 14:30:45 +0800110 buffer.init(kMaxVertexFormatAlignment, renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400111 }
jchen105dc0a6f2018-09-20 14:30:45 +0800112 mDynamicVertexData.init(kMaxVertexFormatAlignment, renderer);
Luc Ferrona9ab0f32018-05-17 17:03:55 -0400113 mDynamicIndexData.init(1, renderer);
Luc Ferron6ed167a2018-06-13 13:45:55 -0400114 mTranslatedByteIndexData.init(1, renderer);
Jamie Madill0a17e482018-08-31 17:19:11 -0400115
116 // Initially consider all inputs dirty.
117 mDirtyPackedInputs.set();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400118}
119
Jamie Madillb980c562018-11-27 11:34:27 -0500120VertexArrayVk::~VertexArrayVk() {}
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500121
Jamie Madill4928b7c2017-06-20 12:57:39 -0400122void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400123{
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500124 RendererVk *renderer = vk::GetImpl(context)->getRenderer();
125
Frank Henigmane4523822018-07-19 16:10:53 -0400126 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
127 {
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500128 buffer.release(renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400129 }
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500130 mDynamicVertexData.release(renderer);
131 mDynamicIndexData.release(renderer);
132 mTranslatedByteIndexData.release(renderer);
133 mLineLoopHelper.release(renderer);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400134}
135
Jamie Madill21061022018-07-12 23:56:30 -0400136angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500137 gl::DrawElementsType indexType,
Jamie Madill253038d2018-08-30 16:18:35 -0400138 size_t indexCount,
139 const void *sourcePointer,
140 vk::DynamicBuffer *dynamicBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400141{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500142 ASSERT(!mState.getElementArrayBuffer() || indexType == gl::DrawElementsType::UnsignedByte);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400143
Jamie Madill253038d2018-08-30 16:18:35 -0400144 dynamicBuffer->releaseRetainedBuffers(contextVk->getRenderer());
Jamie Madilla064c272018-08-30 16:18:34 -0400145
Jamie Madill253038d2018-08-30 16:18:35 -0400146 const size_t amount = sizeof(GLushort) * indexCount;
147 GLubyte *dst = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400148
Jamie Madill253038d2018-08-30 16:18:35 -0400149 ANGLE_TRY(dynamicBuffer->allocate(contextVk, amount, &dst, &mCurrentElementArrayBufferHandle,
150 &mCurrentElementArrayBufferOffset, nullptr));
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 Madill2d03ff42018-09-27 15:04:26 -0400275 mCurrentElementArrayBufferHandle =
276 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill09463932018-04-04 05:26:59 -0400277 }
278 else
279 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500280 mCurrentElementArrayBuffer = nullptr;
281 mCurrentElementArrayBufferHandle = VK_NULL_HANDLE;
Jamie Madill09463932018-04-04 05:26:59 -0400282 }
Luc Ferron387b3b32018-05-28 10:11:57 -0400283
284 mCurrentElementArrayBufferOffset = 0;
285 mLineLoopBufferFirstIndex.reset();
286 mLineLoopBufferLastIndex.reset();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400287 contextVk->setIndexBufferDirty();
Jamie Madillb8e39662018-04-04 11:41:42 -0400288 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400289 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500290 }
Jamie Madill09463932018-04-04 05:26:59 -0400291
292 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400293 mLineLoopBufferFirstIndex.reset();
294 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400295 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400296 break;
297
Jamie Madilla56467e2018-04-11 16:19:41 -0400298 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
299 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
300 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
301
Jamie Madill09463932018-04-04 05:26:59 -0400302 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400303 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400304 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400305 }
306 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400307
Jamie Madillbc5834c2018-11-06 11:13:50 -0500308 if (invalidateContext)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400309 {
Jamie Madillbc5834c2018-11-06 11:13:50 -0500310 contextVk->invalidateVertexAndIndexBuffers();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400311 }
312
Jamie Madill6f755b22018-10-09 12:48:54 -0400313 return angle::Result::Continue();
Jamie Madillbd159f02017-10-09 19:39:06 -0400314}
315
Frank Henigmane4523822018-07-19 16:10:53 -0400316angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
317 const gl::VertexAttribute &attrib,
318 const gl::VertexBinding &binding,
319 size_t attribIndex)
Jamie Madilla56467e2018-04-11 16:19:41 -0400320{
321 // Invalidate the input description for pipelines.
322 mDirtyPackedInputs.set(attribIndex);
323
Frank Henigman67c388e2018-07-19 19:16:11 -0400324 RendererVk *renderer = contextVk->getRenderer();
Frank Henigmane4523822018-07-19 16:10:53 -0400325 bool releaseConversion = true;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400326
Jamie Madilla56467e2018-04-11 16:19:41 -0400327 if (attrib.enabled)
328 {
Frank Henigman67c388e2018-07-19 19:16:11 -0400329 gl::Buffer *bufferGL = binding.getBuffer().get();
Frank Henigman419acc82018-06-24 19:57:31 -0400330 mCurrentArrayBufferFormats[attribIndex] = &renderer->getFormat(GetVertexFormatID(attrib));
Frank Henigmane4523822018-07-19 16:10:53 -0400331
Jamie Madilla56467e2018-04-11 16:19:41 -0400332 if (bufferGL)
333 {
Frank Henigmane4523822018-07-19 16:10:53 -0400334 BufferVk *bufferVk = vk::GetImpl(bufferGL);
335 unsigned componentSize =
336 mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes / attrib.size;
Frank Henigman419acc82018-06-24 19:57:31 -0400337
Frank Henigmane4523822018-07-19 16:10:53 -0400338 if (mCurrentArrayBufferFormats[attribIndex]->vertexLoadRequiresConversion ||
339 !BindingIsAligned(binding, componentSize))
340 {
Jamie Madilla064c272018-08-30 16:18:34 -0400341 mCurrentArrayBufferStrides[attribIndex] =
342 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
343
Frank Henigmane4523822018-07-19 16:10:53 -0400344 ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex));
345
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500346 mCurrentArrayBuffers[attribIndex] = nullptr;
347 releaseConversion = false;
Frank Henigmane4523822018-07-19 16:10:53 -0400348 }
349 else
350 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500351 mCurrentArrayBuffers[attribIndex] = &bufferVk->getBuffer();
Jamie Madill2d03ff42018-09-27 15:04:26 -0400352 mCurrentArrayBufferHandles[attribIndex] =
353 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill77abad82018-10-25 17:03:48 -0400354 mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
355 mCurrentArrayBufferStrides[attribIndex] = binding.getStride();
Frank Henigmane4523822018-07-19 16:10:53 -0400356 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400357 }
358 else
359 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500360 mCurrentArrayBuffers[attribIndex] = nullptr;
361 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
362 mCurrentArrayBufferOffsets[attribIndex] = 0;
Frank Henigman419acc82018-06-24 19:57:31 -0400363 mCurrentArrayBufferStrides[attribIndex] =
Frank Henigmane4523822018-07-19 16:10:53 -0400364 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
Jamie Madilla56467e2018-04-11 16:19:41 -0400365 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400366 }
367 else
368 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400369 contextVk->invalidateDefaultAttribute(attribIndex);
370
371 // These will be filled out by the ContextVk.
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500372 mCurrentArrayBuffers[attribIndex] = nullptr;
373 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
374 mCurrentArrayBufferOffsets[attribIndex] = 0;
375 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400376 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400377 &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
Jamie Madilla56467e2018-04-11 16:19:41 -0400378 }
Frank Henigmane4523822018-07-19 16:10:53 -0400379
380 if (releaseConversion)
381 ensureConversionReleased(renderer, attribIndex);
382
383 return angle::Result::Continue();
Jamie Madilla56467e2018-04-11 16:19:41 -0400384}
385
Shahbaz Youssefic30f45d2018-11-12 16:37:59 -0500386void VertexArrayVk::getPackedInputDescriptions(vk::GraphicsPipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400387{
Frank Henigman419acc82018-06-24 19:57:31 -0400388 updatePackedInputDescriptions();
Jamie Madill112a3a82018-01-23 13:04:06 -0500389 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400390}
391
Frank Henigman419acc82018-06-24 19:57:31 -0400392void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400393{
Jamie Madill112a3a82018-01-23 13:04:06 -0500394 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400395 {
396 return;
397 }
398
399 const auto &attribs = mState.getVertexAttributes();
400 const auto &bindings = mState.getVertexBindings();
401
Jamie Madill112a3a82018-01-23 13:04:06 -0500402 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400403 {
404 const auto &attrib = attribs[attribIndex];
405 const auto &binding = bindings[attrib.bindingIndex];
406 if (attrib.enabled)
407 {
Frank Henigman419acc82018-06-24 19:57:31 -0400408 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400409 }
410 else
411 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400412 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
413 bindingDesc.stride = 0;
414 bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
415
Jamie Madill77b24362018-11-05 22:39:29 -0500416 mPackedInputAttributes.formats[attribIndex] =
417 static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
418 mPackedInputAttributes.offsets[attribIndex] = 0;
Jamie Madillebf72992017-10-13 14:09:45 -0400419 }
420 }
421
Jamie Madill112a3a82018-01-23 13:04:06 -0500422 mDirtyPackedInputs.reset();
423}
424
Frank Henigman419acc82018-06-24 19:57:31 -0400425void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
Jamie Madill112a3a82018-01-23 13:04:06 -0500426 const gl::VertexBinding &binding,
427 const gl::VertexAttribute &attrib)
428{
429 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
430
Frank Henigman419acc82018-06-24 19:57:31 -0400431 bindingDesc.stride = static_cast<uint16_t>(mCurrentArrayBufferStrides[attribIndex]);
Jamie Madill112a3a82018-01-23 13:04:06 -0500432 bindingDesc.inputRate = static_cast<uint16_t>(
433 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
434
Frank Henigman419acc82018-06-24 19:57:31 -0400435 VkFormat vkFormat = mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat;
Jamie Madill112a3a82018-01-23 13:04:06 -0500436 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
Frank Henigman8c379f32018-06-21 19:55:05 -0400437 if (vkFormat == VK_FORMAT_UNDEFINED)
438 {
Frank Henigman8c379f32018-06-21 19:55:05 -0400439 UNIMPLEMENTED();
440 }
Jamie Madill112a3a82018-01-23 13:04:06 -0500441
Jamie Madill77b24362018-11-05 22:39:29 -0500442 mPackedInputAttributes.formats[attribIndex] = static_cast<uint8_t>(vkFormat);
443 mPackedInputAttributes.offsets[attribIndex] = static_cast<uint16_t>(attrib.relativeOffset);
Jamie Madillebf72992017-10-13 14:09:45 -0400444}
445
Jamie Madill88fc6da2018-08-30 16:18:36 -0400446angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400447 GLint firstVertex,
448 GLsizei vertexOrIndexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500449 gl::DrawElementsType indexTypeOrInvalid,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400450 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400451{
Jamie Madill77abad82018-10-25 17:03:48 -0400452 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400453 const gl::AttributesMask &clientAttribs = context->getStateCache().getActiveClientAttribsMask();
Jamie Madill21061022018-07-12 23:56:30 -0400454
Jamie Madill88fc6da2018-08-30 16:18:36 -0400455 ASSERT(clientAttribs.any());
Jamie Madillc1fd7372018-10-26 22:48:39 -0400456
457 GLint startVertex;
458 size_t vertexCount;
Jamie Madill8dc27f92018-11-29 11:45:44 -0500459 ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrInvalid,
460 indices, 0, &startVertex, &vertexCount));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400461
462 mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
463
464 const auto &attribs = mState.getVertexAttributes();
465 const auto &bindings = mState.getVertexBindings();
466
467 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
468 // un-interleaved, wasting space and copying time. Consider improving on that.
469 for (size_t attribIndex : clientAttribs)
470 {
471 const gl::VertexAttribute &attrib = attribs[attribIndex];
472 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
473 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
474
475 const size_t bytesToAllocate =
Jamie Madillc1fd7372018-10-26 22:48:39 -0400476 (startVertex + vertexCount) * mCurrentArrayBufferStrides[attribIndex];
477 const uint8_t *src =
478 static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400479
Jamie Madillc1fd7372018-10-26 22:48:39 -0400480 size_t destOffset = startVertex * mCurrentArrayBufferStrides[attribIndex];
jchen105dc0a6f2018-09-20 14:30:45 +0800481 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
482 kMaxVertexFormatAlignment);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400483
484 // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400485 // We allocate space for startVertex + vertexCount so indexing will work. If we
Jamie Madill88fc6da2018-08-30 16:18:36 -0400486 // don't start at zero all the indices will be off.
487 // TODO(fjhenigman): See if we can account for indices being off by adjusting the
488 // offset, thus avoiding wasted memory.
Jamie Madillc1fd7372018-10-26 22:48:39 -0400489 ANGLE_TRY(StreamVertexData(
490 contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
491 binding.getStride(), mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
492 &mCurrentArrayBufferHandles[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400493 }
494
495 return angle::Result::Continue();
496}
497
498angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400499 GLint firstVertex,
500 GLsizei vertexOrIndexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500501 gl::DrawElementsType indexTypeOrInvalid,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400502 const void *indices)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400503{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500504 if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400505 {
506 // Handle GL_LINE_LOOP drawElements.
507 if (mDirtyLineLoopTranslation)
508 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400509 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400510
511 if (!elementArrayBuffer)
512 {
Frank Henigman85c4b432018-09-19 23:35:00 -0400513 ANGLE_TRY(mLineLoopHelper.streamIndices(
Jamie Madill8dc27f92018-11-29 11:45:44 -0500514 contextVk, indexTypeOrInvalid, vertexOrIndexCount,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400515 reinterpret_cast<const uint8_t *>(indices), &mCurrentElementArrayBufferHandle,
516 &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400517 }
518 else
519 {
520 // When using an element array buffer, 'indices' is an offset to the first element.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400521 intptr_t offset = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400522 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
523 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Jamie Madill8dc27f92018-11-29 11:45:44 -0500524 contextVk, elementArrayBufferVk, indexTypeOrInvalid, vertexOrIndexCount, offset,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400525 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400526 }
527 }
528
529 // If we've had a drawArrays call with a line loop before, we want to make sure this is
530 // invalidated the next time drawArrays is called since we use the same index buffer for
531 // both calls.
532 mLineLoopBufferFirstIndex.reset();
533 mLineLoopBufferLastIndex.reset();
534 return angle::Result::Continue();
535 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400536
Jamie Madill18e323a2018-05-11 16:54:17 -0400537 // Note: Vertex indexes can be arbitrarily large.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400538 uint32_t clampedVertexCount = gl::clampCast<uint32_t>(vertexOrIndexCount);
Jamie Madill18e323a2018-05-11 16:54:17 -0400539
Jamie Madillc3755fc2018-04-05 08:39:13 -0400540 // Handle GL_LINE_LOOP drawArrays.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400541 size_t lastVertex = static_cast<size_t>(firstVertex + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400542 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
Jamie Madillbfe31c42018-10-25 17:03:47 -0400543 mLineLoopBufferFirstIndex != firstVertex || mLineLoopBufferLastIndex != lastVertex)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400544 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400545 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(
546 contextVk, clampedVertexCount, firstVertex, &mCurrentElementArrayBufferHandle,
547 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400548
Jamie Madillbfe31c42018-10-25 17:03:47 -0400549 mLineLoopBufferFirstIndex = firstVertex;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400550 mLineLoopBufferLastIndex = lastVertex;
551 }
552
Jamie Madill88fc6da2018-08-30 16:18:36 -0400553 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400554}
555
Jamie Madill88fc6da2018-08-30 16:18:36 -0400556angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400557 GLsizei indexCount,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500558 gl::DrawElementsType type,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400559 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400560{
Jamie Madill8dc27f92018-11-29 11:45:44 -0500561 ASSERT(type != gl::DrawElementsType::InvalidEnum);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400562
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400563 gl::Buffer *glBuffer = mState.getElementArrayBuffer();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400564
Jamie Madill88fc6da2018-08-30 16:18:36 -0400565 if (!glBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400566 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400567 ANGLE_TRY(streamIndexData(contextVk, type, indexCount, indices, &mDynamicIndexData));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400568 }
Jamie Madill88fc6da2018-08-30 16:18:36 -0400569 else
Jamie Madillc3755fc2018-04-05 08:39:13 -0400570 {
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400571 // Needed before reading buffer or we could get stale data.
572 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
573
Jamie Madill8dc27f92018-11-29 11:45:44 -0500574 ASSERT(type == gl::DrawElementsType::UnsignedByte);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400575 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
576 // memory to a GLushort.
577 BufferVk *bufferVk = vk::GetImpl(glBuffer);
578 void *srcDataMapping = nullptr;
579 ASSERT(!glBuffer->isMapped());
580 ANGLE_TRY(bufferVk->mapImpl(contextVk, &srcDataMapping));
581 uint8_t *srcData = static_cast<uint8_t *>(srcDataMapping);
Jamie Madillbfe31c42018-10-25 17:03:47 -0400582 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400583 srcData += offsetIntoSrcData;
Jamie Madill253038d2018-08-30 16:18:35 -0400584
Jamie Madillbfe31c42018-10-25 17:03:47 -0400585 ANGLE_TRY(streamIndexData(contextVk, type,
Jamie Madill88fc6da2018-08-30 16:18:36 -0400586 static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData,
587 srcData, &mTranslatedByteIndexData));
Luc Ferron6ed167a2018-06-13 13:45:55 -0400588
Jamie Madill88fc6da2018-08-30 16:18:36 -0400589 ANGLE_TRY(bufferVk->unmapImpl(contextVk));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400590 }
591
Jamie Madill88fc6da2018-08-30 16:18:36 -0400592 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400593}
Jamie Madill5a4c9322018-07-16 11:01:58 -0400594
595void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
596 size_t attribIndex,
597 VkBuffer bufferHandle,
598 uint32_t offset)
599{
600 if (!mState.getEnabledAttributesMask().test(attribIndex))
601 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500602 mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
603 mCurrentArrayBufferOffsets[attribIndex] = offset;
604 mCurrentArrayBuffers[attribIndex] = nullptr;
605 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400606 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400607 &renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED);
Jamie Madill5a4c9322018-07-16 11:01:58 -0400608 mDirtyPackedInputs.set(attribIndex);
609 }
610}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400611} // namespace rx