blob: df7bf21fccd6d34f8eb5c699e87cff327b32fa49 [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 Madill3c424b42018-01-19 12:35:09 -050018#include "libANGLE/renderer/vulkan/vk_format_utils.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040019
Jamie Madill9e54b5a2016-05-25 12:57:39 -040020namespace rx
21{
22
Jamie Madillbd159f02017-10-09 19:39:06 -040023VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state)
24 : VertexArrayImpl(state),
Jamie Madillda854a22017-11-30 17:24:21 -050025 mCurrentArrayBufferHandles{},
Frank Henigman17448952017-01-05 15:48:26 -050026 mCurrentArrayBufferOffsets{},
Jamie Madillda854a22017-11-30 17:24:21 -050027 mCurrentArrayBufferResources{},
Jamie Madill112a3a82018-01-23 13:04:06 -050028 mCurrentElementArrayBufferResource(nullptr)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040029{
Jamie Madillda854a22017-11-30 17:24:21 -050030 mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
Frank Henigman17448952017-01-05 15:48:26 -050031 mCurrentArrayBufferOffsets.fill(0);
Jamie Madillda854a22017-11-30 17:24:21 -050032 mCurrentArrayBufferResources.fill(nullptr);
Jamie Madill112a3a82018-01-23 13:04:06 -050033
34 mPackedInputBindings.fill({0, 0});
35 mPackedInputAttributes.fill({0, 0, 0});
Jamie Madill9e54b5a2016-05-25 12:57:39 -040036}
37
Jamie Madillacf2f3a2017-11-21 19:22:44 -050038VertexArrayVk::~VertexArrayVk()
39{
40}
41
Jamie Madill4928b7c2017-06-20 12:57:39 -040042void VertexArrayVk::destroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040043{
44}
45
Jamie Madill32fd63b2018-03-31 11:20:35 -040046gl::AttributesMask VertexArrayVk::getAttribsToStream(const gl::Context *context) const
Frank Henigmana53d0e12018-02-13 00:06:06 -050047{
48 const gl::Program *programGL = context->getGLState().getProgram();
49 return mClientMemoryAttribs & programGL->getActiveAttribLocationsMask();
50}
51
Jamie Madill32fd63b2018-03-31 11:20:35 -040052gl::Error VertexArrayVk::streamVertexData(const gl::Context *context,
Jamie Madillf3614372018-03-31 14:19:14 -040053 DynamicBuffer *dynamicBuffer,
Jamie Madill32fd63b2018-03-31 11:20:35 -040054 const gl::DrawCallParams &drawCallParams)
Frank Henigman17448952017-01-05 15:48:26 -050055{
Jamie Madill32fd63b2018-03-31 11:20:35 -040056 ContextVk *contextVk = vk::GetImpl(context);
Frank Henigman17448952017-01-05 15:48:26 -050057 const auto &attribs = mState.getVertexAttributes();
58 const auto &bindings = mState.getVertexBindings();
Frank Henigman17448952017-01-05 15:48:26 -050059
Jamie Madill32fd63b2018-03-31 11:20:35 -040060 ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
61
62 const size_t lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
63
Frank Henigman17448952017-01-05 15:48:26 -050064 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
65 // un-interleaved, wasting space and copying time. Consider improving on that.
Jamie Madill32fd63b2018-03-31 11:20:35 -040066 for (auto attribIndex : getAttribsToStream(context))
Frank Henigman17448952017-01-05 15:48:26 -050067 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050068 const gl::VertexAttribute &attrib = attribs[attribIndex];
69 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
70 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
Frank Henigman17448952017-01-05 15:48:26 -050071
Frank Henigman6dd4a922018-03-02 16:35:13 -050072 // TODO(fjhenigman): Work with more formats than just GL_FLOAT.
73 if (attrib.type != GL_FLOAT)
Frank Henigman17448952017-01-05 15:48:26 -050074 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050075 UNIMPLEMENTED();
76 return gl::InternalError();
Frank Henigman17448952017-01-05 15:48:26 -050077 }
Frank Henigman6dd4a922018-03-02 16:35:13 -050078
79 // Only [firstVertex, lastVertex] is needed by the upcoming draw so that
80 // is all we copy, but we allocate space for [0, lastVertex] so indexing
81 // will work. If we don't start at zero all the indices will be off.
82 // TODO(fjhenigman): See if we can account for indices being off by adjusting
83 // the offset, thus avoiding wasted memory.
Jamie Madill32fd63b2018-03-31 11:20:35 -040084 const size_t firstByte = drawCallParams.firstVertex() * binding.getStride();
Frank Henigman6dd4a922018-03-02 16:35:13 -050085 const size_t lastByte =
86 lastVertex * binding.getStride() + gl::ComputeVertexAttributeTypeSize(attrib);
87 uint8_t *dst = nullptr;
Luc Ferron7a06ac12018-03-15 10:17:04 -040088 uint32_t offset = 0;
Jamie Madillf3614372018-03-31 14:19:14 -040089 ANGLE_TRY(dynamicBuffer->allocate(
90 contextVk, lastByte, &dst, &mCurrentArrayBufferHandles[attribIndex], &offset, nullptr));
Luc Ferron7a06ac12018-03-15 10:17:04 -040091 mCurrentArrayBufferOffsets[attribIndex] = static_cast<VkDeviceSize>(offset);
Frank Henigman6dd4a922018-03-02 16:35:13 -050092 memcpy(dst + firstByte, static_cast<const uint8_t *>(attrib.pointer) + firstByte,
93 lastByte - firstByte);
Frank Henigman17448952017-01-05 15:48:26 -050094 }
95
Jamie Madillf3614372018-03-31 14:19:14 -040096 ANGLE_TRY(dynamicBuffer->flush(contextVk));
Frank Henigman17448952017-01-05 15:48:26 -050097 return gl::NoError();
98}
99
Frank Henigman0af5b862018-03-27 20:19:33 -0400100gl::Error VertexArrayVk::syncState(const gl::Context *context,
101 const gl::VertexArray::DirtyBits &dirtyBits,
102 const gl::VertexArray::DirtyAttribBitsArray &attribBits,
103 const gl::VertexArray::DirtyBindingBitsArray &bindingBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400104{
105 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400106
Jamie Madillbd159f02017-10-09 19:39:06 -0400107 // Invalidate current pipeline.
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500108 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill49ac74b2017-12-21 14:42:33 -0500109 contextVk->onVertexArrayChange();
Jamie Madillbd159f02017-10-09 19:39:06 -0400110
111 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
112 // TODO(jmadill): Handle buffer storage changes.
113 const auto &attribs = mState.getVertexAttributes();
114 const auto &bindings = mState.getVertexBindings();
115
Jamie Madill09463932018-04-04 05:26:59 -0400116 for (size_t dirtyBit : dirtyBits)
Jamie Madillbd159f02017-10-09 19:39:06 -0400117 {
Jamie Madill09463932018-04-04 05:26:59 -0400118 switch (dirtyBit)
Jamie Madillda854a22017-11-30 17:24:21 -0500119 {
Jamie Madill09463932018-04-04 05:26:59 -0400120 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
Jamie Madillda854a22017-11-30 17:24:21 -0500121 {
Jamie Madill09463932018-04-04 05:26:59 -0400122 gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
123 if (bufferGL)
124 {
125 mCurrentElementArrayBufferResource = vk::GetImpl(bufferGL);
126 }
127 else
128 {
129 mCurrentElementArrayBufferResource = nullptr;
130 }
131 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500132 }
Jamie Madill09463932018-04-04 05:26:59 -0400133
134 case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
135 break;
136
137 default:
Jamie Madillda854a22017-11-30 17:24:21 -0500138 {
Jamie Madill09463932018-04-04 05:26:59 -0400139 size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
140
141 // Invalidate the input description for pipelines.
142 mDirtyPackedInputs.set(attribIndex);
143
144 const auto &attrib = attribs[attribIndex];
145 const auto &binding = bindings[attrib.bindingIndex];
146
147 if (attrib.enabled)
148 {
149 gl::Buffer *bufferGL = binding.getBuffer().get();
150
151 if (bufferGL)
152 {
153 BufferVk *bufferVk = vk::GetImpl(bufferGL);
154 mCurrentArrayBufferResources[attribIndex] = bufferVk;
155 mCurrentArrayBufferHandles[attribIndex] =
156 bufferVk->getVkBuffer().getHandle();
157 mClientMemoryAttribs.reset(attribIndex);
158 }
159 else
160 {
161 mCurrentArrayBufferResources[attribIndex] = nullptr;
162 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
163 mClientMemoryAttribs.set(attribIndex);
164 }
165 // TODO(jmadill): Offset handling. Assume zero for now.
166 mCurrentArrayBufferOffsets[attribIndex] = 0;
167 }
168 else
169 {
170 mClientMemoryAttribs.reset(attribIndex);
171 UNIMPLEMENTED();
172 }
173 break;
Jamie Madillda854a22017-11-30 17:24:21 -0500174 }
Jamie Madillbd159f02017-10-09 19:39:06 -0400175 }
176 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400177
178 return gl::NoError();
Jamie Madillbd159f02017-10-09 19:39:06 -0400179}
180
Jamie Madillda854a22017-11-30 17:24:21 -0500181const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const
Jamie Madillbd159f02017-10-09 19:39:06 -0400182{
Jamie Madillda854a22017-11-30 17:24:21 -0500183 return mCurrentArrayBufferHandles;
Jamie Madillbd159f02017-10-09 19:39:06 -0400184}
185
Frank Henigman17448952017-01-05 15:48:26 -0500186const gl::AttribArray<VkDeviceSize> &VertexArrayVk::getCurrentArrayBufferOffsets() const
187{
188 return mCurrentArrayBufferOffsets;
189}
190
Jamie Madill1f46bc12018-02-20 16:09:43 -0500191void VertexArrayVk::updateDrawDependencies(vk::CommandGraphNode *readNode,
Jamie Madill49ac74b2017-12-21 14:42:33 -0500192 const gl::AttributesMask &activeAttribsMask,
Luc Ferron78e39b32018-02-26 07:42:44 -0500193 ResourceVk *elementArrayBufferOverride,
Jamie Madill49ac74b2017-12-21 14:42:33 -0500194 Serial serial,
Jamie Madill32fd63b2018-03-31 11:20:35 -0400195 bool isDrawElements)
Jamie Madillbd159f02017-10-09 19:39:06 -0400196{
Jamie Madillda854a22017-11-30 17:24:21 -0500197 // Handle the bound array buffers.
Jamie Madillbd159f02017-10-09 19:39:06 -0400198 for (auto attribIndex : activeAttribsMask)
199 {
Frank Henigman17448952017-01-05 15:48:26 -0500200 if (mCurrentArrayBufferResources[attribIndex])
201 mCurrentArrayBufferResources[attribIndex]->onReadResource(readNode, serial);
Jamie Madillda854a22017-11-30 17:24:21 -0500202 }
203
204 // Handle the bound element array buffer.
Jamie Madill32fd63b2018-03-31 11:20:35 -0400205 if (isDrawElements)
Jamie Madillda854a22017-11-30 17:24:21 -0500206 {
Luc Ferron78e39b32018-02-26 07:42:44 -0500207 if (elementArrayBufferOverride != nullptr)
208 {
209 elementArrayBufferOverride->onReadResource(readNode, serial);
210 }
Frank Henigman5d232d52018-04-01 19:57:19 -0400211 else if (mCurrentElementArrayBufferResource != nullptr)
Luc Ferron78e39b32018-02-26 07:42:44 -0500212 {
Luc Ferron78e39b32018-02-26 07:42:44 -0500213 mCurrentElementArrayBufferResource->onReadResource(readNode, serial);
214 }
Jamie Madillbd159f02017-10-09 19:39:06 -0400215 }
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400216}
217
Jamie Madill112a3a82018-01-23 13:04:06 -0500218void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400219{
Jamie Madill112a3a82018-01-23 13:04:06 -0500220 updatePackedInputDescriptions();
221 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400222}
223
Jamie Madill112a3a82018-01-23 13:04:06 -0500224void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400225{
Jamie Madill112a3a82018-01-23 13:04:06 -0500226 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400227 {
228 return;
229 }
230
231 const auto &attribs = mState.getVertexAttributes();
232 const auto &bindings = mState.getVertexBindings();
233
Jamie Madill112a3a82018-01-23 13:04:06 -0500234 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400235 {
236 const auto &attrib = attribs[attribIndex];
237 const auto &binding = bindings[attrib.bindingIndex];
238 if (attrib.enabled)
239 {
Jamie Madill112a3a82018-01-23 13:04:06 -0500240 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400241 }
242 else
243 {
244 UNIMPLEMENTED();
245 }
246 }
247
Jamie Madill112a3a82018-01-23 13:04:06 -0500248 mDirtyPackedInputs.reset();
249}
250
251void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
252 const gl::VertexBinding &binding,
253 const gl::VertexAttribute &attrib)
254{
255 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
256
257 size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
258 ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
259
Frank Henigmana8e868f2018-01-28 23:32:25 -0500260 bindingDesc.stride = static_cast<uint16_t>(binding.getStride());
Jamie Madill112a3a82018-01-23 13:04:06 -0500261 bindingDesc.inputRate = static_cast<uint16_t>(
262 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
263
264 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
265 VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
266 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
267
268 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
269 attribDesc.format = static_cast<uint16_t>(vkFormat);
270 attribDesc.location = static_cast<uint16_t>(attribIndex);
271 attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
Jamie Madillebf72992017-10-13 14:09:45 -0400272}
273
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400274} // namespace rx