blob: d47721ed1d350de421fb4ada451dc264ab0f87de [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 Henigman17448952017-01-05 15:48:26 -050046gl::Error VertexArrayVk::streamVertexData(ContextVk *context,
47 StreamingBuffer *stream,
Frank Henigman6dd4a922018-03-02 16:35:13 -050048 size_t firstVertex,
49 size_t lastVertex)
Frank Henigman17448952017-01-05 15:48:26 -050050{
51 const auto &attribs = mState.getVertexAttributes();
52 const auto &bindings = mState.getVertexBindings();
53 const gl::Program *programGL = context->getGLState().getProgram();
Frank Henigman6dd4a922018-03-02 16:35:13 -050054 const gl::AttributesMask attribsToStream =
55 mClientMemoryAttribs & programGL->getActiveAttribLocationsMask();
Frank Henigman17448952017-01-05 15:48:26 -050056
57 // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
58 // un-interleaved, wasting space and copying time. Consider improving on that.
Frank Henigman6dd4a922018-03-02 16:35:13 -050059 for (auto attribIndex : attribsToStream)
Frank Henigman17448952017-01-05 15:48:26 -050060 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050061 const gl::VertexAttribute &attrib = attribs[attribIndex];
62 const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
63 ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
Frank Henigman17448952017-01-05 15:48:26 -050064
Frank Henigman6dd4a922018-03-02 16:35:13 -050065 // TODO(fjhenigman): Work with more formats than just GL_FLOAT.
66 if (attrib.type != GL_FLOAT)
Frank Henigman17448952017-01-05 15:48:26 -050067 {
Frank Henigman6dd4a922018-03-02 16:35:13 -050068 UNIMPLEMENTED();
69 return gl::InternalError();
Frank Henigman17448952017-01-05 15:48:26 -050070 }
Frank Henigman6dd4a922018-03-02 16:35:13 -050071
72 // Only [firstVertex, lastVertex] is needed by the upcoming draw so that
73 // is all we copy, but we allocate space for [0, lastVertex] so indexing
74 // will work. If we don't start at zero all the indices will be off.
75 // TODO(fjhenigman): See if we can account for indices being off by adjusting
76 // the offset, thus avoiding wasted memory.
77 const size_t firstByte = firstVertex * binding.getStride();
78 const size_t lastByte =
79 lastVertex * binding.getStride() + gl::ComputeVertexAttributeTypeSize(attrib);
80 uint8_t *dst = nullptr;
81 ANGLE_TRY(stream->allocate(context, lastByte, &dst,
82 &mCurrentArrayBufferHandles[attribIndex],
83 &mCurrentArrayBufferOffsets[attribIndex]));
84 memcpy(dst + firstByte, static_cast<const uint8_t *>(attrib.pointer) + firstByte,
85 lastByte - firstByte);
Frank Henigman17448952017-01-05 15:48:26 -050086 }
87
88 ANGLE_TRY(stream->flush(context));
89 return gl::NoError();
90}
91
Jamie Madillc564c072017-06-01 12:45:42 -040092void VertexArrayVk::syncState(const gl::Context *context,
93 const gl::VertexArray::DirtyBits &dirtyBits)
Jamie Madilldd43e6c2017-03-24 14:18:49 -040094{
95 ASSERT(dirtyBits.any());
Jamie Madill72106562017-03-24 14:18:50 -040096
Jamie Madillbd159f02017-10-09 19:39:06 -040097 // Invalidate current pipeline.
Jamie Madillacf2f3a2017-11-21 19:22:44 -050098 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill49ac74b2017-12-21 14:42:33 -050099 contextVk->onVertexArrayChange();
Jamie Madillbd159f02017-10-09 19:39:06 -0400100
101 // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
102 // TODO(jmadill): Handle buffer storage changes.
103 const auto &attribs = mState.getVertexAttributes();
104 const auto &bindings = mState.getVertexBindings();
105
106 for (auto dirtyBit : dirtyBits)
107 {
108 if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
Jamie Madillda854a22017-11-30 17:24:21 -0500109 {
110 gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
111 if (bufferGL)
112 {
113 mCurrentElementArrayBufferResource = vk::GetImpl(bufferGL);
114 }
115 else
116 {
117 mCurrentElementArrayBufferResource = nullptr;
118 }
Jamie Madillbd159f02017-10-09 19:39:06 -0400119 continue;
Jamie Madillda854a22017-11-30 17:24:21 -0500120 }
Jamie Madillbd159f02017-10-09 19:39:06 -0400121
122 size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
123
Jamie Madill112a3a82018-01-23 13:04:06 -0500124 // Invalidate the input description for pipelines.
125 mDirtyPackedInputs.set(attribIndex);
126
Jamie Madillbd159f02017-10-09 19:39:06 -0400127 const auto &attrib = attribs[attribIndex];
128 const auto &binding = bindings[attrib.bindingIndex];
Jamie Madillebf72992017-10-13 14:09:45 -0400129
Jamie Madillbd159f02017-10-09 19:39:06 -0400130 if (attrib.enabled)
131 {
132 gl::Buffer *bufferGL = binding.getBuffer().get();
133
134 if (bufferGL)
135 {
Jamie Madillda854a22017-11-30 17:24:21 -0500136 BufferVk *bufferVk = vk::GetImpl(bufferGL);
137 mCurrentArrayBufferResources[attribIndex] = bufferVk;
138 mCurrentArrayBufferHandles[attribIndex] = bufferVk->getVkBuffer().getHandle();
Frank Henigman6dd4a922018-03-02 16:35:13 -0500139 mClientMemoryAttribs.reset(attribIndex);
Jamie Madillbd159f02017-10-09 19:39:06 -0400140 }
141 else
142 {
Jamie Madillda854a22017-11-30 17:24:21 -0500143 mCurrentArrayBufferResources[attribIndex] = nullptr;
144 mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
Frank Henigman6dd4a922018-03-02 16:35:13 -0500145 mClientMemoryAttribs.set(attribIndex);
Jamie Madillbd159f02017-10-09 19:39:06 -0400146 }
Frank Henigman17448952017-01-05 15:48:26 -0500147 // TODO(jmadill): Offset handling. Assume zero for now.
148 mCurrentArrayBufferOffsets[attribIndex] = 0;
Jamie Madillbd159f02017-10-09 19:39:06 -0400149 }
150 else
151 {
Frank Henigman6dd4a922018-03-02 16:35:13 -0500152 mClientMemoryAttribs.reset(attribIndex);
Jamie Madillbd159f02017-10-09 19:39:06 -0400153 UNIMPLEMENTED();
154 }
155 }
156}
157
Jamie Madillda854a22017-11-30 17:24:21 -0500158const gl::AttribArray<VkBuffer> &VertexArrayVk::getCurrentArrayBufferHandles() const
Jamie Madillbd159f02017-10-09 19:39:06 -0400159{
Jamie Madillda854a22017-11-30 17:24:21 -0500160 return mCurrentArrayBufferHandles;
Jamie Madillbd159f02017-10-09 19:39:06 -0400161}
162
Frank Henigman17448952017-01-05 15:48:26 -0500163const gl::AttribArray<VkDeviceSize> &VertexArrayVk::getCurrentArrayBufferOffsets() const
164{
165 return mCurrentArrayBufferOffsets;
166}
167
Jamie Madill1f46bc12018-02-20 16:09:43 -0500168void VertexArrayVk::updateDrawDependencies(vk::CommandGraphNode *readNode,
Jamie Madill49ac74b2017-12-21 14:42:33 -0500169 const gl::AttributesMask &activeAttribsMask,
Luc Ferron78e39b32018-02-26 07:42:44 -0500170 ResourceVk *elementArrayBufferOverride,
Jamie Madill49ac74b2017-12-21 14:42:33 -0500171 Serial serial,
172 DrawType drawType)
Jamie Madillbd159f02017-10-09 19:39:06 -0400173{
Jamie Madillda854a22017-11-30 17:24:21 -0500174 // Handle the bound array buffers.
Jamie Madillbd159f02017-10-09 19:39:06 -0400175 for (auto attribIndex : activeAttribsMask)
176 {
Frank Henigman17448952017-01-05 15:48:26 -0500177 if (mCurrentArrayBufferResources[attribIndex])
178 mCurrentArrayBufferResources[attribIndex]->onReadResource(readNode, serial);
Jamie Madillda854a22017-11-30 17:24:21 -0500179 }
180
181 // Handle the bound element array buffer.
182 if (drawType == DrawType::Elements)
183 {
Luc Ferron78e39b32018-02-26 07:42:44 -0500184 if (elementArrayBufferOverride != nullptr)
185 {
186 elementArrayBufferOverride->onReadResource(readNode, serial);
187 }
188 else
189 {
190 ASSERT(mCurrentElementArrayBufferResource);
191 mCurrentElementArrayBufferResource->onReadResource(readNode, serial);
192 }
Jamie Madillbd159f02017-10-09 19:39:06 -0400193 }
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400194}
195
Jamie Madill112a3a82018-01-23 13:04:06 -0500196void VertexArrayVk::getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc)
Jamie Madillebf72992017-10-13 14:09:45 -0400197{
Jamie Madill112a3a82018-01-23 13:04:06 -0500198 updatePackedInputDescriptions();
199 pipelineDesc->updateVertexInputInfo(mPackedInputBindings, mPackedInputAttributes);
Jamie Madillebf72992017-10-13 14:09:45 -0400200}
201
Jamie Madill112a3a82018-01-23 13:04:06 -0500202void VertexArrayVk::updatePackedInputDescriptions()
Jamie Madillebf72992017-10-13 14:09:45 -0400203{
Jamie Madill112a3a82018-01-23 13:04:06 -0500204 if (!mDirtyPackedInputs.any())
Jamie Madillebf72992017-10-13 14:09:45 -0400205 {
206 return;
207 }
208
209 const auto &attribs = mState.getVertexAttributes();
210 const auto &bindings = mState.getVertexBindings();
211
Jamie Madill112a3a82018-01-23 13:04:06 -0500212 for (auto attribIndex : mDirtyPackedInputs)
Jamie Madillebf72992017-10-13 14:09:45 -0400213 {
214 const auto &attrib = attribs[attribIndex];
215 const auto &binding = bindings[attrib.bindingIndex];
216 if (attrib.enabled)
217 {
Jamie Madill112a3a82018-01-23 13:04:06 -0500218 updatePackedInputInfo(static_cast<uint32_t>(attribIndex), binding, attrib);
Jamie Madillebf72992017-10-13 14:09:45 -0400219 }
220 else
221 {
222 UNIMPLEMENTED();
223 }
224 }
225
Jamie Madill112a3a82018-01-23 13:04:06 -0500226 mDirtyPackedInputs.reset();
227}
228
229void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
230 const gl::VertexBinding &binding,
231 const gl::VertexAttribute &attrib)
232{
233 vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
234
235 size_t attribSize = gl::ComputeVertexAttributeTypeSize(attrib);
236 ASSERT(attribSize <= std::numeric_limits<uint16_t>::max());
237
Frank Henigmana8e868f2018-01-28 23:32:25 -0500238 bindingDesc.stride = static_cast<uint16_t>(binding.getStride());
Jamie Madill112a3a82018-01-23 13:04:06 -0500239 bindingDesc.inputRate = static_cast<uint16_t>(
240 binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
241
242 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
243 VkFormat vkFormat = vk::GetNativeVertexFormat(vertexFormatType);
244 ASSERT(vkFormat <= std::numeric_limits<uint16_t>::max());
245
246 vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
247 attribDesc.format = static_cast<uint16_t>(vkFormat);
248 attribDesc.location = static_cast<uint16_t>(attribIndex);
249 attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
Jamie Madillebf72992017-10-13 14:09:45 -0400250}
251
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400252} // namespace rx