blob: 90d9ff219ae2166d0d8c7606d3b0e56fdeed9355 [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;
Frank Henigmane4523822018-07-19 16:10:53 -040028
29bool BindingIsAligned(const gl::VertexBinding &binding, unsigned componentSize)
30{
31 return (binding.getOffset() % componentSize == 0) && (binding.getStride() % componentSize == 0);
32}
Jamie Madilla064c272018-08-30 16:18:34 -040033
34angle::Result StreamVertexData(ContextVk *contextVk,
35 vk::DynamicBuffer *dynamicBuffer,
36 const uint8_t *sourceData,
37 size_t bytesToAllocate,
38 size_t destOffset,
39 size_t vertexCount,
40 size_t stride,
41 VertexCopyFunction vertexLoadFunction,
42 VkBuffer *bufferHandleOut,
43 VkDeviceSize *bufferOffsetOut)
44{
45 uint8_t *dst = nullptr;
46 ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, bufferHandleOut,
47 bufferOffsetOut, nullptr));
48 dst += destOffset;
49 vertexLoadFunction(sourceData, stride, vertexCount, dst);
50
51 ANGLE_TRY(dynamicBuffer->flush(contextVk));
52 return angle::Result::Continue();
53}
Jamie Madillc3755fc2018-04-05 08:39:13 -040054} // anonymous namespace
Jamie Madill9e54b5a2016-05-25 12:57:39 -040055
Frank Henigmane4523822018-07-19 16:10:53 -040056#define INIT \
57 { \
58 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 1024 * 8 \
59 }
60
Luc Ferrona9ab0f32018-05-17 17:03:55 -040061VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *renderer)
Jamie Madillbd159f02017-10-09 19:39:06 -040062 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050063 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050064 mCurrentArrayBufferOffsets{},
Jamie Madillda854a22017-11-30 17:24:21 -050065 mCurrentArrayBufferResources{},
Frank Henigman419acc82018-06-24 19:57:31 -040066 mCurrentArrayBufferFormats{},
67 mCurrentArrayBufferStrides{},
Frank Henigmane4523822018-07-19 16:10:53 -040068 mCurrentArrayBufferConversion{{
69 INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT,
70 INIT,
71 }},
72 mCurrentArrayBufferConversionCanRelease{},
Jamie Madillc3755fc2018-04-05 08:39:13 -040073 mCurrentElementArrayBufferHandle(VK_NULL_HANDLE),
74 mCurrentElementArrayBufferOffset(0),
75 mCurrentElementArrayBufferResource(nullptr),
76 mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
77 mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Luc Ferron6ed167a2018-06-13 13:45:55 -040078 mTranslatedByteIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Luc Ferrona9ab0f32018-05-17 17:03:55 -040079 mLineLoopHelper(renderer),
Jamie Madill88fc6da2018-08-30 16:18:36 -040080 mDirtyLineLoopTranslation(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040081{
Jamie Madillda854a22017-11-30 17:24:21 -050082 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -050083 mCurrentArrayBufferOffsets.fill(0);
Jamie Madillda854a22017-11-30 17:24:21 -050084 mCurrentArrayBufferResources.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -050085
86 mPackedInputBindings.fill({0, 0});
87 mPackedInputAttributes.fill({0, 0, 0});
Jamie Madillc3755fc2018-04-05 08:39:13 -040088
Frank Henigmane4523822018-07-19 16:10:53 -040089 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
90 {
91 buffer.init(1, renderer);
92 }
Luc Ferrona9ab0f32018-05-17 17:03:55 -040093 mDynamicVertexData.init(1, renderer);
94 mDynamicIndexData.init(1, renderer);
Luc Ferron6ed167a2018-06-13 13:45:55 -040095 mTranslatedByteIndexData.init(1, renderer);
Jamie Madill0a17e482018-08-31 17:19:11 -040096
97 // Initially consider all inputs dirty.
98 mDirtyPackedInputs.set();
Jamie Madill9e54b5a2016-05-25 12:57:39 -040099}
100
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500101VertexArrayVk::~VertexArrayVk()
102{
103}
104
Jamie Madill4928b7c2017-06-20 12:57:39 -0400105void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400106{
Jamie Madillc3755fc2018-04-05 08:39:13 -0400107 VkDevice device = vk::GetImpl(context)->getRenderer()->getDevice();
Frank Henigmane4523822018-07-19 16:10:53 -0400108 for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
109 {
110 buffer.destroy(device);
111 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400112 mDynamicVertexData.destroy(device);
113 mDynamicIndexData.destroy(device);
Luc Ferron6ed167a2018-06-13 13:45:55 -0400114 mTranslatedByteIndexData.destroy(device);
Jamie Madill22f12fe2018-04-08 14:23:40 -0400115 mLineLoopHelper.destroy(device);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400116}
117
Jamie Madill21061022018-07-12 23:56:30 -0400118angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
Jamie Madill253038d2018-08-30 16:18:35 -0400119 GLenum indexType,
120 size_t indexCount,
121 const void *sourcePointer,
122 vk::DynamicBuffer *dynamicBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400123{
Jamie Madill253038d2018-08-30 16:18:35 -0400124 ASSERT(!mState.getElementArrayBuffer().get() || indexType == GL_UNSIGNED_BYTE);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400125
Jamie Madill253038d2018-08-30 16:18:35 -0400126 dynamicBuffer->releaseRetainedBuffers(contextVk->getRenderer());
Jamie Madilla064c272018-08-30 16:18:34 -0400127
Jamie Madill253038d2018-08-30 16:18:35 -0400128 const size_t amount = sizeof(GLushort) * indexCount;
129 GLubyte *dst = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400130
Jamie Madill253038d2018-08-30 16:18:35 -0400131 ANGLE_TRY(dynamicBuffer->allocate(contextVk, amount, &dst, &mCurrentElementArrayBufferHandle,
132 &mCurrentElementArrayBufferOffset, nullptr));
133 if (indexType == GL_UNSIGNED_BYTE)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400134 {
135 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
136 // memory to a GLushort.
Jamie Madill253038d2018-08-30 16:18:35 -0400137 const GLubyte *in = static_cast<const GLubyte *>(sourcePointer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400138 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
Jamie Madill253038d2018-08-30 16:18:35 -0400139 for (size_t index = 0; index < indexCount; index++)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400140 {
141 expandedDst[index] = static_cast<GLushort>(in[index]);
142 }
143 }
144 else
145 {
Jamie Madill253038d2018-08-30 16:18:35 -0400146 memcpy(dst, sourcePointer, amount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400147 }
Jamie Madill253038d2018-08-30 16:18:35 -0400148 ANGLE_TRY(dynamicBuffer->flush(contextVk));
Jamie Madill21061022018-07-12 23:56:30 -0400149 return angle::Result::Continue();
Frank Henigman17448952017-01-05 15:48:26 -0500150}
151
Frank Henigmane4523822018-07-19 16:10:53 -0400152// We assume the buffer is completely full of the same kind of data and convert
153// and/or align it as we copy it to a DynamicBuffer. The assumption could be wrong
154// but the alternative of copying it piecemeal on each draw would have a lot more
155// overhead.
Jamie Madilla064c272018-08-30 16:18:34 -0400156angle::Result VertexArrayVk::convertVertexBuffer(ContextVk *contextVk,
Frank Henigmane4523822018-07-19 16:10:53 -0400157 BufferVk *srcBuffer,
158 const gl::VertexBinding &binding,
159 size_t attribIndex)
160{
161
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400162 // Needed before reading buffer or we could get stale data.
Jamie Madilla064c272018-08-30 16:18:34 -0400163 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400164
165 unsigned srcFormatSize = mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes;
Jamie Madilla064c272018-08-30 16:18:34 -0400166 unsigned dstFormatSize = mCurrentArrayBufferStrides[attribIndex];
167
168 mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(contextVk->getRenderer());
Frank Henigmane4523822018-07-19 16:10:53 -0400169
170 // Bytes usable for vertex data.
171 GLint64 bytes = srcBuffer->getSize() - binding.getOffset();
172 if (bytes < srcFormatSize)
173 return angle::Result::Continue();
174
175 // Count the last vertex. It may occupy less than a full stride.
176 size_t numVertices = 1;
177 bytes -= srcFormatSize;
178
179 // Count how many strides fit remaining space.
180 if (bytes > 0)
181 numVertices += static_cast<size_t>(bytes) / binding.getStride();
182
183 void *src = nullptr;
Jamie Madilla064c272018-08-30 16:18:34 -0400184 ANGLE_TRY(srcBuffer->mapImpl(contextVk, &src));
185 const uint8_t *srcBytes = reinterpret_cast<const uint8_t *>(src);
186 srcBytes += binding.getOffset();
187 ANGLE_TRY(StreamVertexData(contextVk, &mCurrentArrayBufferConversion[attribIndex], srcBytes,
188 numVertices * dstFormatSize, 0, numVertices, binding.getStride(),
189 mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
190 &mCurrentArrayBufferHandles[attribIndex],
191 &mCurrentArrayBufferOffsets[attribIndex]));
192 ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
Frank Henigmane4523822018-07-19 16:10:53 -0400193
194 mCurrentArrayBufferConversionCanRelease[attribIndex] = true;
Frank Henigmane4523822018-07-19 16:10:53 -0400195
196 return angle::Result::Continue();
197}
198
199void VertexArrayVk::ensureConversionReleased(RendererVk *renderer, size_t attribIndex)
200{
201 if (mCurrentArrayBufferConversionCanRelease[attribIndex])
202 {
203 mCurrentArrayBufferConversion[attribIndex].release(renderer);
204 mCurrentArrayBufferConversionCanRelease[attribIndex] = false;
205 }
206}
207
208#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
209 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
210 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
211 bindings[attribs[INDEX].bindingIndex], INDEX)); \
212 invalidatePipeline = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400213 break;
214
Frank Henigmane4523822018-07-19 16:10:53 -0400215#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
216 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
217 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
218 bindings[attribs[INDEX].bindingIndex], INDEX)); \
219 invalidatePipeline = true; \
Jamie Madilla56467e2018-04-11 16:19:41 -0400220 break;
221
Frank Henigmane4523822018-07-19 16:10:53 -0400222#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
223 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
224 ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX], \
225 bindings[attribs[INDEX].bindingIndex], INDEX)); \
Jamie Madilla56467e2018-04-11 16:19:41 -0400226 break;
227
Frank Henigman0af5b862018-03-27 20:19:33 -0400228gl::Error VertexArrayVk::syncState(const gl::Context *context,
229 const gl::VertexArray::DirtyBits &dirtyBits,
230 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
231 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400232{
233 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400234
Jamie Madillc3755fc2018-04-05 08:39:13 -0400235 bool invalidatePipeline = false;
236
Jamie Madill5a4c9322018-07-16 11:01:58 -0400237 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400238
239 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
240 // TODO(jmadill): Handle buffer storage changes.
241 const auto &attribs = mState.getVertexAttributes();
242 const auto &bindings = mState.getVertexBindings();
243
Jamie Madill09463932018-04-04 05:26:59 -0400244 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400245 {
Jamie Madill09463932018-04-04 05:26:59 -0400246 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500247 {
Jamie Madill09463932018-04-04 05:26:59 -0400248 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500249 {
Jamie Madill09463932018-04-04 05:26:59 -0400250 gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
251 if (bufferGL)
252 {
Jamie Madillc3755fc2018-04-05 08:39:13 -0400253 BufferVk *bufferVk = vk::GetImpl(bufferGL);
Jamie Madill2d03ff42018-09-27 15:04:26 -0400254 mCurrentElementArrayBufferResource = &bufferVk->getBuffer();
255 mCurrentElementArrayBufferHandle =
256 bufferVk->getBuffer().getBuffer().getHandle();
Jamie Madill09463932018-04-04 05:26:59 -0400257 }
258 else
259 {
260 mCurrentElementArrayBufferResource = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400261 mCurrentElementArrayBufferHandle = VK_NULL_HANDLE;
Jamie Madill09463932018-04-04 05:26:59 -0400262 }
Luc Ferron387b3b32018-05-28 10:11:57 -0400263
264 mCurrentElementArrayBufferOffset = 0;
265 mLineLoopBufferFirstIndex.reset();
266 mLineLoopBufferLastIndex.reset();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400267 contextVk->setIndexBufferDirty();
Jamie Madillb8e39662018-04-04 11:41:42 -0400268 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400269 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500270 }
Jamie Madill09463932018-04-04 05:26:59 -0400271
272 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400273 mLineLoopBufferFirstIndex.reset();
274 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400275 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400276 break;
277
Jamie Madilla56467e2018-04-11 16:19:41 -0400278 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
279 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
280 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
281
Jamie Madill09463932018-04-04 05:26:59 -0400282 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400283 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400284 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400285 }
286 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400287
Jamie Madillc3755fc2018-04-05 08:39:13 -0400288 if (invalidatePipeline)
289 {
Jamie Madillc3755fc2018-04-05 08:39:13 -0400290 contextVk->invalidateCurrentPipeline();
291 }
292
Frank Henigman0af5b862018-03-27 20:19:33 -0400293 return gl::NoError();
Jamie Madillbd159f02017-10-09 19:39:06 -0400294}
295
Frank Henigmane4523822018-07-19 16:10:53 -0400296angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
297 const gl::VertexAttribute &attrib,
298 const gl::VertexBinding &binding,
299 size_t attribIndex)
Jamie Madilla56467e2018-04-11 16:19:41 -0400300{
301 // Invalidate the input description for pipelines.
302 mDirtyPackedInputs.set(attribIndex);
303
Frank Henigman67c388e2018-07-19 19:16:11 -0400304 RendererVk *renderer = contextVk->getRenderer();
Frank Henigmane4523822018-07-19 16:10:53 -0400305 bool releaseConversion = true;
Jamie Madill5a4c9322018-07-16 11:01:58 -0400306
Jamie Madilla56467e2018-04-11 16:19:41 -0400307 if (attrib.enabled)
308 {
Frank Henigman67c388e2018-07-19 19:16:11 -0400309 gl::Buffer *bufferGL = binding.getBuffer().get();
Frank Henigman419acc82018-06-24 19:57:31 -0400310 mCurrentArrayBufferFormats[attribIndex] = &renderer->getFormat(GetVertexFormatID(attrib));
Frank Henigmane4523822018-07-19 16:10:53 -0400311
Jamie Madilla56467e2018-04-11 16:19:41 -0400312 if (bufferGL)
313 {
Frank Henigmane4523822018-07-19 16:10:53 -0400314 BufferVk *bufferVk = vk::GetImpl(bufferGL);
315 unsigned componentSize =
316 mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes / attrib.size;
Frank Henigman419acc82018-06-24 19:57:31 -0400317
Frank Henigmane4523822018-07-19 16:10:53 -0400318 if (mCurrentArrayBufferFormats[attribIndex]->vertexLoadRequiresConversion ||
319 !BindingIsAligned(binding, componentSize))
320 {
Jamie Madilla064c272018-08-30 16:18:34 -0400321 mCurrentArrayBufferStrides[attribIndex] =
322 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
323
Frank Henigmane4523822018-07-19 16:10:53 -0400324 ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex));
325
Frank Henigmane4523822018-07-19 16:10:53 -0400326 mCurrentArrayBufferResources[attribIndex] = nullptr;
327 releaseConversion = false;
328 }
329 else
330 {
Jamie Madill2d03ff42018-09-27 15:04:26 -0400331 mCurrentArrayBufferResources[attribIndex] = &bufferVk->getBuffer();
332 mCurrentArrayBufferHandles[attribIndex] =
333 bufferVk->getBuffer().getBuffer().getHandle();
Frank Henigmane4523822018-07-19 16:10:53 -0400334 mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
335 mCurrentArrayBufferStrides[attribIndex] = binding.getStride();
336 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400337 }
338 else
339 {
340 mCurrentArrayBufferResources[attribIndex] = nullptr;
341 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
Luc Ferronfa5d84b2018-06-28 10:40:04 -0400342 mCurrentArrayBufferOffsets[attribIndex] = 0;
Frank Henigman419acc82018-06-24 19:57:31 -0400343 mCurrentArrayBufferStrides[attribIndex] =
Frank Henigmane4523822018-07-19 16:10:53 -0400344 mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
Jamie Madilla56467e2018-04-11 16:19:41 -0400345 }
Jamie Madilla56467e2018-04-11 16:19:41 -0400346 }
347 else
348 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400349 contextVk->invalidateDefaultAttribute(attribIndex);
350
351 // These will be filled out by the ContextVk.
352 mCurrentArrayBufferResources[attribIndex] = nullptr;
353 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
354 mCurrentArrayBufferOffsets[attribIndex] = 0;
355 mCurrentArrayBufferStrides[attribIndex] = 0;
356 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400357 &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
Jamie Madilla56467e2018-04-11 16:19:41 -0400358 }
Frank Henigmane4523822018-07-19 16:10:53 -0400359
360 if (releaseConversion)
361 ensureConversionReleased(renderer, attribIndex);
362
363 return angle::Result::Continue();
Jamie Madilla56467e2018-04-11 16:19:41 -0400364}
365
Frank Henigman419acc82018-06-24 19:57:31 -0400366void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400367{
Frank Henigman419acc82018-06-24 19:57:31 -0400368 updatePackedInputDescriptions();
Jamie Madill112a3a82018-01-23 13:04:06 -0500369 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400370}
371
Frank Henigman419acc82018-06-24 19:57:31 -0400372void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400373{
Jamie Madill112a3a82018-01-23 13:04:06 -0500374 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400375 {
376 return;
377 }
378
379 const auto &attribs = mState.getVertexAttributes();
380 const auto &bindings = mState.getVertexBindings();
381
Jamie Madill112a3a82018-01-23 13:04:06 -0500382 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400383 {
384 const auto &attrib = attribs[attribIndex];
385 const auto &binding = bindings[attrib.bindingIndex];
386 if (attrib.enabled)
387 {
Frank Henigman419acc82018-06-24 19:57:31 -0400388 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400389 }
390 else
391 {
Jamie Madill5a4c9322018-07-16 11:01:58 -0400392 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
393 bindingDesc.stride = 0;
394 bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
395
396 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
397 attribDesc.format = static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
398 attribDesc.location = static_cast<uint16_t>(attribIndex);
399 attribDesc.offset = 0;
Jamie Madillebf72992017-10-13 14:09:45 -0400400 }
401 }
402
Jamie Madill112a3a82018-01-23 13:04:06 -0500403 mDirtyPackedInputs.reset();
404}
405
Frank Henigman419acc82018-06-24 19:57:31 -0400406void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
Jamie Madill112a3a82018-01-23 13:04:06 -0500407 const gl::VertexBinding &binding,
408 const gl::VertexAttribute &attrib)
409{
410 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
411
Frank Henigman419acc82018-06-24 19:57:31 -0400412 bindingDesc.stride = static_cast<uint16_t>(mCurrentArrayBufferStrides[attribIndex]);
Jamie Madill112a3a82018-01-23 13:04:06 -0500413 bindingDesc.inputRate = static_cast<uint16_t>(
414 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
415
Frank Henigman419acc82018-06-24 19:57:31 -0400416 VkFormat vkFormat = mCurrentArrayBufferFormats[attribIndex]->vkBufferFormat;
Jamie Madill112a3a82018-01-23 13:04:06 -0500417 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
Frank Henigman8c379f32018-06-21 19:55:05 -0400418 if (vkFormat == VK_FORMAT_UNDEFINED)
419 {
Frank Henigman8c379f32018-06-21 19:55:05 -0400420 UNIMPLEMENTED();
421 }
Jamie Madill112a3a82018-01-23 13:04:06 -0500422
423 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
424 attribDesc.format = static_cast<uint16_t>(vkFormat);
425 attribDesc.location = static_cast<uint16_t>(attribIndex);
Luc Ferronfa5d84b2018-06-28 10:40:04 -0400426 attribDesc.offset = static_cast<uint32_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,
430 const gl::DrawCallParams &drawCallParams)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400431{
Jamie Madill21061022018-07-12 23:56:30 -0400432 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill88fc6da2018-08-30 16:18:36 -0400433 const gl::AttributesMask &clientAttribs = context->getStateCache().getActiveClientAttribsMask();
Jamie Madill21061022018-07-12 23:56:30 -0400434
Jamie Madill88fc6da2018-08-30 16:18:36 -0400435 ASSERT(clientAttribs.any());
436 ANGLE_TRY_HANDLE(context, drawCallParams.ensureIndexRangeResolved(context));
437
438 mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
439
440 const auto &attribs = mState.getVertexAttributes();
441 const auto &bindings = mState.getVertexBindings();
442
443 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
444 // un-interleaved, wasting space and copying time. Consider improving on that.
445 for (size_t attribIndex : clientAttribs)
446 {
447 const gl::VertexAttribute &attrib = attribs[attribIndex];
448 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
449 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
450
451 const size_t bytesToAllocate =
452 (drawCallParams.firstVertex() + drawCallParams.vertexCount()) *
453 mCurrentArrayBufferStrides[attribIndex];
454 const uint8_t *src = static_cast<const uint8_t *>(attrib.pointer) +
455 drawCallParams.firstVertex() * binding.getStride();
456
457 size_t destOffset = drawCallParams.firstVertex() * mCurrentArrayBufferStrides[attribIndex];
458
459 // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
460 // We allocate space for firstVertex() + vertexCount() so indexing will work. If we
461 // don't start at zero all the indices will be off.
462 // TODO(fjhenigman): See if we can account for indices being off by adjusting the
463 // offset, thus avoiding wasted memory.
464 ANGLE_TRY(StreamVertexData(contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset,
465 drawCallParams.vertexCount(), binding.getStride(),
466 mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
467 &mCurrentArrayBufferHandles[attribIndex],
468 &mCurrentArrayBufferOffsets[attribIndex]));
469 }
470
471 return angle::Result::Continue();
472}
473
474angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk,
475 const gl::DrawCallParams &drawCallParams)
476{
477 if (drawCallParams.isDrawElements())
478 {
479 // Handle GL_LINE_LOOP drawElements.
480 if (mDirtyLineLoopTranslation)
481 {
482 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
Jamie Madill88fc6da2018-08-30 16:18:36 -0400483
484 if (!elementArrayBuffer)
485 {
Frank Henigman85c4b432018-09-19 23:35:00 -0400486 ANGLE_TRY(mLineLoopHelper.streamIndices(
487 contextVk, drawCallParams.type(), drawCallParams.indexCount(),
488 reinterpret_cast<const uint8_t *>(drawCallParams.indices()),
489 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400490 }
491 else
492 {
493 // When using an element array buffer, 'indices' is an offset to the first element.
494 intptr_t offset = reinterpret_cast<intptr_t>(drawCallParams.indices());
495 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
496 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Frank Henigman85c4b432018-09-19 23:35:00 -0400497 contextVk, elementArrayBufferVk, drawCallParams.type(),
498 drawCallParams.indexCount(), offset, &mCurrentElementArrayBufferHandle,
499 &mCurrentElementArrayBufferOffset));
Jamie Madill88fc6da2018-08-30 16:18:36 -0400500 }
501 }
502
503 // If we've had a drawArrays call with a line loop before, we want to make sure this is
504 // invalidated the next time drawArrays is called since we use the same index buffer for
505 // both calls.
506 mLineLoopBufferFirstIndex.reset();
507 mLineLoopBufferLastIndex.reset();
508 return angle::Result::Continue();
509 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400510
Jamie Madill18e323a2018-05-11 16:54:17 -0400511 // Note: Vertex indexes can be arbitrarily large.
512 uint32_t clampedVertexCount = drawCallParams.getClampedVertexCount<uint32_t>();
513
Jamie Madillc3755fc2018-04-05 08:39:13 -0400514 // Handle GL_LINE_LOOP drawArrays.
Jamie Madill18e323a2018-05-11 16:54:17 -0400515 size_t lastVertex = static_cast<size_t>(drawCallParams.firstVertex() + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400516 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
517 mLineLoopBufferFirstIndex != drawCallParams.firstVertex() ||
518 mLineLoopBufferLastIndex != lastVertex)
519 {
Jamie Madill21061022018-07-12 23:56:30 -0400520 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(contextVk, drawCallParams,
Jamie Madill22f12fe2018-04-08 14:23:40 -0400521 &mCurrentElementArrayBufferHandle,
522 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400523
524 mLineLoopBufferFirstIndex = drawCallParams.firstVertex();
525 mLineLoopBufferLastIndex = lastVertex;
526 }
527
Jamie Madill88fc6da2018-08-30 16:18:36 -0400528 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400529}
530
Jamie Madill88fc6da2018-08-30 16:18:36 -0400531angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
532 const gl::DrawCallParams &drawCallParams)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400533{
Jamie Madill88fc6da2018-08-30 16:18:36 -0400534 ASSERT(drawCallParams.isDrawElements());
535 ASSERT(drawCallParams.mode() != gl::PrimitiveMode::LineLoop);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400536
Luc Ferron6ed167a2018-06-13 13:45:55 -0400537 gl::Buffer *glBuffer = mState.getElementArrayBuffer().get();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400538
Jamie Madill88fc6da2018-08-30 16:18:36 -0400539 if (!glBuffer)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400540 {
Jamie Madill253038d2018-08-30 16:18:35 -0400541 ANGLE_TRY(streamIndexData(contextVk, drawCallParams.type(), drawCallParams.indexCount(),
542 drawCallParams.indices(), &mDynamicIndexData));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400543 }
Jamie Madill88fc6da2018-08-30 16:18:36 -0400544 else
Jamie Madillc3755fc2018-04-05 08:39:13 -0400545 {
Frank Henigman9d84ccb2018-09-12 18:09:02 -0400546 // Needed before reading buffer or we could get stale data.
547 ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
548
Jamie Madill88fc6da2018-08-30 16:18:36 -0400549 ASSERT(drawCallParams.type() == GL_UNSIGNED_BYTE);
550 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
551 // memory to a GLushort.
552 BufferVk *bufferVk = vk::GetImpl(glBuffer);
553 void *srcDataMapping = nullptr;
554 ASSERT(!glBuffer->isMapped());
555 ANGLE_TRY(bufferVk->mapImpl(contextVk, &srcDataMapping));
556 uint8_t *srcData = static_cast<uint8_t *>(srcDataMapping);
557 intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(drawCallParams.indices());
558 srcData += offsetIntoSrcData;
Jamie Madill253038d2018-08-30 16:18:35 -0400559
Jamie Madill88fc6da2018-08-30 16:18:36 -0400560 ANGLE_TRY(streamIndexData(contextVk, drawCallParams.type(),
561 static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData,
562 srcData, &mTranslatedByteIndexData));
Luc Ferron6ed167a2018-06-13 13:45:55 -0400563
Jamie Madill88fc6da2018-08-30 16:18:36 -0400564 ANGLE_TRY(bufferVk->unmapImpl(contextVk));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400565 }
566
Jamie Madill88fc6da2018-08-30 16:18:36 -0400567 return angle::Result::Continue();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400568}
Jamie Madill5a4c9322018-07-16 11:01:58 -0400569
570void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
571 size_t attribIndex,
572 VkBuffer bufferHandle,
573 uint32_t offset)
574{
575 if (!mState.getEnabledAttributesMask().test(attribIndex))
576 {
577 mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
578 mCurrentArrayBufferOffsets[attribIndex] = offset;
579 mCurrentArrayBufferResources[attribIndex] = nullptr;
580 mCurrentArrayBufferStrides[attribIndex] = 0;
581 mCurrentArrayBufferFormats[attribIndex] =
Jamie Madillba365932018-07-18 17:23:46 -0400582 &renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED);
Jamie Madill5a4c9322018-07-16 11:01:58 -0400583 mDirtyPackedInputs.set(attribIndex);
584 }
585}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400586} // namespace rx