blob: 99299308750e42f7f6f228919aa0caf4a96ddc31 [file] [log] [blame]
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -05001//
2// Copyright 2018 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// DispatchUtilsVk.cpp:
7// Implements the DispatchUtilsVk class.
8//
9
10#include "libANGLE/renderer/vulkan/DispatchUtilsVk.h"
11
12#include "libANGLE/renderer/vulkan/BufferVk.h"
13#include "libANGLE/renderer/vulkan/FramebufferVk.h"
14#include "libANGLE/renderer/vulkan/RendererVk.h"
15#include "libANGLE/renderer/vulkan/TextureVk.h"
16
17namespace rx
18{
19
20namespace BufferUtils_comp = vk::InternalShader::BufferUtils_comp;
21
22namespace
23{
24// All internal shaders assume there is only one descriptor set, indexed at 0
25constexpr uint32_t kSetIndex = 0;
26
27constexpr uint32_t kClearOutputBinding = 0;
28constexpr uint32_t kCopyDestinationBinding = 0;
29constexpr uint32_t kCopySourceBinding = 1;
30
31uint32_t GetBufferUtilsFlags(size_t dispatchSize, const vk::Format &format)
32{
33 uint32_t flags = dispatchSize % 64 == 0 ? BufferUtils_comp::kIsAligned : 0;
34 const angle::Format &bufferFormat = format.bufferFormat();
35
36 flags |= bufferFormat.componentType == GL_INT
37 ? BufferUtils_comp::kIsInt
38 : bufferFormat.componentType == GL_UNSIGNED_INT ? BufferUtils_comp::kIsUint
39 : BufferUtils_comp::kIsFloat;
40
41 return flags;
42}
43} // namespace
44
45DispatchUtilsVk::DispatchUtilsVk() = default;
46
47DispatchUtilsVk::~DispatchUtilsVk() = default;
48
49void DispatchUtilsVk::destroy(VkDevice device)
50{
51 for (Function f : angle::AllEnums<Function>())
52 {
53 for (auto &descriptorSetLayout : mDescriptorSetLayouts[f])
54 {
55 descriptorSetLayout.reset();
56 }
57 mPipelineLayouts[f].reset();
58 mDescriptorPools[f].destroy(device);
59 }
60
61 for (vk::ShaderProgramHelper &program : mPrograms)
62 {
63 program.destroy(device);
64 }
65}
66
67angle::Result DispatchUtilsVk::ensureResourcesInitialized(vk::Context *context,
68 Function function,
69 VkDescriptorPoolSize *setSizes,
70 size_t setSizesCount)
71{
72 RendererVk *renderer = context->getRenderer();
73
74 vk::DescriptorSetLayoutDesc descriptorSetDesc;
75
76 uint32_t currentBinding = 0;
77 for (size_t i = 0; i < setSizesCount; ++i)
78 {
79 descriptorSetDesc.update(currentBinding, setSizes[i].type, setSizes[i].descriptorCount);
80 currentBinding += setSizes[i].descriptorCount;
81 }
82
83 ANGLE_TRY(renderer->getDescriptorSetLayout(context, descriptorSetDesc,
84 &mDescriptorSetLayouts[function][kSetIndex]));
85
86 // Corresponding pipeline layouts:
87 vk::PipelineLayoutDesc pipelineLayoutDesc;
88
89 pipelineLayoutDesc.updateDescriptorSetLayout(kSetIndex, descriptorSetDesc);
90 pipelineLayoutDesc.updatePushConstantRange(gl::ShaderType::Compute, 0, sizeof(ShaderParams));
91
92 ANGLE_TRY(renderer->getPipelineLayout(
93 context, pipelineLayoutDesc, mDescriptorSetLayouts[function], &mPipelineLayouts[function]));
94
95 ANGLE_TRY(mDescriptorPools[function].init(context, setSizes, setSizesCount));
96
97 return angle::Result::Continue();
98}
99
100angle::Result DispatchUtilsVk::ensureBufferClearInitialized(vk::Context *context)
101{
102 if (mPipelineLayouts[Function::BufferClear].valid())
103 {
104 return angle::Result::Continue();
105 }
106
107 VkDescriptorPoolSize setSizes[1] = {
108 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1},
109 };
110
111 return ensureResourcesInitialized(context, Function::BufferClear, setSizes,
112 ArraySize(setSizes));
113}
114
115angle::Result DispatchUtilsVk::ensureBufferCopyInitialized(vk::Context *context)
116{
117 if (mPipelineLayouts[Function::BufferCopy].valid())
118 {
119 return angle::Result::Continue();
120 }
121
122 VkDescriptorPoolSize setSizes[2] = {
123 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1},
124 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1},
125 };
126
127 return ensureResourcesInitialized(context, Function::BufferCopy, setSizes, ArraySize(setSizes));
128}
129
130angle::Result DispatchUtilsVk::setupProgram(vk::Context *context,
131 uint32_t function,
132 const VkDescriptorSet &descriptorSet,
133 const ShaderParams &params,
134 vk::CommandBuffer *commandBuffer)
135{
136 RendererVk *renderer = context->getRenderer();
137 vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
138
139 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
140 ANGLE_TRY(shaderLibrary.getBufferUtils_comp(context, function, &shader));
141
142 mPrograms[function].setShader(gl::ShaderType::Compute, shader);
143
144 bool isClear = (function & BufferUtils_comp::kFunctionMask) == BufferUtils_comp::kIsClear;
145 Function pipelineLayoutIndex = isClear ? Function::BufferClear : Function::BufferCopy;
146 const vk::BindingPointer<vk::PipelineLayout> &pipelineLayout =
147 mPipelineLayouts[pipelineLayoutIndex];
148
149 vk::PipelineAndSerial *pipelineAndSerial;
150 ANGLE_TRY(
151 mPrograms[function].getComputePipeline(context, pipelineLayout.get(), &pipelineAndSerial));
152
153 commandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipelineAndSerial->get());
154 pipelineAndSerial->updateSerial(renderer->getCurrentQueueSerial());
155
156 commandBuffer->bindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0, 1,
157 &descriptorSet, 0, nullptr);
158 commandBuffer->pushConstants(pipelineLayout.get(), VK_SHADER_STAGE_COMPUTE_BIT, 0,
159 sizeof(params), &params);
160
161 return angle::Result::Continue();
162}
163
164angle::Result DispatchUtilsVk::clearBuffer(vk::Context *context,
165 vk::BufferHelper *dest,
166 const ClearParameters &params)
167{
168 ANGLE_TRY(ensureBufferClearInitialized(context));
169
170 vk::CommandBuffer *commandBuffer;
171 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
172
173 // Tell dest it's being written to.
174 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
175
176 const vk::Format &destFormat = dest->getViewFormat();
177
178 uint32_t function = BufferUtils_comp::kIsClear | GetBufferUtilsFlags(params.size, destFormat);
179
180 ShaderParams shaderParams;
181 shaderParams.destOffset = params.offset;
182 shaderParams.size = params.size;
183 shaderParams.clearValue = params.clearValue;
184
185 VkDescriptorSet descriptorSet;
186 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
187 ANGLE_TRY(mDescriptorPools[Function::BufferClear].allocateSets(
188 context, mDescriptorSetLayouts[Function::BufferClear][kSetIndex].get().ptr(), 1,
189 &descriptorPoolBinding, &descriptorSet));
190
191 VkWriteDescriptorSet writeInfo = {};
192
193 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
194 writeInfo.dstSet = descriptorSet;
195 writeInfo.dstBinding = kClearOutputBinding;
196 writeInfo.descriptorCount = 1;
197 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
198 writeInfo.pTexelBufferView = dest->getBufferView().ptr();
199
200 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
201
202 ANGLE_TRY(setupProgram(context, function, descriptorSet, shaderParams, commandBuffer));
203
204 commandBuffer->dispatch(UnsignedCeilDivide(params.size, 64), 1, 1);
205
206 descriptorPoolBinding.reset();
207
208 return angle::Result::Continue();
209}
210
211angle::Result DispatchUtilsVk::copyBuffer(vk::Context *context,
212 vk::BufferHelper *dest,
213 vk::BufferHelper *src,
214 const CopyParameters &params)
215{
216 ANGLE_TRY(ensureBufferCopyInitialized(context));
217
218 vk::CommandBuffer *commandBuffer;
219 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
220
221 // Tell src we are going to read from it.
222 src->onRead(dest, VK_ACCESS_SHADER_READ_BIT);
223 // Tell dest it's being written to.
224 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
225
226 const vk::Format &destFormat = dest->getViewFormat();
227 const vk::Format &srcFormat = src->getViewFormat();
228
229 ASSERT(destFormat.vkFormatIsInt == srcFormat.vkFormatIsInt);
230 ASSERT(destFormat.vkFormatIsUnsigned == srcFormat.vkFormatIsUnsigned);
231
232 uint32_t function = BufferUtils_comp::kIsCopy | GetBufferUtilsFlags(params.size, destFormat);
233
234 ShaderParams shaderParams;
235 shaderParams.destOffset = params.destOffset;
236 shaderParams.size = params.size;
237 shaderParams.srcOffset = params.srcOffset;
238
239 VkDescriptorSet descriptorSet;
240 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
241 ANGLE_TRY(mDescriptorPools[Function::BufferCopy].allocateSets(
242 context, mDescriptorSetLayouts[Function::BufferCopy][kSetIndex].get().ptr(), 1,
243 &descriptorPoolBinding, &descriptorSet));
244
245 VkWriteDescriptorSet writeInfo[2] = {};
246
247 writeInfo[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
248 writeInfo[0].dstSet = descriptorSet;
249 writeInfo[0].dstBinding = kCopyDestinationBinding;
250 writeInfo[0].descriptorCount = 1;
251 writeInfo[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
252 writeInfo[0].pTexelBufferView = dest->getBufferView().ptr();
253
254 writeInfo[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
255 writeInfo[1].dstSet = descriptorSet;
256 writeInfo[1].dstBinding = kCopySourceBinding;
257 writeInfo[1].descriptorCount = 1;
258 writeInfo[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
259 writeInfo[1].pTexelBufferView = src->getBufferView().ptr();
260
261 vkUpdateDescriptorSets(context->getDevice(), 2, writeInfo, 0, nullptr);
262
263 ANGLE_TRY(setupProgram(context, function, descriptorSet, shaderParams, commandBuffer));
264
265 commandBuffer->dispatch(UnsignedCeilDivide(params.size, 64), 1, 1);
266
267 descriptorPoolBinding.reset();
268
269 return angle::Result::Continue();
270}
271
272} // namespace rx