blob: 3748816f478f3572b85ad1ccf883862a94f41ff0 [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 Madill03d1a5e2018-11-12 11:34:24 -050067 mCurrentArrayBuffers{},
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),
Jamie Madill03d1a5e2018-11-12 11:34:24 -050077 mCurrentElementArrayBuffer(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 Madill03d1a5e2018-11-12 11:34:24 -050088 mCurrentArrayBuffers.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{
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500108 RendererVk *renderer = vk::GetImpl(context)->getRenderer();
109
Frank Henigmane4523822018-07-19 16:10:53 -0400110 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
111 {
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500112 buffer.release(renderer);
Frank Henigmane4523822018-07-19 16:10:53 -0400113 }
Shahbaz Youssefifca8fd62018-11-13 13:55:48 -0500114 mDynamicVertexData.release(renderer);
115 mDynamicIndexData.release(renderer);
116 mTranslatedByteIndexData.release(renderer);
117 mLineLoopHelper.release(renderer);
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
Jamie Madill77abad82018-10-25 17:03:48 -0400185 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)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500216 invalidateContext = 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)); \
Jamie Madillbc5834c2018-11-06 11:13:50 -0500223 invalidateContext = 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 Madillbc5834c2018-11-06 11:13:50 -0500239 bool invalidateContext = false;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400240
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 Madill03d1a5e2018-11-12 11:34:24 -0500257 BufferVk *bufferVk = vk::GetImpl(bufferGL);
258 mCurrentElementArrayBuffer = &bufferVk->getBuffer();
Jamie Madill2d03ff42018-09-27 15:04:26 -0400259 mCurrentElementArrayBufferHandle =
260 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill09463932018-04-04 05:26:59 -0400261 }
262 else
263 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500264 mCurrentElementArrayBuffer = nullptr;
265 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 Madillbc5834c2018-11-06 11:13:50 -0500292 if (invalidateContext)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400293 {
Jamie Madillbc5834c2018-11-06 11:13:50 -0500294 contextVk->invalidateVertexAndIndexBuffers();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400295 }
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
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500330 mCurrentArrayBuffers[attribIndex] = nullptr;
331 releaseConversion = false;
Frank Henigmane4523822018-07-19 16:10:53 -0400332 }
333 else
334 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500335 mCurrentArrayBuffers[attribIndex] = &bufferVk->getBuffer();
Jamie Madill2d03ff42018-09-27 15:04:26 -0400336 mCurrentArrayBufferHandles[attribIndex] =
337 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill77abad82018-10-25 17:03:48 -0400338 mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
339 mCurrentArrayBufferStrides[attribIndex] = binding.getStride();
Frank Henigmane4523822018-07-19 16:10:53 -0400340 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400341 }
342 else
343 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500344 mCurrentArrayBuffers[attribIndex] = nullptr;
345 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
346 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.
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500356 mCurrentArrayBuffers[attribIndex] = nullptr;
357 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
358 mCurrentArrayBufferOffsets[attribIndex] = 0;
359 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400360 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
Jamie Madill77b24362018-11-05 22:39:29 -0500400 mPackedInputAttributes.formats[attribIndex] =
401 static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
402 mPackedInputAttributes.offsets[attribIndex] = 0;
Jamie Madillebf72992017-10-13 14:09:45 -0400403 }
404 }
405
Jamie Madill112a3a82018-01-23 13:04:06 -0500406 mDirtyPackedInputs.reset();
407}
408
Frank Henigman419acc82018-06-24 19:57:31 -0400409void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
Jamie Madill112a3a82018-01-23 13:04:06 -0500410 const gl::VertexBinding &binding,
411 const gl::VertexAttribute &attrib)
412{
413 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
414
Frank Henigman419acc82018-06-24 19:57:31 -0400415 bindingDesc.stride = static_cast<uint16_t>(mCurrentArrayBufferStrides[attribIndex]);
Jamie Madill112a3a82018-01-23 13:04:06 -0500416 bindingDesc.inputRate = static_cast<uint16_t>(
417 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
418
Frank Henigman419acc82018-06-24 19:57:31 -0400419 VkFormat vkFormat = mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat;
Jamie Madill112a3a82018-01-23 13:04:06 -0500420 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
Frank Henigman8c379f32018-06-21 19:55:05 -0400421 if (vkFormat == VK_FORMAT_UNDEFINED)
422 {
Frank Henigman8c379f32018-06-21 19:55:05 -0400423 UNIMPLEMENTED();
424 }
Jamie Madill112a3a82018-01-23 13:04:06 -0500425
Jamie Madill77b24362018-11-05 22:39:29 -0500426 mPackedInputAttributes.formats[attribIndex] = static_cast<uint8_t>(vkFormat);
427 mPackedInputAttributes.offsets[attribIndex] = static_cast<uint16_t>(attrib.relativeOffset);
Jamie Madillebf72992017-10-13 14:09:45 -0400428}
429
Jamie Madill88fc6da2018-08-30 16:18:36 -0400430angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400431 GLint firstVertex,
432 GLsizei vertexOrIndexCount,
433 GLenum indexTypeOrNone,
434 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400435{
Jamie Madill77abad82018-10-25 17:03:48 -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;
Jamie Madillbfe31c42018-10-25 17:03:47 -0400443 ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrNone, indices,
444 0, &startVertex, &vertexCount));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400445
446 mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
447
448 const auto &attribs = mState.getVertexAttributes();
449 const auto &bindings = mState.getVertexBindings();
450
451 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
452 // un-interleaved, wasting space and copying time. Consider improving on that.
453 for (size_t attribIndex : clientAttribs)
454 {
455 const gl::VertexAttribute &attrib = attribs[attribIndex];
456 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
457 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
458
459 const size_t bytesToAllocate =
Jamie Madillc1fd7372018-10-26 22:48:39 -0400460 (startVertex + vertexCount) * mCurrentArrayBufferStrides[attribIndex];
461 const uint8_t *src =
462 static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400463
Jamie Madillc1fd7372018-10-26 22:48:39 -0400464 size_t destOffset = startVertex * mCurrentArrayBufferStrides[attribIndex];
jchen105dc0a6f2018-09-20 14:30:45 +0800465 ASSERT(GetVertexInputAlignment(*mCurrentArrayBufferFormats[attribIndex]) <=
466 kMaxVertexFormatAlignment);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400467
468 // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400469 // We allocate space for startVertex + vertexCount so indexing will work. If we
Jamie Madill88fc6da2018-08-30 16:18:36 -0400470 // don't start at zero all the indices will be off.
471 // TODO(fjhenigman): See if we can account for indices being off by adjusting the
472 // offset, thus avoiding wasted memory.
Jamie Madillc1fd7372018-10-26 22:48:39 -0400473 ANGLE_TRY(StreamVertexData(
474 contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
475 binding.getStride(), mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
476 &mCurrentArrayBufferHandles[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400477 }
478
479 return angle::Result::Continue();
480}
481
482angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400483 GLint firstVertex,
484 GLsizei vertexOrIndexCount,
485 GLenum indexTypeOrNone,
486 const void *indices)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400487{
Jamie Madillbfe31c42018-10-25 17:03:47 -0400488 if (indexTypeOrNone != GL_NONE)
Jamie Madill88fc6da2018-08-30 16:18:36 -0400489 {
490 // Handle GL_LINE_LOOP drawElements.
491 if (mDirtyLineLoopTranslation)
492 {
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400493 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400494
495 if (!elementArrayBuffer)
496 {
Frank Henigman85c4b432018-09-19 23:35:00 -0400497 ANGLE_TRY(mLineLoopHelper.streamIndices(
Jamie Madillbfe31c42018-10-25 17:03:47 -0400498 contextVk, indexTypeOrNone, vertexOrIndexCount,
499 reinterpret_cast<const uint8_t *>(indices), &mCurrentElementArrayBufferHandle,
500 &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400501 }
502 else
503 {
504 // When using an element array buffer, 'indices' is an offset to the first element.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400505 intptr_t offset = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400506 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
507 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Jamie Madillbfe31c42018-10-25 17:03:47 -0400508 contextVk, elementArrayBufferVk, indexTypeOrNone, vertexOrIndexCount, offset,
509 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400510 }
511 }
512
513 // If we've had a drawArrays call with a line loop before, we want to make sure this is
514 // invalidated the next time drawArrays is called since we use the same index buffer for
515 // both calls.
516 mLineLoopBufferFirstIndex.reset();
517 mLineLoopBufferLastIndex.reset();
518 return angle::Result::Continue();
519 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400520
Jamie Madill18e323a2018-05-11 16:54:17 -0400521 // Note: Vertex indexes can be arbitrarily large.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400522 uint32_t clampedVertexCount = gl::clampCast<uint32_t>(vertexOrIndexCount);
Jamie Madill18e323a2018-05-11 16:54:17 -0400523
Jamie Madillc3755fc2018-04-05 08:39:13 -0400524 // Handle GL_LINE_LOOP drawArrays.
Jamie Madillbfe31c42018-10-25 17:03:47 -0400525 size_t lastVertex = static_cast<size_t>(firstVertex + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400526 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
Jamie Madillbfe31c42018-10-25 17:03:47 -0400527 mLineLoopBufferFirstIndex != firstVertex || mLineLoopBufferLastIndex != lastVertex)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400528 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400529 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(
530 contextVk, clampedVertexCount, firstVertex, &mCurrentElementArrayBufferHandle,
531 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400532
Jamie Madillbfe31c42018-10-25 17:03:47 -0400533 mLineLoopBufferFirstIndex = firstVertex;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400534 mLineLoopBufferLastIndex = lastVertex;
535 }
536
Jamie Madill88fc6da2018-08-30 16:18:36 -0400537 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400538}
539
Jamie Madill88fc6da2018-08-30 16:18:36 -0400540angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
Jamie Madillbfe31c42018-10-25 17:03:47 -0400541 GLsizei indexCount,
542 GLenum type,
543 const void *indices)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400544{
Jamie Madillbfe31c42018-10-25 17:03:47 -0400545 ASSERT(type != GL_NONE);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400546
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400547 gl::Buffer *glBuffer = mState.getElementArrayBuffer();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400548
Jamie Madill88fc6da2018-08-30 16:18:36 -0400549 if (!glBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400550 {
Jamie Madillbfe31c42018-10-25 17:03:47 -0400551 ANGLE_TRY(streamIndexData(contextVk, type, indexCount, indices, &mDynamicIndexData));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400552 }
Jamie Madill88fc6da2018-08-30 16:18:36 -0400553 else
Jamie Madillc3755fc2018-04-05 08:39:13 -0400554 {
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400555 // Needed before reading buffer or we could get stale data.
556 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
557
Jamie Madillbfe31c42018-10-25 17:03:47 -0400558 ASSERT(type == GL_UNSIGNED_BYTE);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400559 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
560 // memory to a GLushort.
561 BufferVk *bufferVk = vk::GetImpl(glBuffer);
562 void *srcDataMapping = nullptr;
563 ASSERT(!glBuffer->isMapped());
564 ANGLE_TRY(bufferVk->mapImpl(contextVk, &srcDataMapping));
565 uint8_t *srcData = static_cast<uint8_t *>(srcDataMapping);
Jamie Madillbfe31c42018-10-25 17:03:47 -0400566 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400567 srcData += offsetIntoSrcData;
Jamie Madill253038d2018-08-30 16:18:35 -0400568
Jamie Madillbfe31c42018-10-25 17:03:47 -0400569 ANGLE_TRY(streamIndexData(contextVk, type,
Jamie Madill88fc6da2018-08-30 16:18:36 -0400570 static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData,
571 srcData, &mTranslatedByteIndexData));
Luc Ferron6ed167a2018-06-13 13:45:55 -0400572
Jamie Madill88fc6da2018-08-30 16:18:36 -0400573 ANGLE_TRY(bufferVk->unmapImpl(contextVk));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400574 }
575
Jamie Madill88fc6da2018-08-30 16:18:36 -0400576 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400577}
Jamie Madill5a4c9322018-07-16 11:01:58 -0400578
579void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
580 size_t attribIndex,
581 VkBuffer bufferHandle,
582 uint32_t offset)
583{
584 if (!mState.getEnabledAttributesMask().test(attribIndex))
585 {
Jamie Madill03d1a5e2018-11-12 11:34:24 -0500586 mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
587 mCurrentArrayBufferOffsets[attribIndex] = offset;
588 mCurrentArrayBuffers[attribIndex] = nullptr;
589 mCurrentArrayBufferStrides[attribIndex] = 0;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400590 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400591 &renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED);
Jamie Madill5a4c9322018-07-16 11:01:58 -0400592 mDirtyPackedInputs.set(attribIndex);
593 }
594}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400595} // namespace rx