blob: 94550351f8295d20e1e81f7aa146b003e36766a4 [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"
13
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{
26constexpr 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),
78 mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
79 mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Luc Ferron6ed167a2018-06-13 13:45:55 -040080 mTranslatedByteIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Luc Ferrona9ab0f32018-05-17 17:03:55 -040081 mLineLoopHelper(renderer),
Jamie Madill88fc6da2018-08-30 16:18:36 -040082 mDirtyLineLoopTranslation(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040083{
Jamie Madillda854a22017-11-30 17:24:21 -050084 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -050085 mCurrentArrayBufferOffsets.fill(0);
Jamie Madillda854a22017-11-30 17:24:21 -050086 mCurrentArrayBufferResources.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -050087
88 mPackedInputBindings.fill({0, 0});
89 mPackedInputAttributes.fill({0, 0, 0});
Jamie Madillc3755fc2018-04-05 08:39:13 -040090
Frank Henigmane4523822018-07-19 16:10:53 -040091 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
92 {
jchen105dc0a6f2018-09-20 14:30:45 +080093 buffer.init(kMaxVertexFormatAlignment, renderer);
Frank Henigmane4523822018-07-19 16:10:53 -040094 }
jchen105dc0a6f2018-09-20 14:30:45 +080095 mDynamicVertexData.init(kMaxVertexFormatAlignment, renderer);
Luc Ferrona9ab0f32018-05-17 17:03:55 -040096 mDynamicIndexData.init(1, renderer);
Luc Ferron6ed167a2018-06-13 13:45:55 -040097 mTranslatedByteIndexData.init(1, renderer);
Jamie Madill0a17e482018-08-31 17:19:11 -040098
99 // Initially consider all inputs dirty.
100 mDirtyPackedInputs.set();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400101}
102
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500103VertexArrayVk::~VertexArrayVk()
104{
105}
106
Jamie Madill4928b7c2017-06-20 12:57:39 -0400107void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400108{
Jamie Madillc3755fc2018-04-05 08:39:13 -0400109 VkDevice device = vk::GetImpl(context)->getRenderer()->getDevice();
Frank Henigmane4523822018-07-19 16:10:53 -0400110 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
111 {
112 buffer.destroy(device);
113 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400114 mDynamicVertexData.destroy(device);
115 mDynamicIndexData.destroy(device);
Luc Ferron6ed167a2018-06-13 13:45:55 -0400116 mTranslatedByteIndexData.destroy(device);
Jamie Madill22f12fe2018-04-08 14:23:40 -0400117 mLineLoopHelper.destroy(device);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400118}
119
Jamie Madill21061022018-07-12 23:56:30 -0400120angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
Jamie Madill253038d2018-08-30 16:18:35 -0400121 GLenum indexType,
122 size_t indexCount,
123 const void *sourcePointer,
124 vk::DynamicBuffer *dynamicBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400125{
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400126 ASSERT(!mState.getElementArrayBuffer() || indexType == GL_UNSIGNED_BYTE);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400127
Jamie Madill253038d2018-08-30 16:18:35 -0400128 dynamicBuffer->releaseRetainedBuffers(contextVk->getRenderer());
Jamie Madilla064c272018-08-30 16:18:34 -0400129
Jamie Madill253038d2018-08-30 16:18:35 -0400130 const size_t amount = sizeof(GLushort) * indexCount;
131 GLubyte *dst = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400132
Jamie Madill253038d2018-08-30 16:18:35 -0400133 ANGLE_TRY(dynamicBuffer->allocate(contextVk, amount, &dst, &mCurrentElementArrayBufferHandle,
134 &mCurrentElementArrayBufferOffset, nullptr));
135 if (indexType == GL_UNSIGNED_BYTE)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400136 {
137 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
138 // memory to a GLushort.
Jamie Madill253038d2018-08-30 16:18:35 -0400139 const GLubyte *in = static_cast<const GLubyte *>(sourcePointer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400140 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
Jamie Madill253038d2018-08-30 16:18:35 -0400141 for (size_t index = 0; index < indexCount; index++)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400142 {
143 expandedDst[index] = static_cast<GLushort>(in[index]);
144 }
145 }
146 else
147 {
Jamie Madill253038d2018-08-30 16:18:35 -0400148 memcpy(dst, sourcePointer, amount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400149 }
Jamie Madill253038d2018-08-30 16:18:35 -0400150 ANGLE_TRY(dynamicBuffer->flush(contextVk));
Jamie Madill21061022018-07-12 23:56:30 -0400151 return angle::Result::Continue();
Frank Henigman17448952017-01-05 15:48:26 -0500152}
153
Frank Henigmane4523822018-07-19 16:10:53 -0400154// We assume the buffer is completely full of the same kind of data and convert
155// and/or align it as we copy it to a DynamicBuffer. The assumption could be wrong
156// but the alternative of copying it piecemeal on each draw would have a lot more
157// overhead.
Jamie Madilla064c272018-08-30 16:18:34 -0400158angle::Result VertexArrayVk::convertVertexBuffer(ContextVk *contextVk,
Frank Henigmane4523822018-07-19 16:10:53 -0400159 BufferVk *srcBuffer,
160 const gl::VertexBinding &binding,
161 size_t attribIndex)
162{
163
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400164 // Needed before reading buffer or we could get stale data.
Jamie Madilla064c272018-08-30 16:18:34 -0400165 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400166
167 unsigned srcFormatSize = mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes;
Jamie Madilla064c272018-08-30 16:18:34 -0400168 unsigned dstFormatSize = mCurrentArrayBufferStrides[attribIndex];
169
170 mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(contextVk->getRenderer());
Frank Henigmane4523822018-07-19 16:10:53 -0400171
172 // Bytes usable for vertex data.
173 GLint64 bytes = srcBuffer->getSize() - binding.getOffset();
174 if (bytes < srcFormatSize)
175 return angle::Result::Continue();
176
177 // Count the last vertex. It may occupy less than a full stride.
178 size_t numVertices = 1;
179 bytes -= srcFormatSize;
180
181 // Count how many strides fit remaining space.
182 if (bytes > 0)
183 numVertices += static_cast<size_t>(bytes) / binding.getStride();
184
185 void *src = nullptr;
Jamie Madilla064c272018-08-30 16:18:34 -0400186 ANGLE_TRY(srcBuffer->mapImpl(contextVk, &src));
187 const uint8_t *srcBytes = reinterpret_cast<const uint8_t *>(src);
188 srcBytes += binding.getOffset();
jchen105dc0a6f2018-09-20 14:30:45 +0800189 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
190 kMaxVertexFormatAlignment);
Jamie Madilla064c272018-08-30 16:18:34 -0400191 ANGLE_TRY(StreamVertexData(contextVk, &mCurrentArrayBufferConversion[attribIndex], srcBytes,
192 numVertices * dstFormatSize, 0, numVertices, binding.getStride(),
193 mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
194 &mCurrentArrayBufferHandles[attribIndex],
195 &mCurrentArrayBufferOffsets[attribIndex]));
196 ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400197
198 mCurrentArrayBufferConversionCanRelease[attribIndex] = true;
Frank Henigmane4523822018-07-19 16:10:53 -0400199
200 return angle::Result::Continue();
201}
202
203void VertexArrayVk::ensureConversionReleased(RendererVk *renderer, size_t attribIndex)
204{
205 if (mCurrentArrayBufferConversionCanRelease[attribIndex])
206 {
207 mCurrentArrayBufferConversion[attribIndex].release(renderer);
208 mCurrentArrayBufferConversionCanRelease[attribIndex] = false;
209 }
210}
211
212#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
213 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
214 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
215 bindings[attribs[INDEX].bindingIndex], INDEX)); \
216 invalidatePipeline = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400217 break;
218
Frank Henigmane4523822018-07-19 16:10:53 -0400219#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
220 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
221 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
222 bindings[attribs[INDEX].bindingIndex], INDEX)); \
223 invalidatePipeline = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400224 break;
225
Frank Henigmane4523822018-07-19 16:10:53 -0400226#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
227 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
228 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
229 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madilla56467e2018-04-11 16:19:41 -0400230 break;
231
Jamie Madill6f755b22018-10-09 12:48:54 -0400232angle::Result VertexArrayVk::syncState(const gl::Context *context,
233 const gl::VertexArray::DirtyBits &dirtyBits,
234 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
235 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400236{
237 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400238
Jamie Madillc3755fc2018-04-05 08:39:13 -0400239 bool invalidatePipeline = false;
240
Jamie Madill5a4c9322018-07-16 11:01:58 -0400241 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400242
243 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
244 // TODO(jmadill): Handle buffer storage changes.
245 const auto &attribs = mState.getVertexAttributes();
246 const auto &bindings = mState.getVertexBindings();
247
Jamie Madill09463932018-04-04 05:26:59 -0400248 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400249 {
Jamie Madill09463932018-04-04 05:26:59 -0400250 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500251 {
Jamie Madill09463932018-04-04 05:26:59 -0400252 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500253 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400254 gl::Buffer *bufferGL = mState.getElementArrayBuffer();
Jamie Madill09463932018-04-04 05:26:59 -0400255 if (bufferGL)
256 {
Jamie Madillc3755fc2018-04-05 08:39:13 -0400257 BufferVk *bufferVk = vk::GetImpl(bufferGL);
Jamie Madill2d03ff42018-09-27 15:04:26 -0400258 mCurrentElementArrayBufferResource = &bufferVk->getBuffer();
259 mCurrentElementArrayBufferHandle =
260 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill09463932018-04-04 05:26:59 -0400261 }
262 else
263 {
264 mCurrentElementArrayBufferResource = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400265 mCurrentElementArrayBufferHandle = VK_NULL_HANDLE;
Jamie Madill09463932018-04-04 05:26:59 -0400266 }
Luc Ferron387b3b32018-05-28 10:11:57 -0400267
268 mCurrentElementArrayBufferOffset = 0;
269 mLineLoopBufferFirstIndex.reset();
270 mLineLoopBufferLastIndex.reset();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400271 contextVk->setIndexBufferDirty();
Jamie Madillb8e39662018-04-04 11:41:42 -0400272 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400273 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500274 }
Jamie Madill09463932018-04-04 05:26:59 -0400275
276 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400277 mLineLoopBufferFirstIndex.reset();
278 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400279 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400280 break;
281
Jamie Madilla56467e2018-04-11 16:19:41 -0400282 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
283 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
284 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
285
Jamie Madill09463932018-04-04 05:26:59 -0400286 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400287 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400288 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400289 }
290 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400291
Jamie Madillc3755fc2018-04-05 08:39:13 -0400292 if (invalidatePipeline)
293 {
Jamie Madillc3755fc2018-04-05 08:39:13 -0400294 contextVk->invalidateCurrentPipeline();
295 }
296
Jamie Madill6f755b22018-10-09 12:48:54 -0400297 return angle::Result::Continue();
Jamie Madillbd159f02017-10-09 19:39:06 -0400298}
299
Frank Henigmane4523822018-07-19 16:10:53 -0400300angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
301 const gl::VertexAttribute &attrib,
302 const gl::VertexBinding &binding,
303 size_t attribIndex)
Jamie Madilla56467e2018-04-11 16:19:41 -0400304{
305 // Invalidate the input description for pipelines.
306 mDirtyPackedInputs.set(attribIndex);
307
Frank Henigman67c388e2018-07-19 19:16:11 -0400308 RendererVk *renderer = contextVk->getRenderer();
Frank Henigmane4523822018-07-19 16:10:53 -0400309 bool releaseConversion = true;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400310
Jamie Madilla56467e2018-04-11 16:19:41 -0400311 if (attrib.enabled)
312 {
Frank Henigman67c388e2018-07-19 19:16:11 -0400313 gl::Buffer *bufferGL = binding.getBuffer().get();
Frank Henigman419acc82018-06-24 19:57:31 -0400314 mCurrentArrayBufferFormats[attribIndex] = &renderer->getFormat(GetVertexFormatID(attrib));
Frank Henigmane4523822018-07-19 16:10:53 -0400315
Jamie Madilla56467e2018-04-11 16:19:41 -0400316 if (bufferGL)
317 {
Frank Henigmane4523822018-07-19 16:10:53 -0400318 BufferVk *bufferVk = vk::GetImpl(bufferGL);
319 unsigned componentSize =
320 mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes / attrib.size;
Frank Henigman419acc82018-06-24 19:57:31 -0400321
Frank Henigmane4523822018-07-19 16:10:53 -0400322 if (mCurrentArrayBufferFormats[attribIndex]->vertexLoadRequiresConversion ||
323 !BindingIsAligned(binding, componentSize))
324 {
Jamie Madilla064c272018-08-30 16:18:34 -0400325 mCurrentArrayBufferStrides[attribIndex] =
326 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
327
Frank Henigmane4523822018-07-19 16:10:53 -0400328 ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex));
329
Frank Henigmane4523822018-07-19 16:10:53 -0400330 mCurrentArrayBufferResources[attribIndex] = nullptr;
331 releaseConversion = false;
332 }
333 else
334 {
Jamie Madill2d03ff42018-09-27 15:04:26 -0400335 mCurrentArrayBufferResources[attribIndex] = &bufferVk->getBuffer();
336 mCurrentArrayBufferHandles[attribIndex] =
337 bufferVk->getBuffer().getBuffer().getHandle();
Frank Henigmane4523822018-07-19 16:10:53 -0400338 mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
339 mCurrentArrayBufferStrides[attribIndex] = binding.getStride();
340 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400341 }
342 else
343 {
344 mCurrentArrayBufferResources[attribIndex] = nullptr;
345 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
Luc Ferronfa5d84b2018-06-28 10:40:04 -0400346 mCurrentArrayBufferOffsets[attribIndex] = 0;
Frank Henigman419acc82018-06-24 19:57:31 -0400347 mCurrentArrayBufferStrides[attribIndex] =
Frank Henigmane4523822018-07-19 16:10:53 -0400348 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
Jamie Madilla56467e2018-04-11 16:19:41 -0400349 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400350 }
351 else
352 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400353 contextVk->invalidateDefaultAttribute(attribIndex);
354
355 // These will be filled out by the ContextVk.
356 mCurrentArrayBufferResources[attribIndex] = nullptr;
357 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
358 mCurrentArrayBufferOffsets[attribIndex] = 0;
359 mCurrentArrayBufferStrides[attribIndex] = 0;
360 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400361 &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
Jamie Madilla56467e2018-04-11 16:19:41 -0400362 }
Frank Henigmane4523822018-07-19 16:10:53 -0400363
364 if (releaseConversion)
365 ensureConversionReleased(renderer, attribIndex);
366
367 return angle::Result::Continue();
Jamie Madilla56467e2018-04-11 16:19:41 -0400368}
369
Frank Henigman419acc82018-06-24 19:57:31 -0400370void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400371{
Frank Henigman419acc82018-06-24 19:57:31 -0400372 updatePackedInputDescriptions();
Jamie Madill112a3a82018-01-23 13:04:06 -0500373 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400374}
375
Frank Henigman419acc82018-06-24 19:57:31 -0400376void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400377{
Jamie Madill112a3a82018-01-23 13:04:06 -0500378 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400379 {
380 return;
381 }
382
383 const auto &attribs = mState.getVertexAttributes();
384 const auto &bindings = mState.getVertexBindings();
385
Jamie Madill112a3a82018-01-23 13:04:06 -0500386 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400387 {
388 const auto &attrib = attribs[attribIndex];
389 const auto &binding = bindings[attrib.bindingIndex];
390 if (attrib.enabled)
391 {
Frank Henigman419acc82018-06-24 19:57:31 -0400392 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400393 }
394 else
395 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400396 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
397 bindingDesc.stride = 0;
398 bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
399
400 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
401 attribDesc.format = static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
402 attribDesc.location = static_cast<uint16_t>(attribIndex);
403 attribDesc.offset = 0;
Jamie Madillebf72992017-10-13 14:09:45 -0400404 }
405 }
406
Jamie Madill112a3a82018-01-23 13:04:06 -0500407 mDirtyPackedInputs.reset();
408}
409
Frank Henigman419acc82018-06-24 19:57:31 -0400410void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
Jamie Madill112a3a82018-01-23 13:04:06 -0500411 const gl::VertexBinding &binding,
412 const gl::VertexAttribute &attrib)
413{
414 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
415
Frank Henigman419acc82018-06-24 19:57:31 -0400416 bindingDesc.stride = static_cast<uint16_t>(mCurrentArrayBufferStrides[attribIndex]);
Jamie Madill112a3a82018-01-23 13:04:06 -0500417 bindingDesc.inputRate = static_cast<uint16_t>(
418 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
419
Frank Henigman419acc82018-06-24 19:57:31 -0400420 VkFormat vkFormat = mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat;
Jamie Madill112a3a82018-01-23 13:04:06 -0500421 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
Frank Henigman8c379f32018-06-21 19:55:05 -0400422 if (vkFormat == VK_FORMAT_UNDEFINED)
423 {
Frank Henigman8c379f32018-06-21 19:55:05 -0400424 UNIMPLEMENTED();
425 }
Jamie Madill112a3a82018-01-23 13:04:06 -0500426
427 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
428 attribDesc.format = static_cast<uint16_t>(vkFormat);
429 attribDesc.location = static_cast<uint16_t>(attribIndex);
Luc Ferronfa5d84b2018-06-28 10:40:04 -0400430 attribDesc.offset = static_cast<uint32_t>(attrib.relativeOffset);
Jamie Madillebf72992017-10-13 14:09:45 -0400431}
432
Jamie Madill88fc6da2018-08-30 16:18:36 -0400433angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
434 const gl::DrawCallParams &drawCallParams)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400435{
Jamie Madill21061022018-07-12 23:56:30 -0400436 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400437 const gl::AttributesMask &clientAttribs = context->getStateCache().getActiveClientAttribsMask();
Jamie Madill21061022018-07-12 23:56:30 -0400438
Jamie Madill88fc6da2018-08-30 16:18:36 -0400439 ASSERT(clientAttribs.any());
Jamie Madillc1fd7372018-10-26 22:48:39 -0400440
441 GLint startVertex;
442 size_t vertexCount;
443 GLsizei vertexOrIndexCount = drawCallParams.isDrawElements() ? drawCallParams.indexCount()
444 : drawCallParams.vertexCount();
445 GLenum indexTypeOrNone = drawCallParams.isDrawElements() ? drawCallParams.type() : GL_NONE;
446 ANGLE_TRY(GetVertexRangeInfo(context, drawCallParams.firstVertex(), vertexOrIndexCount,
447 indexTypeOrNone, drawCallParams.indices(),
448 drawCallParams.baseVertex(), &startVertex, &vertexCount));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400449
450 mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
451
452 const auto &attribs = mState.getVertexAttributes();
453 const auto &bindings = mState.getVertexBindings();
454
455 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
456 // un-interleaved, wasting space and copying time. Consider improving on that.
457 for (size_t attribIndex : clientAttribs)
458 {
459 const gl::VertexAttribute &attrib = attribs[attribIndex];
460 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
461 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
462
463 const size_t bytesToAllocate =
Jamie Madillc1fd7372018-10-26 22:48:39 -0400464 (startVertex + vertexCount) * mCurrentArrayBufferStrides[attribIndex];
465 const uint8_t *src =
466 static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400467
Jamie Madillc1fd7372018-10-26 22:48:39 -0400468 size_t destOffset = startVertex * mCurrentArrayBufferStrides[attribIndex];
jchen105dc0a6f2018-09-20 14:30:45 +0800469 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
470 kMaxVertexFormatAlignment);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400471
472 // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
473 // We allocate space for firstVertex() + vertexCount() so indexing will work. If we
474 // don't start at zero all the indices will be off.
475 // TODO(fjhenigman): See if we can account for indices being off by adjusting the
476 // offset, thus avoiding wasted memory.
Jamie Madillc1fd7372018-10-26 22:48:39 -0400477 ANGLE_TRY(StreamVertexData(
478 contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
479 binding.getStride(), mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
480 &mCurrentArrayBufferHandles[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400481 }
482
483 return angle::Result::Continue();
484}
485
486angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk,
487 const gl::DrawCallParams &drawCallParams)
488{
489 if (drawCallParams.isDrawElements())
490 {
491 // Handle GL_LINE_LOOP drawElements.
492 if (mDirtyLineLoopTranslation)
493 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400494 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400495
496 if (!elementArrayBuffer)
497 {
Frank Henigman85c4b432018-09-19 23:35:00 -0400498 ANGLE_TRY(mLineLoopHelper.streamIndices(
499 contextVk, drawCallParams.type(), drawCallParams.indexCount(),
500 reinterpret_cast<const uint8_t *>(drawCallParams.indices()),
501 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400502 }
503 else
504 {
505 // When using an element array buffer, 'indices' is an offset to the first element.
506 intptr_t offset = reinterpret_cast<intptr_t>(drawCallParams.indices());
507 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
508 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Frank Henigman85c4b432018-09-19 23:35:00 -0400509 contextVk, elementArrayBufferVk, drawCallParams.type(),
510 drawCallParams.indexCount(), offset, &mCurrentElementArrayBufferHandle,
511 &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400512 }
513 }
514
515 // If we've had a drawArrays call with a line loop before, we want to make sure this is
516 // invalidated the next time drawArrays is called since we use the same index buffer for
517 // both calls.
518 mLineLoopBufferFirstIndex.reset();
519 mLineLoopBufferLastIndex.reset();
520 return angle::Result::Continue();
521 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400522
Jamie Madill18e323a2018-05-11 16:54:17 -0400523 // Note: Vertex indexes can be arbitrarily large.
524 uint32_t clampedVertexCount = drawCallParams.getClampedVertexCount<uint32_t>();
525
Jamie Madillc3755fc2018-04-05 08:39:13 -0400526 // Handle GL_LINE_LOOP drawArrays.
Jamie Madill18e323a2018-05-11 16:54:17 -0400527 size_t lastVertex = static_cast<size_t>(drawCallParams.firstVertex() + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400528 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
529 mLineLoopBufferFirstIndex != drawCallParams.firstVertex() ||
530 mLineLoopBufferLastIndex != lastVertex)
531 {
Jamie Madill21061022018-07-12 23:56:30 -0400532 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(contextVk, drawCallParams,
Jamie Madill22f12fe2018-04-08 14:23:40 -0400533 &mCurrentElementArrayBufferHandle,
534 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400535
536 mLineLoopBufferFirstIndex = drawCallParams.firstVertex();
537 mLineLoopBufferLastIndex = lastVertex;
538 }
539
Jamie Madill88fc6da2018-08-30 16:18:36 -0400540 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400541}
542
Jamie Madill88fc6da2018-08-30 16:18:36 -0400543angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
544 const gl::DrawCallParams &drawCallParams)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400545{
Jamie Madill88fc6da2018-08-30 16:18:36 -0400546 ASSERT(drawCallParams.isDrawElements());
547 ASSERT(drawCallParams.mode() != gl::PrimitiveMode::LineLoop);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400548
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400549 gl::Buffer *glBuffer = mState.getElementArrayBuffer();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400550
Jamie Madill88fc6da2018-08-30 16:18:36 -0400551 if (!glBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400552 {
Jamie Madill253038d2018-08-30 16:18:35 -0400553 ANGLE_TRY(streamIndexData(contextVk, drawCallParams.type(), drawCallParams.indexCount(),
554 drawCallParams.indices(), &mDynamicIndexData));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400555 }
Jamie Madill88fc6da2018-08-30 16:18:36 -0400556 else
Jamie Madillc3755fc2018-04-05 08:39:13 -0400557 {
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400558 // Needed before reading buffer or we could get stale data.
559 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
560
Jamie Madill88fc6da2018-08-30 16:18:36 -0400561 ASSERT(drawCallParams.type() == GL_UNSIGNED_BYTE);
562 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
563 // memory to a GLushort.
564 BufferVk *bufferVk = vk::GetImpl(glBuffer);
565 void *srcDataMapping = nullptr;
566 ASSERT(!glBuffer->isMapped());
567 ANGLE_TRY(bufferVk->mapImpl(contextVk, &srcDataMapping));
568 uint8_t *srcData = static_cast<uint8_t *>(srcDataMapping);
569 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(drawCallParams.indices());
570 srcData += offsetIntoSrcData;
Jamie Madill253038d2018-08-30 16:18:35 -0400571
Jamie Madill88fc6da2018-08-30 16:18:36 -0400572 ANGLE_TRY(streamIndexData(contextVk, drawCallParams.type(),
573 static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData,
574 srcData, &mTranslatedByteIndexData));
Luc Ferron6ed167a2018-06-13 13:45:55 -0400575
Jamie Madill88fc6da2018-08-30 16:18:36 -0400576 ANGLE_TRY(bufferVk->unmapImpl(contextVk));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400577 }
578
Jamie Madill88fc6da2018-08-30 16:18:36 -0400579 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400580}
Jamie Madill5a4c9322018-07-16 11:01:58 -0400581
582void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
583 size_t attribIndex,
584 VkBuffer bufferHandle,
585 uint32_t offset)
586{
587 if (!mState.getEnabledAttributesMask().test(attribIndex))
588 {
589 mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
590 mCurrentArrayBufferOffsets[attribIndex] = offset;
591 mCurrentArrayBufferResources[attribIndex] = nullptr;
592 mCurrentArrayBufferStrides[attribIndex] = 0;
593 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400594 &renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED);
Jamie Madill5a4c9322018-07-16 11:01:58 -0400595 mDirtyPackedInputs.set(attribIndex);
596 }
597}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400598} // namespace rx