blob: 0b37d30e23a670fe0cf953272633f7d45070b8fc [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;
28} // anonymous namespace
Jamie Madill9e54b5a2016-05-25 12:57:39 -040029
Luc Ferrona9ab0f32018-05-17 17:03:55 -040030VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *renderer)
Jamie Madillbd159f02017-10-09 19:39:06 -040031 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050032 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050033 mCurrentArrayBufferOffsets{},
Jamie Madillda854a22017-11-30 17:24:21 -050034 mCurrentArrayBufferResources{},
Jamie Madillc3755fc2018-04-05 08:39:13 -040035 mCurrentElementArrayBufferHandle(VK_NULL_HANDLE),
36 mCurrentElementArrayBufferOffset(0),
37 mCurrentElementArrayBufferResource(nullptr),
38 mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
39 mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
Luc Ferrona9ab0f32018-05-17 17:03:55 -040040 mLineLoopHelper(renderer),
Jamie Madillb8e39662018-04-04 11:41:42 -040041 mDirtyLineLoopTranslation(true),
Jamie Madillc3755fc2018-04-05 08:39:13 -040042 mVertexBuffersDirty(false),
Luc Ferron49aacad2018-06-12 08:33:59 -040043 mIndexBufferDirty(false),
44 mLastIndexBufferOffset(0)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040045{
Jamie Madillda854a22017-11-30 17:24:21 -050046 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -050047 mCurrentArrayBufferOffsets.fill(0);
Jamie Madillda854a22017-11-30 17:24:21 -050048 mCurrentArrayBufferResources.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -050049
50 mPackedInputBindings.fill({0, 0});
51 mPackedInputAttributes.fill({0, 0, 0});
Jamie Madillc3755fc2018-04-05 08:39:13 -040052
Luc Ferrona9ab0f32018-05-17 17:03:55 -040053 mDynamicVertexData.init(1, renderer);
54 mDynamicIndexData.init(1, renderer);
Jamie Madill9e54b5a2016-05-25 12:57:39 -040055}
56
Jamie Madillacf2f3a2017-11-21 19:22:44 -050057VertexArrayVk::~VertexArrayVk()
58{
59}
60
Jamie Madill4928b7c2017-06-20 12:57:39 -040061void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040062{
Jamie Madillc3755fc2018-04-05 08:39:13 -040063 VkDevice device = vk::GetImpl(context)->getRenderer()->getDevice();
Jamie Madillc3755fc2018-04-05 08:39:13 -040064 mDynamicVertexData.destroy(device);
65 mDynamicIndexData.destroy(device);
Jamie Madill22f12fe2018-04-08 14:23:40 -040066 mLineLoopHelper.destroy(device);
Jamie Madill9e54b5a2016-05-25 12:57:39 -040067}
68
Jamie Madillc3755fc2018-04-05 08:39:13 -040069gl::Error VertexArrayVk::streamVertexData(RendererVk *renderer,
70 const gl::AttributesMask &attribsToStream,
Jamie Madill32fd63b2018-03-31 11:20:35 -040071 const gl::DrawCallParams &drawCallParams)
Frank Henigman17448952017-01-05 15:48:26 -050072{
Jamie Madillc3755fc2018-04-05 08:39:13 -040073 ASSERT(!attribsToStream.none());
74
Jamie Madillbcef3222018-04-13 15:19:11 -040075 const auto &attribs = mState.getVertexAttributes();
76 const auto &bindings = mState.getVertexBindings();
Frank Henigman17448952017-01-05 15:48:26 -050077
Jamie Madill32fd63b2018-03-31 11:20:35 -040078 const size_t lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
79
Frank Henigman17448952017-01-05 15:48:26 -050080 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
81 // un-interleaved, wasting space and copying time. Consider improving on that.
Jamie Madillb8e39662018-04-04 11:41:42 -040082 for (size_t attribIndex : attribsToStream)
Frank Henigman17448952017-01-05 15:48:26 -050083 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050084 const gl::VertexAttribute &attrib = attribs[attribIndex];
85 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
86 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
Frank Henigman17448952017-01-05 15:48:26 -050087
Frank Henigman6dd4a922018-03-02 16:35:13 -050088 // TODO(fjhenigman): Work with more formats than just GL_FLOAT.
89 if (attrib.type != GL_FLOAT)
Frank Henigman17448952017-01-05 15:48:26 -050090 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050091 UNIMPLEMENTED();
92 return gl::InternalError();
Frank Henigman17448952017-01-05 15:48:26 -050093 }
Frank Henigman6dd4a922018-03-02 16:35:13 -050094
95 // Only [firstVertex, lastVertex] is needed by the upcoming draw so that
96 // is all we copy, but we allocate space for [0, lastVertex] so indexing
97 // will work. If we don't start at zero all the indices will be off.
98 // TODO(fjhenigman): See if we can account for indices being off by adjusting
99 // the offset, thus avoiding wasted memory.
Jamie Madill32fd63b2018-03-31 11:20:35 -0400100 const size_t firstByte = drawCallParams.firstVertex() * binding.getStride();
Frank Henigman6dd4a922018-03-02 16:35:13 -0500101 const size_t lastByte =
102 lastVertex * binding.getStride() + gl::ComputeVertexAttributeTypeSize(attrib);
Jamie Madill493f9572018-05-24 19:52:15 -0400103 uint8_t *dst = nullptr;
Luc Ferron7a06ac12018-03-15 10:17:04 -0400104 uint32_t offset = 0;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400105 ANGLE_TRY(mDynamicVertexData.allocate(
106 renderer, lastByte, &dst, &mCurrentArrayBufferHandles[attribIndex], &offset, nullptr));
Luc Ferron7a06ac12018-03-15 10:17:04 -0400107 mCurrentArrayBufferOffsets[attribIndex] = static_cast<VkDeviceSize>(offset);
Frank Henigman6dd4a922018-03-02 16:35:13 -0500108 memcpy(dst + firstByte, static_cast<const uint8_t *>(attrib.pointer) + firstByte,
109 lastByte - firstByte);
Frank Henigman17448952017-01-05 15:48:26 -0500110 }
111
Jamie Madillc3755fc2018-04-05 08:39:13 -0400112 ANGLE_TRY(mDynamicVertexData.flush(renderer->getDevice()));
Luc Ferron61859812018-05-09 14:17:39 -0400113 mDynamicVertexData.releaseRetainedBuffers(renderer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400114 return gl::NoError();
115}
116
117gl::Error VertexArrayVk::streamIndexData(RendererVk *renderer,
118 const gl::DrawCallParams &drawCallParams)
119{
120 ASSERT(!mState.getElementArrayBuffer().get());
121
122 uint32_t offset = 0;
123
124 const GLsizei amount = sizeof(GLushort) * drawCallParams.indexCount();
125 GLubyte *dst = nullptr;
126
127 ANGLE_TRY(mDynamicIndexData.allocate(renderer, amount, &dst, &mCurrentElementArrayBufferHandle,
128 &offset, nullptr));
129 if (drawCallParams.type() == GL_UNSIGNED_BYTE)
130 {
131 // Unsigned bytes don't have direct support in Vulkan so we have to expand the
132 // memory to a GLushort.
133 const GLubyte *in = static_cast<const GLubyte *>(drawCallParams.indices());
134 GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
135 for (GLsizei index = 0; index < drawCallParams.indexCount(); index++)
136 {
137 expandedDst[index] = static_cast<GLushort>(in[index]);
138 }
139 }
140 else
141 {
142 memcpy(dst, drawCallParams.indices(), amount);
143 }
144 ANGLE_TRY(mDynamicIndexData.flush(renderer->getDevice()));
Luc Ferron61859812018-05-09 14:17:39 -0400145 mDynamicIndexData.releaseRetainedBuffers(renderer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400146 mCurrentElementArrayBufferOffset = offset;
Frank Henigman17448952017-01-05 15:48:26 -0500147 return gl::NoError();
148}
149
Jamie Madilla56467e2018-04-11 16:19:41 -0400150#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
151 case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
152 syncDirtyAttrib(attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
153 invalidatePipeline = true; \
154 break;
155
156#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
157 case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
158 syncDirtyAttrib(attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
159 invalidatePipeline = true; \
160 break;
161
162#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
163 case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
164 break;
165
Frank Henigman0af5b862018-03-27 20:19:33 -0400166gl::Error VertexArrayVk::syncState(const gl::Context *context,
167 const gl::VertexArray::DirtyBits &dirtyBits,
168 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
169 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400170{
171 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400172
Jamie Madillc3755fc2018-04-05 08:39:13 -0400173 bool invalidatePipeline = false;
174
Jamie Madillbd159f02017-10-09 19:39:06 -0400175 // Invalidate current pipeline.
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500176 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madillbd159f02017-10-09 19:39:06 -0400177
178 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
179 // TODO(jmadill): Handle buffer storage changes.
180 const auto &attribs = mState.getVertexAttributes();
181 const auto &bindings = mState.getVertexBindings();
182
Jamie Madill09463932018-04-04 05:26:59 -0400183 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400184 {
Jamie Madill09463932018-04-04 05:26:59 -0400185 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500186 {
Jamie Madill09463932018-04-04 05:26:59 -0400187 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500188 {
Jamie Madill09463932018-04-04 05:26:59 -0400189 gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
190 if (bufferGL)
191 {
Jamie Madillc3755fc2018-04-05 08:39:13 -0400192 BufferVk *bufferVk = vk::GetImpl(bufferGL);
193 mCurrentElementArrayBufferResource = bufferVk;
194 mCurrentElementArrayBufferHandle = bufferVk->getVkBuffer().getHandle();
Jamie Madill09463932018-04-04 05:26:59 -0400195 }
196 else
197 {
198 mCurrentElementArrayBufferResource = nullptr;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400199 mCurrentElementArrayBufferHandle = VK_NULL_HANDLE;
Jamie Madill09463932018-04-04 05:26:59 -0400200 }
Luc Ferron387b3b32018-05-28 10:11:57 -0400201
202 mCurrentElementArrayBufferOffset = 0;
203 mLineLoopBufferFirstIndex.reset();
204 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400205 mIndexBufferDirty = true;
206 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400207 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500208 }
Jamie Madill09463932018-04-04 05:26:59 -0400209
210 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Jamie Madillc3755fc2018-04-05 08:39:13 -0400211 mLineLoopBufferFirstIndex.reset();
212 mLineLoopBufferLastIndex.reset();
Jamie Madillb8e39662018-04-04 11:41:42 -0400213 mDirtyLineLoopTranslation = true;
Jamie Madill09463932018-04-04 05:26:59 -0400214 break;
215
Jamie Madilla56467e2018-04-11 16:19:41 -0400216 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
217 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
218 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
219
Jamie Madill09463932018-04-04 05:26:59 -0400220 default:
Jamie Madilla56467e2018-04-11 16:19:41 -0400221 UNREACHABLE();
Jamie Madill09463932018-04-04 05:26:59 -0400222 break;
Jamie Madillbd159f02017-10-09 19:39:06 -0400223 }
224 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400225
Jamie Madillc3755fc2018-04-05 08:39:13 -0400226 if (invalidatePipeline)
227 {
228 mVertexBuffersDirty = true;
229 contextVk->invalidateCurrentPipeline();
230 }
231
Frank Henigman0af5b862018-03-27 20:19:33 -0400232 return gl::NoError();
Jamie Madillbd159f02017-10-09 19:39:06 -0400233}
234
Jamie Madilla56467e2018-04-11 16:19:41 -0400235void VertexArrayVk::syncDirtyAttrib(const gl::VertexAttribute &attrib,
236 const gl::VertexBinding &binding,
237 size_t attribIndex)
238{
239 // Invalidate the input description for pipelines.
240 mDirtyPackedInputs.set(attribIndex);
241
242 if (attrib.enabled)
243 {
244 gl::Buffer *bufferGL = binding.getBuffer().get();
245
246 if (bufferGL)
247 {
248 BufferVk *bufferVk = vk::GetImpl(bufferGL);
249 mCurrentArrayBufferResources[attribIndex] = bufferVk;
250 mCurrentArrayBufferHandles[attribIndex] = bufferVk->getVkBuffer().getHandle();
Jamie Madilla56467e2018-04-11 16:19:41 -0400251 }
252 else
253 {
254 mCurrentArrayBufferResources[attribIndex] = nullptr;
255 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
Jamie Madilla56467e2018-04-11 16:19:41 -0400256 }
257 // TODO(jmadill): Offset handling. Assume zero for now.
258 mCurrentArrayBufferOffsets[attribIndex] = 0;
259 }
260 else
261 {
Jamie Madilla56467e2018-04-11 16:19:41 -0400262 UNIMPLEMENTED();
263 }
264}
265
Jamie Madillda854a22017-11-30 17:24:21 -0500266const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const
Jamie Madillbd159f02017-10-09 19:39:06 -0400267{
Jamie Madillda854a22017-11-30 17:24:21 -0500268 return mCurrentArrayBufferHandles;
Jamie Madillbd159f02017-10-09 19:39:06 -0400269}
270
Frank Henigman17448952017-01-05 15:48:26 -0500271const gl::AttribArray<VkDeviceSize> &VertexArrayVk::getCurrentArrayBufferOffsets() const
272{
273 return mCurrentArrayBufferOffsets;
274}
275
Jamie Madill316c6062018-05-29 10:49:45 -0400276void VertexArrayVk::updateArrayBufferReadDependencies(vk::CommandGraphResource *drawFramebuffer,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400277 const gl::AttributesMask &activeAttribsMask,
278 Serial serial)
Jamie Madillbd159f02017-10-09 19:39:06 -0400279{
Jamie Madillda854a22017-11-30 17:24:21 -0500280 // Handle the bound array buffers.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400281 for (size_t attribIndex : activeAttribsMask)
Jamie Madillbd159f02017-10-09 19:39:06 -0400282 {
Frank Henigman17448952017-01-05 15:48:26 -0500283 if (mCurrentArrayBufferResources[attribIndex])
Jamie Madill316c6062018-05-29 10:49:45 -0400284 mCurrentArrayBufferResources[attribIndex]->addReadDependency(drawFramebuffer);
Jamie Madillda854a22017-11-30 17:24:21 -0500285 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400286}
Jamie Madillda854a22017-11-30 17:24:21 -0500287
Jamie Madill316c6062018-05-29 10:49:45 -0400288void VertexArrayVk::updateElementArrayBufferReadDependency(
289 vk::CommandGraphResource *drawFramebuffer,
290 Serial serial)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400291{
Jamie Madillda854a22017-11-30 17:24:21 -0500292 // Handle the bound element array buffer.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400293 if (mCurrentElementArrayBufferResource)
Jamie Madillda854a22017-11-30 17:24:21 -0500294 {
Jamie Madill316c6062018-05-29 10:49:45 -0400295 mCurrentElementArrayBufferResource->addReadDependency(drawFramebuffer);
Jamie Madillbd159f02017-10-09 19:39:06 -0400296 }
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400297}
298
Jamie Madill112a3a82018-01-23 13:04:06 -0500299void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400300{
Jamie Madill112a3a82018-01-23 13:04:06 -0500301 updatePackedInputDescriptions();
302 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400303}
304
Jamie Madill112a3a82018-01-23 13:04:06 -0500305void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400306{
Jamie Madill112a3a82018-01-23 13:04:06 -0500307 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400308 {
309 return;
310 }
311
312 const auto &attribs = mState.getVertexAttributes();
313 const auto &bindings = mState.getVertexBindings();
314
Jamie Madill112a3a82018-01-23 13:04:06 -0500315 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400316 {
317 const auto &attrib = attribs[attribIndex];
318 const auto &binding = bindings[attrib.bindingIndex];
319 if (attrib.enabled)
320 {
Jamie Madill112a3a82018-01-23 13:04:06 -0500321 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400322 }
323 else
324 {
325 UNIMPLEMENTED();
326 }
327 }
328
Jamie Madill112a3a82018-01-23 13:04:06 -0500329 mDirtyPackedInputs.reset();
330}
331
332void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
333 const gl::VertexBinding &binding,
334 const gl::VertexAttribute &attrib)
335{
336 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
337
338 size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
339 ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
340
Frank Henigmana8e868f2018-01-28 23:32:25 -0500341 bindingDesc.stride = static_cast<uint16_t>(binding.getStride());
Jamie Madill112a3a82018-01-23 13:04:06 -0500342 bindingDesc.inputRate = static_cast<uint16_t>(
343 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
344
345 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
346 VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
347 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
348
349 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
350 attribDesc.format = static_cast<uint16_t>(vkFormat);
351 attribDesc.location = static_cast<uint16_t>(attribIndex);
352 attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
Jamie Madillebf72992017-10-13 14:09:45 -0400353}
354
Jamie Madillc3755fc2018-04-05 08:39:13 -0400355gl::Error VertexArrayVk::drawArrays(const gl::Context *context,
356 RendererVk *renderer,
357 const gl::DrawCallParams &drawCallParams,
Jamie Madill316c6062018-05-29 10:49:45 -0400358 vk::CommandBuffer *commandBuffer,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400359 bool newCommandBuffer)
360{
Jamie Madillc3755fc2018-04-05 08:39:13 -0400361 ASSERT(commandBuffer->valid());
362
Jamie Madill316c6062018-05-29 10:49:45 -0400363 ANGLE_TRY(onDraw(context, renderer, drawCallParams, commandBuffer, newCommandBuffer));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400364
Jamie Madill18e323a2018-05-11 16:54:17 -0400365 // Note: Vertex indexes can be arbitrarily large.
366 uint32_t clampedVertexCount = drawCallParams.getClampedVertexCount<uint32_t>();
367
Jamie Madill493f9572018-05-24 19:52:15 -0400368 if (drawCallParams.mode() != gl::PrimitiveMode::LineLoop)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400369 {
Jamie Madill18e323a2018-05-11 16:54:17 -0400370 commandBuffer->draw(clampedVertexCount, 1, drawCallParams.firstVertex(), 0);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400371 return gl::NoError();
372 }
373
374 // Handle GL_LINE_LOOP drawArrays.
Jamie Madill18e323a2018-05-11 16:54:17 -0400375 size_t lastVertex = static_cast<size_t>(drawCallParams.firstVertex() + clampedVertexCount);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400376 if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
377 mLineLoopBufferFirstIndex != drawCallParams.firstVertex() ||
378 mLineLoopBufferLastIndex != lastVertex)
379 {
Jamie Madill22f12fe2018-04-08 14:23:40 -0400380 ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(renderer, drawCallParams,
381 &mCurrentElementArrayBufferHandle,
382 &mCurrentElementArrayBufferOffset));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400383
384 mLineLoopBufferFirstIndex = drawCallParams.firstVertex();
385 mLineLoopBufferLastIndex = lastVertex;
386 }
387
388 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
389 mCurrentElementArrayBufferOffset, VK_INDEX_TYPE_UINT32);
390
Jamie Madill18e323a2018-05-11 16:54:17 -0400391 vk::LineLoopHelper::Draw(clampedVertexCount, commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400392
393 return gl::NoError();
394}
395
396gl::Error VertexArrayVk::drawElements(const gl::Context *context,
397 RendererVk *renderer,
398 const gl::DrawCallParams &drawCallParams,
Jamie Madill316c6062018-05-29 10:49:45 -0400399 vk::CommandBuffer *commandBuffer,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400400 bool newCommandBuffer)
401{
Jamie Madillc3755fc2018-04-05 08:39:13 -0400402 ASSERT(commandBuffer->valid());
403
Jamie Madill493f9572018-05-24 19:52:15 -0400404 if (drawCallParams.mode() != gl::PrimitiveMode::LineLoop)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400405 {
Jamie Madill316c6062018-05-29 10:49:45 -0400406 ANGLE_TRY(
407 onIndexedDraw(context, renderer, drawCallParams, commandBuffer, newCommandBuffer));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400408 commandBuffer->drawIndexed(drawCallParams.indexCount(), 1, 0, 0, 0);
409 return gl::NoError();
410 }
411
412 // Handle GL_LINE_LOOP drawElements.
Jamie Madillb8e39662018-04-04 11:41:42 -0400413 if (mDirtyLineLoopTranslation)
414 {
Luc Ferrona9120462018-04-12 13:11:03 -0400415 gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
416 VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
417
418 if (!elementArrayBuffer)
419 {
420 ANGLE_TRY(mLineLoopHelper.getIndexBufferForClientElementArray(
Luc Ferron3e313802018-06-11 14:44:33 -0400421 renderer, drawCallParams, &mCurrentElementArrayBufferHandle,
422 &mCurrentElementArrayBufferOffset));
Luc Ferrona9120462018-04-12 13:11:03 -0400423 }
424 else
425 {
Luc Ferrona4fa9c22018-04-13 07:00:56 -0400426 // When using an element array buffer, 'indices' is an offset to the first element.
427 intptr_t offset = reinterpret_cast<intptr_t>(drawCallParams.indices());
Luc Ferrona9120462018-04-12 13:11:03 -0400428 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
429 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
Luc Ferrona4fa9c22018-04-13 07:00:56 -0400430 renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(), offset,
Luc Ferrona9120462018-04-12 13:11:03 -0400431 &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
432 }
Jamie Madillb8e39662018-04-04 11:41:42 -0400433 }
Jamie Madillc3755fc2018-04-05 08:39:13 -0400434
Jamie Madill316c6062018-05-29 10:49:45 -0400435 ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, commandBuffer, newCommandBuffer));
Jamie Madill22f12fe2018-04-08 14:23:40 -0400436 vk::LineLoopHelper::Draw(drawCallParams.indexCount(), commandBuffer);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400437
438 return gl::NoError();
439}
440
441gl::Error VertexArrayVk::onDraw(const gl::Context *context,
442 RendererVk *renderer,
443 const gl::DrawCallParams &drawCallParams,
Jamie Madill316c6062018-05-29 10:49:45 -0400444 vk::CommandBuffer *commandBuffer,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400445 bool newCommandBuffer)
446{
447 const gl::State &state = context->getGLState();
448 const gl::Program *programGL = state.getProgram();
Jamie Madillbcef3222018-04-13 15:19:11 -0400449 const gl::AttributesMask &clientAttribs = mState.getEnabledClientMemoryAttribsMask();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400450 const gl::AttributesMask &activeAttribs = programGL->getActiveAttribLocationsMask();
451 uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation();
452
Jamie Madillbcef3222018-04-13 15:19:11 -0400453 if (clientAttribs.any())
Jamie Madillc3755fc2018-04-05 08:39:13 -0400454 {
Jamie Madillbcef3222018-04-13 15:19:11 -0400455 const gl::AttributesMask &attribsToStream = (clientAttribs & activeAttribs);
Jamie Madillc3755fc2018-04-05 08:39:13 -0400456 if (attribsToStream.any())
457 {
458 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
459 ANGLE_TRY(streamVertexData(renderer, attribsToStream, drawCallParams));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400460 commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
461 mCurrentArrayBufferOffsets.data());
462 }
463 }
464 else if (mVertexBuffersDirty || newCommandBuffer)
465 {
Luc Ferron44162472018-04-06 13:20:45 -0400466 if (maxAttrib > 0)
467 {
Luc Ferron44162472018-04-06 13:20:45 -0400468 commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
469 mCurrentArrayBufferOffsets.data());
Jamie Madill316c6062018-05-29 10:49:45 -0400470
471 vk::CommandGraphResource *drawFramebuffer = vk::GetImpl(state.getDrawFramebuffer());
472 updateArrayBufferReadDependencies(drawFramebuffer, activeAttribs,
Luc Ferron44162472018-04-06 13:20:45 -0400473 renderer->getCurrentQueueSerial());
474 }
Luc Ferronc1e02682018-04-11 11:02:55 -0400475
Jamie Madillc3755fc2018-04-05 08:39:13 -0400476 mVertexBuffersDirty = false;
Luc Ferronc1e02682018-04-11 11:02:55 -0400477
478 // This forces the binding to happen if we follow a drawElement call from a drawArrays call.
479 mIndexBufferDirty = true;
Luc Ferron983c4292018-04-10 13:05:45 -0400480
481 // If we've had a drawElements call with a line loop before, we want to make sure this is
482 // invalidated the next time drawElements is called since we use the same index buffer for
483 // both calls.
484 mDirtyLineLoopTranslation = true;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400485 }
486
487 return gl::NoError();
488}
489
490gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
491 RendererVk *renderer,
492 const gl::DrawCallParams &drawCallParams,
Jamie Madill316c6062018-05-29 10:49:45 -0400493 vk::CommandBuffer *commandBuffer,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400494 bool newCommandBuffer)
495{
Jamie Madill316c6062018-05-29 10:49:45 -0400496 ANGLE_TRY(onDraw(context, renderer, drawCallParams, commandBuffer, newCommandBuffer));
Luc Ferron49aacad2018-06-12 08:33:59 -0400497 bool isLineLoop = drawCallParams.mode() == gl::PrimitiveMode::LineLoop;
498 uintptr_t offset = mState.getElementArrayBuffer().get() && !isLineLoop
499 ? reinterpret_cast<uintptr_t>(drawCallParams.indices())
500 : 0;
Jamie Madillc3755fc2018-04-05 08:39:13 -0400501
Luc Ferron49aacad2018-06-12 08:33:59 -0400502 if (!mState.getElementArrayBuffer().get() && !isLineLoop)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400503 {
504 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
505 ANGLE_TRY(streamIndexData(renderer, drawCallParams));
Jamie Madillc3755fc2018-04-05 08:39:13 -0400506 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
507 mCurrentElementArrayBufferOffset,
508 gl_vk::GetIndexType(drawCallParams.type()));
509 }
Luc Ferron49aacad2018-06-12 08:33:59 -0400510 else if (mIndexBufferDirty || newCommandBuffer || offset != mLastIndexBufferOffset)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400511 {
Luc Ferron3e313802018-06-11 14:44:33 -0400512 if (drawCallParams.type() == GL_UNSIGNED_BYTE &&
513 drawCallParams.mode() != gl::PrimitiveMode::LineLoop)
Jamie Madillc3755fc2018-04-05 08:39:13 -0400514 {
Luc Ferron3e313802018-06-11 14:44:33 -0400515 // TODO(fjhenigman): Index format translation for non line-loop calls.
Jamie Madillc3755fc2018-04-05 08:39:13 -0400516 UNIMPLEMENTED();
517 return gl::InternalError()
518 << "Unsigned byte translation is not implemented for indices in a buffer object";
519 }
520
Jamie Madillc3755fc2018-04-05 08:39:13 -0400521 commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
Luc Ferron49aacad2018-06-12 08:33:59 -0400522 mCurrentElementArrayBufferOffset + offset,
Jamie Madillc3755fc2018-04-05 08:39:13 -0400523 gl_vk::GetIndexType(drawCallParams.type()));
Luc Ferron49aacad2018-06-12 08:33:59 -0400524 mLastIndexBufferOffset = offset;
Jamie Madill316c6062018-05-29 10:49:45 -0400525
526 const gl::State &glState = context->getGLState();
527 vk::CommandGraphResource *drawFramebuffer = vk::GetImpl(glState.getDrawFramebuffer());
528 updateElementArrayBufferReadDependency(drawFramebuffer, renderer->getCurrentQueueSerial());
Jamie Madillc3755fc2018-04-05 08:39:13 -0400529 mIndexBufferDirty = false;
Luc Ferron983c4292018-04-10 13:05:45 -0400530
531 // If we've had a drawArrays call with a line loop before, we want to make sure this is
532 // invalidated the next time drawArrays is called since we use the same index buffer for
533 // both calls.
534 mLineLoopBufferFirstIndex.reset();
535 mLineLoopBufferLastIndex.reset();
Jamie Madillc3755fc2018-04-05 08:39:13 -0400536 }
537
538 return gl::NoError();
539}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400540} // namespace rx