blob: 91821351ca8e26f419ef380911e64a50ff4531ec [file] [log] [blame]
Jamie Madill9e54b5a2016-05-25 12:57:39 -04001//
2// Copyright 2016 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// VertexArrayVk.cpp:
7// Implements the class methods for VertexArrayVk.
8//
9
10#include "libANGLE/renderer/vulkan/VertexArrayVk.h"
11
12#include "common/debug.h"
Jamie Madillbfe31c42018-10-25 17:03:47 -040013#include "common/utilities.h"
Jamie Madillc564c072017-06-01 12:45:42 -040014#include "libANGLE/Context.h"
Jamie Madillbd159f02017-10-09 19:39:06 -040015#include "libANGLE/renderer/vulkan/BufferVk.h"
Jamie Madill1f46bc12018-02-20 16:09:43 -050016#include "libANGLE/renderer/vulkan/CommandGraph.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040017#include "libANGLE/renderer/vulkan/ContextVk.h"
Jamie Madill316c6062018-05-29 10:49:45 -040018#include "libANGLE/renderer/vulkan/FramebufferVk.h"
Jamie Madillc3755fc2018-04-05 08:39:13 -040019#include "libANGLE/renderer/vulkan/RendererVk.h"
Jamie Madill3c424b42018-01-19 12:35:09 -050020#include "libANGLE/renderer/vulkan/vk_format_utils.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040021
Jamie Madill9e54b5a2016-05-25 12:57:39 -040022namespace rx
23{
Jamie Madillc3755fc2018-04-05 08:39:13 -040024namespace
25{
Jamie Madill77abad82018-10-25 17:03:48 -040026constexpr size_t kDynamicVertexDataSize = 1024 * 1024;
27constexpr size_t kDynamicIndexDataSize = 1024 * 8;
jchen105dc0a6f2018-09-20 14:30:45 +080028constexpr size_t kMaxVertexFormatAlignment = 4;
Frank Henigmane4523822018-07-19 16:10:53 -040029
30bool BindingIsAligned(const gl::VertexBinding &binding, unsigned componentSize)
31{
32 return (binding.getOffset() % componentSize == 0) && (binding.getStride() % componentSize == 0);
33}
Jamie Madilla064c272018-08-30 16:18:34 -040034
35angle::Result StreamVertexData(ContextVk *contextVk,
36 vk::DynamicBuffer *dynamicBuffer,
37 const uint8_t *sourceData,
38 size_t bytesToAllocate,
39 size_t destOffset,
40 size_t vertexCount,
41 size_t stride,
42 VertexCopyFunction vertexLoadFunction,
43 VkBuffer *bufferHandleOut,
44 VkDeviceSize *bufferOffsetOut)
45{
46 uint8_t *dst = nullptr;
47 ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, bufferHandleOut,
48 bufferOffsetOut, nullptr));
49 dst += destOffset;
50 vertexLoadFunction(sourceData, stride, vertexCount, dst);
51
52 ANGLE_TRY(dynamicBuffer->flush(contextVk));
53 return angle::Result::Continue();
54}
jchen105dc0a6f2018-09-20 14:30:45 +080055
Jamie Madillc3755fc2018-04-05 08:39:13 -040056} // anonymous namespace
Jamie Madill9e54b5a2016-05-25 12:57:39 -040057
Frank Henigmane4523822018-07-19 16:10:53 -040058#define INIT \
59 { \
60 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 1024 * 8 \
61 }
62
Luc Ferrona9ab0f32018-05-17 17:03:55 -040063VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *renderer)
Jamie Madillbd159f02017-10-09 19:39:06 -040064 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050065 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050066 mCurrentArrayBufferOffsets{},
Jamie Madillda854a22017-11-30 17:24:21 -050067 mCurrentArrayBufferResources{},
Frank Henigman419acc82018-06-24 19:57:31 -040068 mCurrentArrayBufferFormats{},
69 mCurrentArrayBufferStrides{},
Frank Henigmane4523822018-07-19 16:10:53 -040070 mCurrentArrayBufferConversion{{
71 INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT,
72 INIT,
73 }},
74 mCurrentArrayBufferConversionCanRelease{},
Jamie Madillc3755fc2018-04-05 08:39:13 -040075 mCurrentElementArrayBufferHandle(VK_NULL_HANDLE),
76 mCurrentElementArrayBufferOffset(0),
77 mCurrentElementArrayBufferResource(nullptr),
Jamie Madill77b24362018-11-05 22:39:29 -050078 mPackedInputBindings{},
79 mPackedInputAttributes{},
Jamie Madillc3755fc2018-04-05 08:39:13 -040080 mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
81 mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Luc Ferron6ed167a2018-06-13 13:45:55 -040082 mTranslatedByteIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Luc Ferrona9ab0f32018-05-17 17:03:55 -040083 mLineLoopHelper(renderer),
Jamie Madill88fc6da2018-08-30 16:18:36 -040084 mDirtyLineLoopTranslation(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040085{
Jamie Madillda854a22017-11-30 17:24:21 -050086 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -050087 mCurrentArrayBufferOffsets.fill(0);
Jamie Madillda854a22017-11-30 17:24:21 -050088 mCurrentArrayBufferResources.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -050089
Frank Henigmane4523822018-07-19 16:10:53 -040090 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
91 {
jchen105dc0a6f2018-09-20 14:30:45 +080092 buffer.init(kMaxVertexFormatAlignment, renderer);
Frank Henigmane4523822018-07-19 16:10:53 -040093 }
jchen105dc0a6f2018-09-20 14:30:45 +080094 mDynamicVertexData.init(kMaxVertexFormatAlignment, renderer);
Luc Ferrona9ab0f32018-05-17 17:03:55 -040095 mDynamicIndexData.init(1, renderer);
Luc Ferron6ed167a2018-06-13 13:45:55 -040096 mTranslatedByteIndexData.init(1, renderer);
Jamie Madill0a17e482018-08-31 17:19:11 -040097
98 // Initially consider all inputs dirty.
99 mDirtyPackedInputs.set();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400100}
101
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500102VertexArrayVk::~VertexArrayVk()
103{
104}
105
Jamie Madill4928b7c2017-06-20 12:57:39 -0400106void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400107{
Jamie Madillc3755fc2018-04-05 08:39:13 -0400108 VkDevice device = vk::GetImpl(context)->getRenderer()->getDevice();
Frank Henigmane4523822018-07-19 16:10:53 -0400109 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
110 {
111 buffer.destroy(device);
112 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400113 mDynamicVertexData.destroy(device);
114 mDynamicIndexData.destroy(device);
Luc Ferron6ed167a2018-06-13 13:45:55 -0400115 mTranslatedByteIndexData.destroy(device);
Jamie Madill22f12fe2018-04-08 14:23:40 -0400116 mLineLoopHelper.destroy(device);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400117}
118
Jamie Madill21061022018-07-12 23:56:30 -0400119angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
Jamie Madill253038d2018-08-30 16:18:35 -0400120 GLenum indexType,
121 size_t indexCount,
122 const void *sourcePointer,
123 vk::DynamicBuffer *dynamicBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400124{
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400125 ASSERT(!mState.getElementArrayBuffer() || indexType == GL_UNSIGNED_BYTE);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400126
Jamie Madill253038d2018-08-30 16:18:35 -0400127 dynamicBuffer->releaseRetainedBuffers(contextVk->getRenderer());
Jamie Madilla064c272018-08-30 16:18:34 -0400128
Jamie Madill253038d2018-08-30 16:18:35 -0400129 const size_t amount = sizeof(GLushort) * indexCount;
130 GLubyte *dst = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400131
Jamie Madill253038d2018-08-30 16:18:35 -0400132 ANGLE_TRY(dynamicBuffer->allocate(contextVk, amount, &dst, &mCurrentElementArrayBufferHandle,
133 &mCurrentElementArrayBufferOffset, nullptr));
134 if (indexType == GL_UNSIGNED_BYTE)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400135 {
136 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
137 // memory to a GLushort.
Jamie Madill253038d2018-08-30 16:18:35 -0400138 const GLubyte *in = static_cast<const GLubyte *>(sourcePointer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400139 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
Jamie Madill253038d2018-08-30 16:18:35 -0400140 for (size_t index = 0; index < indexCount; index++)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400141 {
142 expandedDst[index] = static_cast<GLushort>(in[index]);
143 }
144 }
145 else
146 {
Jamie Madill253038d2018-08-30 16:18:35 -0400147 memcpy(dst, sourcePointer, amount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400148 }
Jamie Madill253038d2018-08-30 16:18:35 -0400149 ANGLE_TRY(dynamicBuffer->flush(contextVk));
Jamie Madill21061022018-07-12 23:56:30 -0400150 return angle::Result::Continue();
Frank Henigman17448952017-01-05 15:48:26 -0500151}
152
Frank Henigmane4523822018-07-19 16:10:53 -0400153// We assume the buffer is completely full of the same kind of data and convert
154// and/or align it as we copy it to a DynamicBuffer. The assumption could be wrong
155// but the alternative of copying it piecemeal on each draw would have a lot more
156// overhead.
Jamie Madilla064c272018-08-30 16:18:34 -0400157angle::Result VertexArrayVk::convertVertexBuffer(ContextVk *contextVk,
Frank Henigmane4523822018-07-19 16:10:53 -0400158 BufferVk *srcBuffer,
159 const gl::VertexBinding &binding,
160 size_t attribIndex)
161{
162
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400163 // Needed before reading buffer or we could get stale data.
Jamie Madilla064c272018-08-30 16:18:34 -0400164 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400165
166 unsigned srcFormatSize = mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes;
Jamie Madilla064c272018-08-30 16:18:34 -0400167 unsigned dstFormatSize = mCurrentArrayBufferStrides[attribIndex];
168
169 mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(contextVk->getRenderer());
Frank Henigmane4523822018-07-19 16:10:53 -0400170
171 // Bytes usable for vertex data.
172 GLint64 bytes = srcBuffer->getSize() - binding.getOffset();
173 if (bytes < srcFormatSize)
174 return angle::Result::Continue();
175
176 // Count the last vertex. It may occupy less than a full stride.
177 size_t numVertices = 1;
178 bytes -= srcFormatSize;
179
180 // Count how many strides fit remaining space.
181 if (bytes > 0)
182 numVertices += static_cast<size_t>(bytes) / binding.getStride();
183
Jamie Madill77abad82018-10-25 17:03:48 -0400184 void *src = nullptr;
Jamie Madilla064c272018-08-30 16:18:34 -0400185 ANGLE_TRY(srcBuffer->mapImpl(contextVk, &src));
186 const uint8_t *srcBytes = reinterpret_cast<const uint8_t *>(src);
187 srcBytes += binding.getOffset();
jchen105dc0a6f2018-09-20 14:30:45 +0800188 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
189 kMaxVertexFormatAlignment);
Jamie Madilla064c272018-08-30 16:18:34 -0400190 ANGLE_TRY(StreamVertexData(contextVk, &mCurrentArrayBufferConversion[attribIndex], srcBytes,
191 numVertices * dstFormatSize, 0, numVertices, binding.getStride(),
192 mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
193 &mCurrentArrayBufferHandles[attribIndex],
194 &mCurrentArrayBufferOffsets[attribIndex]));
195 ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400196
197 mCurrentArrayBufferConversionCanRelease[attribIndex] = true;
Frank Henigmane4523822018-07-19 16:10:53 -0400198
199 return angle::Result::Continue();
200}
201
202void VertexArrayVk::ensureConversionReleased(RendererVk *renderer, size_t attribIndex)
203{
204 if (mCurrentArrayBufferConversionCanRelease[attribIndex])
205 {
206 mCurrentArrayBufferConversion[attribIndex].release(renderer);
207 mCurrentArrayBufferConversionCanRelease[attribIndex] = false;
208 }
209}
210
211#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
212 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
213 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
214 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500215 invalidateContext = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400216 break;
217
Frank Henigmane4523822018-07-19 16:10:53 -0400218#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
219 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
220 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
221 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500222 invalidateContext = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400223 break;
224
Frank Henigmane4523822018-07-19 16:10:53 -0400225#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
226 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
227 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
228 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madilla56467e2018-04-11 16:19:41 -0400229 break;
230
Jamie Madill6f755b22018-10-09 12:48:54 -0400231angle::Result VertexArrayVk::syncState(const gl::Context *context,
232 const gl::VertexArray::DirtyBits &dirtyBits,
233 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
234 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400235{
236 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400237
Jamie Madillbc5834c2018-11-06 11:13:50 -0500238 bool invalidateContext = false;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400239
Jamie Madill5a4c9322018-07-16 11:01:58 -0400240 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400241
242 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
243 // TODO(jmadill): Handle buffer storage changes.
244 const auto &attribs = mState.getVertexAttributes();
245 const auto &bindings = mState.getVertexBindings();
246
Jamie Madill09463932018-04-04 05:26:59 -0400247 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400248 {
Jamie Madill09463932018-04-04 05:26:59 -0400249 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500250 {
Jamie Madill09463932018-04-04 05:26:59 -0400251 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500252 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400253 gl::Buffer *bufferGL = mState.getElementArrayBuffer();
Jamie Madill09463932018-04-04 05:26:59 -0400254 if (bufferGL)
255 {
Jamie Madillc3755fc2018-04-05 08:39:13 -0400256 BufferVk *bufferVk = vk::GetImpl(bufferGL);
Jamie Madill2d03ff42018-09-27 15:04:26 -0400257 mCurrentElementArrayBufferResource = &bufferVk->getBuffer();
258 mCurrentElementArrayBufferHandle =
259 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill09463932018-04-04 05:26:59 -0400260 }
261 else
262 {
263 mCurrentElementArrayBufferResource = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400264 mCurrentElementArrayBufferHandle = VK_NULL_HANDLE;
Jamie Madill09463932018-04-04 05:26:59 -0400265 }
Luc Ferron387b3b32018-05-28 10:11:57 -0400266
267 mCurrentElementArrayBufferOffset = 0;
268 mLineLoopBufferFirstIndex.reset();
269 mLineLoopBufferLastIndex.reset();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400270 contextVk->setIndexBufferDirty();
Jamie Madillb8e39662018-04-04 11:41:42 -0400271 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400272 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500273 }
Jamie Madill09463932018-04-04 05:26:59 -0400274
275 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400276 mLineLoopBufferFirstIndex.reset();
277 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400278 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400279 break;
280
Jamie Madilla56467e2018-04-11 16:19:41 -0400281 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
282 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
283 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
284
Jamie Madill09463932018-04-04 05:26:59 -0400285 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400286 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400287 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400288 }
289 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400290
Jamie Madillbc5834c2018-11-06 11:13:50 -0500291 if (invalidateContext)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400292 {
Jamie Madillbc5834c2018-11-06 11:13:50 -0500293 contextVk->invalidateVertexAndIndexBuffers();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400294 }
295
Jamie Madill6f755b22018-10-09 12:48:54 -0400296 return angle::Result::Continue();
Jamie Madillbd159f02017-10-09 19:39:06 -0400297}
298
Frank Henigmane4523822018-07-19 16:10:53 -0400299angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
300 const gl::VertexAttribute &attrib,
301 const gl::VertexBinding &binding,
302 size_t attribIndex)
Jamie Madilla56467e2018-04-11 16:19:41 -0400303{
304 // Invalidate the input description for pipelines.
305 mDirtyPackedInputs.set(attribIndex);
306
Frank Henigman67c388e2018-07-19 19:16:11 -0400307 RendererVk *renderer = contextVk->getRenderer();
Frank Henigmane4523822018-07-19 16:10:53 -0400308 bool releaseConversion = true;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400309
Jamie Madilla56467e2018-04-11 16:19:41 -0400310 if (attrib.enabled)
311 {
Frank Henigman67c388e2018-07-19 19:16:11 -0400312 gl::Buffer *bufferGL = binding.getBuffer().get();
Frank Henigman419acc82018-06-24 19:57:31 -0400313 mCurrentArrayBufferFormats[attribIndex] = &renderer->getFormat(GetVertexFormatID(attrib));
Frank Henigmane4523822018-07-19 16:10:53 -0400314
Jamie Madilla56467e2018-04-11 16:19:41 -0400315 if (bufferGL)
316 {
Frank Henigmane4523822018-07-19 16:10:53 -0400317 BufferVk *bufferVk = vk::GetImpl(bufferGL);
318 unsigned componentSize =
319 mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes / attrib.size;
Frank Henigman419acc82018-06-24 19:57:31 -0400320
Frank Henigmane4523822018-07-19 16:10:53 -0400321 if (mCurrentArrayBufferFormats[attribIndex]->vertexLoadRequiresConversion ||
322 !BindingIsAligned(binding, componentSize))
323 {
Jamie Madilla064c272018-08-30 16:18:34 -0400324 mCurrentArrayBufferStrides[attribIndex] =
325 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
326
Frank Henigmane4523822018-07-19 16:10:53 -0400327 ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex));
328
Frank Henigmane4523822018-07-19 16:10:53 -0400329 mCurrentArrayBufferResources[attribIndex] = nullptr;
330 releaseConversion = false;
331 }
332 else
333 {
Jamie Madill2d03ff42018-09-27 15:04:26 -0400334 mCurrentArrayBufferResources[attribIndex] = &bufferVk->getBuffer();
335 mCurrentArrayBufferHandles[attribIndex] =
336 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill77abad82018-10-25 17:03:48 -0400337 mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
338 mCurrentArrayBufferStrides[attribIndex] = binding.getStride();
Frank Henigmane4523822018-07-19 16:10:53 -0400339 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400340 }
341 else
342 {
343 mCurrentArrayBufferResources[attribIndex] = nullptr;
344 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
Luc Ferronfa5d84b2018-06-28 10:40:04 -0400345 mCurrentArrayBufferOffsets[attribIndex] = 0;
Frank Henigman419acc82018-06-24 19:57:31 -0400346 mCurrentArrayBufferStrides[attribIndex] =
Frank Henigmane4523822018-07-19 16:10:53 -0400347 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
Jamie Madilla56467e2018-04-11 16:19:41 -0400348 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400349 }
350 else
351 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400352 contextVk->invalidateDefaultAttribute(attribIndex);
353
354 // These will be filled out by the ContextVk.
355 mCurrentArrayBufferResources[attribIndex] = nullptr;
356 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
357 mCurrentArrayBufferOffsets[attribIndex] = 0;
358 mCurrentArrayBufferStrides[attribIndex] = 0;
359 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400360 &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
Jamie Madilla56467e2018-04-11 16:19:41 -0400361 }
Frank Henigmane4523822018-07-19 16:10:53 -0400362
363 if (releaseConversion)
364 ensureConversionReleased(renderer, attribIndex);
365
366 return angle::Result::Continue();
Jamie Madilla56467e2018-04-11 16:19:41 -0400367}
368
Frank Henigman419acc82018-06-24 19:57:31 -0400369void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400370{
Frank Henigman419acc82018-06-24 19:57:31 -0400371 updatePackedInputDescriptions();
Jamie Madill112a3a82018-01-23 13:04:06 -0500372 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400373}
374
Frank Henigman419acc82018-06-24 19:57:31 -0400375void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400376{
Jamie Madill112a3a82018-01-23 13:04:06 -0500377 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400378 {
379 return;
380 }
381
382 const auto &attribs = mState.getVertexAttributes();
383 const auto &bindings = mState.getVertexBindings();
384
Jamie Madill112a3a82018-01-23 13:04:06 -0500385 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400386 {
387 const auto &attrib = attribs[attribIndex];
388 const auto &binding = bindings[attrib.bindingIndex];
389 if (attrib.enabled)
390 {
Frank Henigman419acc82018-06-24 19:57:31 -0400391 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400392 }
393 else
394 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400395 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
396 bindingDesc.stride = 0;
397 bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
398
Jamie Madill77b24362018-11-05 22:39:29 -0500399 mPackedInputAttributes.formats[attribIndex] =
400 static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
401 mPackedInputAttributes.offsets[attribIndex] = 0;
Jamie Madillebf72992017-10-13 14:09:45 -0400402 }
403 }
404
Jamie Madill112a3a82018-01-23 13:04:06 -0500405 mDirtyPackedInputs.reset();
406}
407
Frank Henigman419acc82018-06-24 19:57:31 -0400408void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
Jamie Madill112a3a82018-01-23 13:04:06 -0500409 const gl::VertexBinding &binding,
410 const gl::VertexAttribute &attrib)
411{
412 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
413
Frank Henigman419acc82018-06-24 19:57:31 -0400414 bindingDesc.stride = static_cast<uint16_t>(mCurrentArrayBufferStrides[attribIndex]);
Jamie Madill112a3a82018-01-23 13:04:06 -0500415 bindingDesc.inputRate = static_cast<uint16_t>(
416 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
417
Frank Henigman419acc82018-06-24 19:57:31 -0400418 VkFormat vkFormat = mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat;
Jamie Madill112a3a82018-01-23 13:04:06 -0500419 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
Frank Henigman8c379f32018-06-21 19:55:05 -0400420 if (vkFormat == VK_FORMAT_UNDEFINED)
421 {
Frank Henigman8c379f32018-06-21 19:55:05 -0400422 UNIMPLEMENTED();
423 }
Jamie Madill112a3a82018-01-23 13:04:06 -0500424
Jamie Madill77b24362018-11-05 22:39:29 -0500425 mPackedInputAttributes.formats[attribIndex] = static_cast<uint8_t>(vkFormat);
426 mPackedInputAttributes.offsets[attribIndex] = static_cast<uint16_t>(attrib.relativeOffset);
Jamie Madillebf72992017-10-13 14:09:45 -0400427}
428
Jamie Madill88fc6da2018-08-30 16:18:36 -0400429angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400430 GLint firstVertex,
431 GLsizei vertexOrIndexCount,
432 GLenum indexTypeOrNone,
433 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400434{
Jamie Madill77abad82018-10-25 17:03:48 -0400435 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400436 const gl::AttributesMask &clientAttribs = context->getStateCache().getActiveClientAttribsMask();
Jamie Madill21061022018-07-12 23:56:30 -0400437
Jamie Madill88fc6da2018-08-30 16:18:36 -0400438 ASSERT(clientAttribs.any());
Jamie Madillc1fd7372018-10-26 22:48:39 -0400439
440 GLint startVertex;
441 size_t vertexCount;
Jamie Madillbfe31c42018-10-25 17:03:47 -0400442 ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrNone, indices,
443 0, &startVertex, &vertexCount));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400444
445 mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
446
447 const auto &attribs = mState.getVertexAttributes();
448 const auto &bindings = mState.getVertexBindings();
449
450 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
451 // un-interleaved, wasting space and copying time. Consider improving on that.
452 for (size_t attribIndex : clientAttribs)
453 {
454 const gl::VertexAttribute &attrib = attribs[attribIndex];
455 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
456 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
457
458 const size_t bytesToAllocate =
Jamie Madillc1fd7372018-10-26 22:48:39 -0400459 (startVertex + vertexCount) * mCurrentArrayBufferStrides[attribIndex];
460 const uint8_t *src =
461 static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400462
Jamie Madillc1fd7372018-10-26 22:48:39 -0400463 size_t destOffset = startVertex * mCurrentArrayBufferStrides[attribIndex];
jchen105dc0a6f2018-09-20 14:30:45 +0800464 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
465 kMaxVertexFormatAlignment);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400466
467 // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400468 // We allocate space for startVertex + vertexCount so indexing will work. If we
Jamie Madill88fc6da2018-08-30 16:18:36 -0400469 // don't start at zero all the indices will be off.
470 // TODO(fjhenigman): See if we can account for indices being off by adjusting the
471 // offset, thus avoiding wasted memory.
Jamie Madillc1fd7372018-10-26 22:48:39 -0400472 ANGLE_TRY(StreamVertexData(
473 contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
474 binding.getStride(), mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
475 &mCurrentArrayBufferHandles[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400476 }
477
478 return angle::Result::Continue();
479}
480
481angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400482 GLint firstVertex,
483 GLsizei vertexOrIndexCount,
484 GLenum indexTypeOrNone,
485 const void *indices)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400486{
Jamie Madillbfe31c42018-10-25 17:03:47 -0400487 if (indexTypeOrNone != GL_NONE)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400488 {
489 // Handle GL_LINE_LOOP drawElements.
490 if (mDirtyLineLoopTranslation)
491 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400492 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400493
494 if (!elementArrayBuffer)
495 {
Frank Henigman85c4b432018-09-19 23:35:00 -0400496 ANGLE_TRY(mLineLoopHelper.streamIndices(
Jamie Madillbfe31c42018-10-25 17:03:47 -0400497 contextVk, indexTypeOrNone, vertexOrIndexCount,
498 reinterpret_cast<const uint8_t *>(indices), &mCurrentElementArrayBufferHandle,
499 &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400500 }
501 else
502 {
503 // When using an element array buffer, 'indices' is an offset to the first element.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400504 intptr_t offset = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400505 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
506 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Jamie Madillbfe31c42018-10-25 17:03:47 -0400507 contextVk, elementArrayBufferVk, indexTypeOrNone, vertexOrIndexCount, offset,
508 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400509 }
510 }
511
512 // If we've had a drawArrays call with a line loop before, we want to make sure this is
513 // invalidated the next time drawArrays is called since we use the same index buffer for
514 // both calls.
515 mLineLoopBufferFirstIndex.reset();
516 mLineLoopBufferLastIndex.reset();
517 return angle::Result::Continue();
518 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400519
Jamie Madill18e323a2018-05-11 16:54:17 -0400520 // Note: Vertex indexes can be arbitrarily large.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400521 uint32_t clampedVertexCount = gl::clampCast<uint32_t>(vertexOrIndexCount);
Jamie Madill18e323a2018-05-11 16:54:17 -0400522
Jamie Madillc3755fc2018-04-05 08:39:13 -0400523 // Handle GL_LINE_LOOP drawArrays.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400524 size_t lastVertex = static_cast<size_t>(firstVertex + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400525 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
Jamie Madillbfe31c42018-10-25 17:03:47 -0400526 mLineLoopBufferFirstIndex != firstVertex || mLineLoopBufferLastIndex != lastVertex)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400527 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400528 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(
529 contextVk, clampedVertexCount, firstVertex, &mCurrentElementArrayBufferHandle,
530 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400531
Jamie Madillbfe31c42018-10-25 17:03:47 -0400532 mLineLoopBufferFirstIndex = firstVertex;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400533 mLineLoopBufferLastIndex = lastVertex;
534 }
535
Jamie Madill88fc6da2018-08-30 16:18:36 -0400536 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400537}
538
Jamie Madill88fc6da2018-08-30 16:18:36 -0400539angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400540 GLsizei indexCount,
541 GLenum type,
542 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400543{
Jamie Madillbfe31c42018-10-25 17:03:47 -0400544 ASSERT(type != GL_NONE);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400545
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400546 gl::Buffer *glBuffer = mState.getElementArrayBuffer();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400547
Jamie Madill88fc6da2018-08-30 16:18:36 -0400548 if (!glBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400549 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400550 ANGLE_TRY(streamIndexData(contextVk, type, indexCount, indices, &mDynamicIndexData));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400551 }
Jamie Madill88fc6da2018-08-30 16:18:36 -0400552 else
Jamie Madillc3755fc2018-04-05 08:39:13 -0400553 {
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400554 // Needed before reading buffer or we could get stale data.
555 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
556
Jamie Madillbfe31c42018-10-25 17:03:47 -0400557 ASSERT(type == GL_UNSIGNED_BYTE);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400558 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
559 // memory to a GLushort.
560 BufferVk *bufferVk = vk::GetImpl(glBuffer);
561 void *srcDataMapping = nullptr;
562 ASSERT(!glBuffer->isMapped());
563 ANGLE_TRY(bufferVk->mapImpl(contextVk, &srcDataMapping));
564 uint8_t *srcData = static_cast<uint8_t *>(srcDataMapping);
Jamie Madillbfe31c42018-10-25 17:03:47 -0400565 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400566 srcData += offsetIntoSrcData;
Jamie Madill253038d2018-08-30 16:18:35 -0400567
Jamie Madillbfe31c42018-10-25 17:03:47 -0400568 ANGLE_TRY(streamIndexData(contextVk, type,
Jamie Madill88fc6da2018-08-30 16:18:36 -0400569 static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData,
570 srcData, &mTranslatedByteIndexData));
Luc Ferron6ed167a2018-06-13 13:45:55 -0400571
Jamie Madill88fc6da2018-08-30 16:18:36 -0400572 ANGLE_TRY(bufferVk->unmapImpl(contextVk));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400573 }
574
Jamie Madill88fc6da2018-08-30 16:18:36 -0400575 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400576}
Jamie Madill5a4c9322018-07-16 11:01:58 -0400577
578void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
579 size_t attribIndex,
580 VkBuffer bufferHandle,
581 uint32_t offset)
582{
583 if (!mState.getEnabledAttributesMask().test(attribIndex))
584 {
585 mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
586 mCurrentArrayBufferOffsets[attribIndex] = offset;
587 mCurrentArrayBufferResources[attribIndex] = nullptr;
588 mCurrentArrayBufferStrides[attribIndex] = 0;
589 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400590 &renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED);
Jamie Madill5a4c9322018-07-16 11:01:58 -0400591 mDirtyPackedInputs.set(attribIndex);
592 }
593}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400594} // namespace rx