blob: be79380eb994d55e7df49decf983a11e0fcc622e [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
Frank Henigmana53d0e12018-02-13 00:06:06 -050046gl::AttributesMask VertexArrayVk::attribsToStream(ContextVk *context) const
47{
48 const gl::Program *programGL = context->getGLState().getProgram();
49 return mClientMemoryAttribs & programGL->getActiveAttribLocationsMask();
50}
51
Frank Henigman17448952017-01-05 15:48:26 -050052gl::Error VertexArrayVk::streamVertexData(ContextVk *context,
53 StreamingBuffer *stream,
Frank Henigman6dd4a922018-03-02 16:35:13 -050054 size_t firstVertex,
55 size_t lastVertex)
Frank Henigman17448952017-01-05 15:48:26 -050056{
57 const auto &attribs = mState.getVertexAttributes();
58 const auto &bindings = mState.getVertexBindings();
Frank Henigman17448952017-01-05 15:48:26 -050059
60 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
61 // un-interleaved, wasting space and copying time. Consider improving on that.
Frank Henigmana53d0e12018-02-13 00:06:06 -050062 for (auto attribIndex : attribsToStream(context))
Frank Henigman17448952017-01-05 15:48:26 -050063 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050064 const gl::VertexAttribute &attrib = attribs[attribIndex];
65 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
66 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
Frank Henigman17448952017-01-05 15:48:26 -050067
Frank Henigman6dd4a922018-03-02 16:35:13 -050068 // TODO(fjhenigman): Work with more formats than just GL_FLOAT.
69 if (attrib.type != GL_FLOAT)
Frank Henigman17448952017-01-05 15:48:26 -050070 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050071 UNIMPLEMENTED();
72 return gl::InternalError();
Frank Henigman17448952017-01-05 15:48:26 -050073 }
Frank Henigman6dd4a922018-03-02 16:35:13 -050074
75 // Only [firstVertex, lastVertex] is needed by the upcoming draw so that
76 // is all we copy, but we allocate space for [0, lastVertex] so indexing
77 // will work. If we don't start at zero all the indices will be off.
78 // TODO(fjhenigman): See if we can account for indices being off by adjusting
79 // the offset, thus avoiding wasted memory.
80 const size_t firstByte = firstVertex * binding.getStride();
81 const size_t lastByte =
82 lastVertex * binding.getStride() + gl::ComputeVertexAttributeTypeSize(attrib);
83 uint8_t *dst = nullptr;
Luc Ferron7a06ac12018-03-15 10:17:04 -040084 uint32_t offset = 0;
Frank Henigman6dd4a922018-03-02 16:35:13 -050085 ANGLE_TRY(stream->allocate(context, lastByte, &dst,
Luc Ferron7a06ac12018-03-15 10:17:04 -040086 &mCurrentArrayBufferHandles[attribIndex], &offset, nullptr));
87 mCurrentArrayBufferOffsets[attribIndex] = static_cast<VkDeviceSize>(offset);
Frank Henigman6dd4a922018-03-02 16:35:13 -050088 memcpy(dst + firstByte, static_cast<const uint8_t *>(attrib.pointer) + firstByte,
89 lastByte - firstByte);
Frank Henigman17448952017-01-05 15:48:26 -050090 }
91
92 ANGLE_TRY(stream->flush(context));
93 return gl::NoError();
94}
95
Jamie Madillc564c072017-06-01 12:45:42 -040096void VertexArrayVk::syncState(const gl::Context *context,
97 const gl::VertexArray::DirtyBits &dirtyBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -040098{
99 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -0400100
Jamie Madillbd159f02017-10-09 19:39:06 -0400101 // Invalidate current pipeline.
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500102 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill49ac74b2017-12-21 14:42:33 -0500103 contextVk->onVertexArrayChange();
Jamie Madillbd159f02017-10-09 19:39:06 -0400104
105 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
106 // TODO(jmadill): Handle buffer storage changes.
107 const auto &attribs = mState.getVertexAttributes();
108 const auto &bindings = mState.getVertexBindings();
109
110 for (auto dirtyBit : dirtyBits)
111 {
112 if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
Jamie Madillda854a22017-11-30 17:24:21 -0500113 {
114 gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
115 if (bufferGL)
116 {
117 mCurrentElementArrayBufferResource = vk::GetImpl(bufferGL);
118 }
119 else
120 {
121 mCurrentElementArrayBufferResource = nullptr;
122 }
Jamie Madillbd159f02017-10-09 19:39:06 -0400123 continue;
Jamie Madillda854a22017-11-30 17:24:21 -0500124 }
Jamie Madillbd159f02017-10-09 19:39:06 -0400125
126 size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
127
Jamie Madill112a3a82018-01-23 13:04:06 -0500128 // Invalidate the input description for pipelines.
129 mDirtyPackedInputs.set(attribIndex);
130
Jamie Madillbd159f02017-10-09 19:39:06 -0400131 const auto &attrib = attribs[attribIndex];
132 const auto &binding = bindings[attrib.bindingIndex];
Jamie Madillebf72992017-10-13 14:09:45 -0400133
Jamie Madillbd159f02017-10-09 19:39:06 -0400134 if (attrib.enabled)
135 {
136 gl::Buffer *bufferGL = binding.getBuffer().get();
137
138 if (bufferGL)
139 {
Jamie Madillda854a22017-11-30 17:24:21 -0500140 BufferVk *bufferVk = vk::GetImpl(bufferGL);
141 mCurrentArrayBufferResources[attribIndex] = bufferVk;
142 mCurrentArrayBufferHandles[attribIndex] = bufferVk->getVkBuffer().getHandle();
Frank Henigman6dd4a922018-03-02 16:35:13 -0500143 mClientMemoryAttribs.reset(attribIndex);
Jamie Madillbd159f02017-10-09 19:39:06 -0400144 }
145 else
146 {
Jamie Madillda854a22017-11-30 17:24:21 -0500147 mCurrentArrayBufferResources[attribIndex] = nullptr;
148 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
Frank Henigman6dd4a922018-03-02 16:35:13 -0500149 mClientMemoryAttribs.set(attribIndex);
Jamie Madillbd159f02017-10-09 19:39:06 -0400150 }
Frank Henigman17448952017-01-05 15:48:26 -0500151 // TODO(jmadill): Offset handling. Assume zero for now.
152 mCurrentArrayBufferOffsets[attribIndex] = 0;
Jamie Madillbd159f02017-10-09 19:39:06 -0400153 }
154 else
155 {
Frank Henigman6dd4a922018-03-02 16:35:13 -0500156 mClientMemoryAttribs.reset(attribIndex);
Jamie Madillbd159f02017-10-09 19:39:06 -0400157 UNIMPLEMENTED();
158 }
159 }
160}
161
Jamie Madillda854a22017-11-30 17:24:21 -0500162const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const
Jamie Madillbd159f02017-10-09 19:39:06 -0400163{
Jamie Madillda854a22017-11-30 17:24:21 -0500164 return mCurrentArrayBufferHandles;
Jamie Madillbd159f02017-10-09 19:39:06 -0400165}
166
Frank Henigman17448952017-01-05 15:48:26 -0500167const gl::AttribArray<VkDeviceSize> &VertexArrayVk::getCurrentArrayBufferOffsets() const
168{
169 return mCurrentArrayBufferOffsets;
170}
171
Jamie Madill1f46bc12018-02-20 16:09:43 -0500172void VertexArrayVk::updateDrawDependencies(vk::CommandGraphNode *readNode,
Jamie Madill49ac74b2017-12-21 14:42:33 -0500173 const gl::AttributesMask &activeAttribsMask,
Luc Ferron78e39b32018-02-26 07:42:44 -0500174 ResourceVk *elementArrayBufferOverride,
Jamie Madill49ac74b2017-12-21 14:42:33 -0500175 Serial serial,
176 DrawType drawType)
Jamie Madillbd159f02017-10-09 19:39:06 -0400177{
Jamie Madillda854a22017-11-30 17:24:21 -0500178 // Handle the bound array buffers.
Jamie Madillbd159f02017-10-09 19:39:06 -0400179 for (auto attribIndex : activeAttribsMask)
180 {
Frank Henigman17448952017-01-05 15:48:26 -0500181 if (mCurrentArrayBufferResources[attribIndex])
182 mCurrentArrayBufferResources[attribIndex]->onReadResource(readNode, serial);
Jamie Madillda854a22017-11-30 17:24:21 -0500183 }
184
185 // Handle the bound element array buffer.
Frank Henigmana53d0e12018-02-13 00:06:06 -0500186 if (drawType == DrawType::Elements && mCurrentElementArrayBufferResource)
Jamie Madillda854a22017-11-30 17:24:21 -0500187 {
Luc Ferron78e39b32018-02-26 07:42:44 -0500188 if (elementArrayBufferOverride != nullptr)
189 {
190 elementArrayBufferOverride->onReadResource(readNode, serial);
191 }
192 else
193 {
194 ASSERT(mCurrentElementArrayBufferResource);
195 mCurrentElementArrayBufferResource->onReadResource(readNode, serial);
196 }
Jamie Madillbd159f02017-10-09 19:39:06 -0400197 }
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400198}
199
Jamie Madill112a3a82018-01-23 13:04:06 -0500200void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400201{
Jamie Madill112a3a82018-01-23 13:04:06 -0500202 updatePackedInputDescriptions();
203 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400204}
205
Jamie Madill112a3a82018-01-23 13:04:06 -0500206void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400207{
Jamie Madill112a3a82018-01-23 13:04:06 -0500208 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400209 {
210 return;
211 }
212
213 const auto &attribs = mState.getVertexAttributes();
214 const auto &bindings = mState.getVertexBindings();
215
Jamie Madill112a3a82018-01-23 13:04:06 -0500216 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400217 {
218 const auto &attrib = attribs[attribIndex];
219 const auto &binding = bindings[attrib.bindingIndex];
220 if (attrib.enabled)
221 {
Jamie Madill112a3a82018-01-23 13:04:06 -0500222 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400223 }
224 else
225 {
226 UNIMPLEMENTED();
227 }
228 }
229
Jamie Madill112a3a82018-01-23 13:04:06 -0500230 mDirtyPackedInputs.reset();
231}
232
233void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
234 const gl::VertexBinding &binding,
235 const gl::VertexAttribute &attrib)
236{
237 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
238
239 size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
240 ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
241
Frank Henigmana8e868f2018-01-28 23:32:25 -0500242 bindingDesc.stride = static_cast<uint16_t>(binding.getStride());
Jamie Madill112a3a82018-01-23 13:04:06 -0500243 bindingDesc.inputRate = static_cast<uint16_t>(
244 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
245
246 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
247 VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
248 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
249
250 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
251 attribDesc.format = static_cast<uint16_t>(vkFormat);
252 attribDesc.location = static_cast<uint16_t>(attribIndex);
253 attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
Jamie Madillebf72992017-10-13 14:09:45 -0400254}
255
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400256} // namespace rx