blob: fbfa6bdfcee896929d62f4fc0ab373d8acaa4dbd [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//
Shahbaz Youssefie3219402018-12-08 16:54:14 +01006// UtilsVk.cpp:
7// Implements the UtilsVk class.
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -05008//
9
Shahbaz Youssefie3219402018-12-08 16:54:14 +010010#include "libANGLE/renderer/vulkan/UtilsVk.h"
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -050011
Shahbaz Youssefie3219402018-12-08 16:54:14 +010012#include "libANGLE/renderer/vulkan/ContextVk.h"
13#include "libANGLE/renderer/vulkan/FramebufferVk.h"
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -050014#include "libANGLE/renderer/vulkan/RendererVk.h"
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -050015
16namespace rx
17{
18
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +010019namespace BufferUtils_comp = vk::InternalShader::BufferUtils_comp;
20namespace ConvertVertex_comp = vk::InternalShader::ConvertVertex_comp;
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +010021namespace ImageCopy_frag = vk::InternalShader::ImageCopy_frag;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -050022
23namespace
24{
25// All internal shaders assume there is only one descriptor set, indexed at 0
26constexpr uint32_t kSetIndex = 0;
27
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +010028constexpr uint32_t kBufferClearOutputBinding = 0;
29constexpr uint32_t kBufferCopyDestinationBinding = 0;
30constexpr uint32_t kBufferCopySourceBinding = 1;
31constexpr uint32_t kConvertVertexDestinationBinding = 0;
32constexpr uint32_t kConvertVertexSourceBinding = 1;
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +010033constexpr uint32_t kImageCopySourceBinding = 0;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -050034
35uint32_t GetBufferUtilsFlags(size_t dispatchSize, const vk::Format &format)
36{
37 uint32_t flags = dispatchSize % 64 == 0 ? BufferUtils_comp::kIsAligned : 0;
38 const angle::Format &bufferFormat = format.bufferFormat();
39
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +010040 flags |= bufferFormat.isInt()
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -050041 ? BufferUtils_comp::kIsInt
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +010042 : bufferFormat.isUint() ? BufferUtils_comp::kIsUint : BufferUtils_comp::kIsFloat;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -050043
44 return flags;
45}
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +010046
Shahbaz Youssefie3219402018-12-08 16:54:14 +010047uint32_t GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters &params)
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +010048{
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +010049 bool srcIsInt = params.srcFormat->isInt();
50 bool srcIsUint = params.srcFormat->isUint();
51 bool srcIsSnorm = params.srcFormat->isSnorm();
52 bool srcIsUnorm = params.srcFormat->isUnorm();
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +010053 bool srcIsFixed = params.srcFormat->isFixed;
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +010054 bool srcIsFloat = params.srcFormat->isFloat();
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +010055
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +010056 bool destIsInt = params.destFormat->isInt();
57 bool destIsUint = params.destFormat->isUint();
58 bool destIsFloat = params.destFormat->isFloat();
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +010059
60 // Assert on the types to make sure the shader supports its. These are based on
61 // ConvertVertex_comp::Conversion values.
62 ASSERT(!destIsInt || srcIsInt); // If destination is int, src must be int too
63 ASSERT(!destIsUint || srcIsUint); // If destination is uint, src must be uint too
64 ASSERT(!srcIsFixed || destIsFloat); // If source is fixed, dest must be float
65 // One of each bool set must be true
66 ASSERT(srcIsInt || srcIsUint || srcIsSnorm || srcIsUnorm || srcIsFixed || srcIsFloat);
67 ASSERT(destIsInt || destIsUint || destIsFloat);
68
69 // We currently don't have any big-endian devices in the list of supported platforms. The
70 // shader is capable of supporting big-endian architectures, but the relevant flag (IsBigEndian)
71 // is not added to the build configuration file (to reduce binary size). If necessary, add
72 // IsBigEndian to ConvertVertex.comp.json and select the appropriate flag based on the
73 // endian-ness test here.
74 uint32_t endiannessTest = 0;
75 *reinterpret_cast<uint8_t *>(&endiannessTest) = 1;
76 ASSERT(endiannessTest == 1);
77
78 uint32_t flags = 0;
79
80 if (srcIsInt && destIsInt)
81 {
82 flags |= ConvertVertex_comp::kIntToInt;
83 }
84 else if (srcIsUint && destIsUint)
85 {
86 flags |= ConvertVertex_comp::kUintToUint;
87 }
88 else if (srcIsInt)
89 {
90 flags |= ConvertVertex_comp::kIntToFloat;
91 }
92 else if (srcIsUint)
93 {
94 flags |= ConvertVertex_comp::kUintToFloat;
95 }
96 else if (srcIsSnorm)
97 {
98 flags |= ConvertVertex_comp::kSnormToFloat;
99 }
100 else if (srcIsUnorm)
101 {
102 flags |= ConvertVertex_comp::kUnormToFloat;
103 }
104 else if (srcIsFixed)
105 {
106 flags |= ConvertVertex_comp::kFixedToFloat;
107 }
108 else if (srcIsFloat)
109 {
110 flags |= ConvertVertex_comp::kFloatToFloat;
111 }
112 else
113 {
114 UNREACHABLE();
115 }
116
117 return flags;
118}
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100119
120uint32_t GetImageCopyFlags(const vk::Format &srcFormat, const vk::Format &destFormat)
121{
122 const angle::Format &srcAngleFormat = srcFormat.angleFormat();
123 const angle::Format &destAngleFormat = destFormat.angleFormat();
124
125 uint32_t flags = 0;
126
127 flags |= srcAngleFormat.isInt() ? ImageCopy_frag::kSrcIsInt
128 : srcAngleFormat.isUint() ? ImageCopy_frag::kSrcIsUint
129 : ImageCopy_frag::kSrcIsFloat;
130 flags |= destAngleFormat.isInt() ? ImageCopy_frag::kDestIsInt
131 : destAngleFormat.isUint() ? ImageCopy_frag::kDestIsUint
132 : ImageCopy_frag::kDestIsFloat;
133
134 return flags;
135}
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500136} // namespace
137
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100138UtilsVk::UtilsVk() = default;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500139
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100140UtilsVk::~UtilsVk() = default;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500141
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100142void UtilsVk::destroy(VkDevice device)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500143{
144 for (Function f : angle::AllEnums<Function>())
145 {
146 for (auto &descriptorSetLayout : mDescriptorSetLayouts[f])
147 {
148 descriptorSetLayout.reset();
149 }
150 mPipelineLayouts[f].reset();
151 mDescriptorPools[f].destroy(device);
152 }
153
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100154 for (vk::ShaderProgramHelper &program : mBufferUtilsPrograms)
155 {
156 program.destroy(device);
157 }
158 for (vk::ShaderProgramHelper &program : mConvertVertexPrograms)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500159 {
160 program.destroy(device);
161 }
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100162 mImageClearProgram.destroy(device);
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100163 for (vk::ShaderProgramHelper &program : mImageCopyPrograms)
164 {
165 program.destroy(device);
166 }
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500167}
168
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100169angle::Result UtilsVk::ensureResourcesInitialized(vk::Context *context,
170 Function function,
171 VkDescriptorPoolSize *setSizes,
172 size_t setSizesCount,
173 size_t pushConstantsSize)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500174{
175 RendererVk *renderer = context->getRenderer();
176
177 vk::DescriptorSetLayoutDesc descriptorSetDesc;
178
179 uint32_t currentBinding = 0;
180 for (size_t i = 0; i < setSizesCount; ++i)
181 {
182 descriptorSetDesc.update(currentBinding, setSizes[i].type, setSizes[i].descriptorCount);
183 currentBinding += setSizes[i].descriptorCount;
184 }
185
186 ANGLE_TRY(renderer->getDescriptorSetLayout(context, descriptorSetDesc,
187 &mDescriptorSetLayouts[function][kSetIndex]));
188
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100189 gl::ShaderType pushConstantsShaderStage = function >= Function::ComputeStartIndex
190 ? gl::ShaderType::Compute
191 : gl::ShaderType::Fragment;
192
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500193 // Corresponding pipeline layouts:
194 vk::PipelineLayoutDesc pipelineLayoutDesc;
195
196 pipelineLayoutDesc.updateDescriptorSetLayout(kSetIndex, descriptorSetDesc);
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100197 pipelineLayoutDesc.updatePushConstantRange(pushConstantsShaderStage, 0, pushConstantsSize);
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500198
199 ANGLE_TRY(renderer->getPipelineLayout(
200 context, pipelineLayoutDesc, mDescriptorSetLayouts[function], &mPipelineLayouts[function]));
201
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100202 if (setSizesCount > 0)
203 {
204 ANGLE_TRY(mDescriptorPools[function].init(context, setSizes, setSizesCount));
205 }
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500206
Jamie Madill7c985f52018-11-29 18:16:17 -0500207 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500208}
209
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100210angle::Result UtilsVk::ensureBufferClearResourcesInitialized(vk::Context *context)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500211{
212 if (mPipelineLayouts[Function::BufferClear].valid())
213 {
Jamie Madill7c985f52018-11-29 18:16:17 -0500214 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500215 }
216
217 VkDescriptorPoolSize setSizes[1] = {
218 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1},
219 };
220
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100221 return ensureResourcesInitialized(context, Function::BufferClear, setSizes, ArraySize(setSizes),
222 sizeof(BufferUtilsShaderParams));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500223}
224
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100225angle::Result UtilsVk::ensureBufferCopyResourcesInitialized(vk::Context *context)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500226{
227 if (mPipelineLayouts[Function::BufferCopy].valid())
228 {
Jamie Madill7c985f52018-11-29 18:16:17 -0500229 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500230 }
231
232 VkDescriptorPoolSize setSizes[2] = {
233 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1},
234 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1},
235 };
236
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100237 return ensureResourcesInitialized(context, Function::BufferCopy, setSizes, ArraySize(setSizes),
238 sizeof(BufferUtilsShaderParams));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500239}
240
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100241angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(vk::Context *context)
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100242{
243 if (mPipelineLayouts[Function::ConvertVertexBuffer].valid())
244 {
245 return angle::Result::Continue;
246 }
247
248 VkDescriptorPoolSize setSizes[2] = {
249 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
250 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
251 };
252
253 return ensureResourcesInitialized(context, Function::ConvertVertexBuffer, setSizes,
254 ArraySize(setSizes), sizeof(ConvertVertexShaderParams));
255}
256
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100257angle::Result UtilsVk::ensureImageClearResourcesInitialized(vk::Context *context)
258{
259 if (mPipelineLayouts[Function::ImageClear].valid())
260 {
261 return angle::Result::Continue;
262 }
263
264 // The shader does not use any descriptor sets.
265 return ensureResourcesInitialized(context, Function::ImageClear, nullptr, 0,
266 sizeof(ImageClearShaderParams));
267}
268
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100269angle::Result UtilsVk::ensureImageCopyResourcesInitialized(vk::Context *context)
270{
271 if (mPipelineLayouts[Function::ImageCopy].valid())
272 {
273 return angle::Result::Continue;
274 }
275
276 VkDescriptorPoolSize setSizes[1] = {
277 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
278 };
279
280 return ensureResourcesInitialized(context, Function::ImageCopy, setSizes, ArraySize(setSizes),
281 sizeof(ImageCopyShaderParams));
282}
283
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100284angle::Result UtilsVk::setupProgram(vk::Context *context,
285 Function function,
286 vk::RefCounted<vk::ShaderAndSerial> *fsCsShader,
287 vk::RefCounted<vk::ShaderAndSerial> *vsShader,
288 vk::ShaderProgramHelper *program,
289 const vk::GraphicsPipelineDesc *pipelineDesc,
290 const VkDescriptorSet descriptorSet,
291 const void *pushConstants,
292 size_t pushConstantsSize,
293 vk::CommandBuffer *commandBuffer)
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100294{
295 RendererVk *renderer = context->getRenderer();
296
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100297 bool isCompute = function >= Function::ComputeStartIndex;
298 VkPipelineBindPoint bindPoint =
299 isCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
300 VkShaderStageFlags pushConstantsShaderStage =
301 isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
302
303 // If compute, vsShader and pipelineDesc should be nullptr, and if not compute they shouldn't
304 // be.
305 ASSERT(isCompute != (vsShader && pipelineDesc));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100306
307 const vk::BindingPointer<vk::PipelineLayout> &pipelineLayout = mPipelineLayouts[function];
308
309 vk::PipelineAndSerial *pipelineAndSerial;
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100310 if (isCompute)
311 {
312 program->setShader(gl::ShaderType::Compute, fsCsShader);
313 ANGLE_TRY(program->getComputePipeline(context, pipelineLayout.get(), &pipelineAndSerial));
314 }
315 else
316 {
317 program->setShader(gl::ShaderType::Vertex, vsShader);
318 program->setShader(gl::ShaderType::Fragment, fsCsShader);
319 ANGLE_TRY(program->getGraphicsPipeline(context, pipelineLayout.get(), *pipelineDesc,
320 gl::AttributesMask(), &pipelineAndSerial));
321 }
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100322
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100323 commandBuffer->bindPipeline(bindPoint, pipelineAndSerial->get());
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100324 pipelineAndSerial->updateSerial(renderer->getCurrentQueueSerial());
325
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100326 if (descriptorSet != VK_NULL_HANDLE)
327 {
328 commandBuffer->bindDescriptorSets(bindPoint, pipelineLayout.get(), 0, 1, &descriptorSet, 0,
329 nullptr);
330 }
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100331
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100332 commandBuffer->pushConstants(pipelineLayout.get(), pushConstantsShaderStage, 0,
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100333 pushConstantsSize, pushConstants);
334
335 return angle::Result::Continue;
336}
337
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100338angle::Result UtilsVk::clearBuffer(vk::Context *context,
339 vk::BufferHelper *dest,
340 const ClearParameters &params)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500341{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100342 RendererVk *renderer = context->getRenderer();
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500343
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100344 ANGLE_TRY(ensureBufferClearResourcesInitialized(context));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500345
346 vk::CommandBuffer *commandBuffer;
347 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
348
349 // Tell dest it's being written to.
350 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
351
352 const vk::Format &destFormat = dest->getViewFormat();
353
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100354 uint32_t flags = BufferUtils_comp::kIsClear | GetBufferUtilsFlags(params.size, destFormat);
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500355
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100356 BufferUtilsShaderParams shaderParams;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500357 shaderParams.destOffset = params.offset;
358 shaderParams.size = params.size;
359 shaderParams.clearValue = params.clearValue;
360
361 VkDescriptorSet descriptorSet;
362 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
363 ANGLE_TRY(mDescriptorPools[Function::BufferClear].allocateSets(
364 context, mDescriptorSetLayouts[Function::BufferClear][kSetIndex].get().ptr(), 1,
365 &descriptorPoolBinding, &descriptorSet));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100366 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500367
368 VkWriteDescriptorSet writeInfo = {};
369
370 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
371 writeInfo.dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100372 writeInfo.dstBinding = kBufferClearOutputBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500373 writeInfo.descriptorCount = 1;
374 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
375 writeInfo.pTexelBufferView = dest->getBufferView().ptr();
376
377 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
378
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100379 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
380 ANGLE_TRY(renderer->getShaderLibrary().getBufferUtils_comp(context, flags, &shader));
381
382 ANGLE_TRY(setupProgram(context, Function::BufferClear, shader, nullptr,
383 &mBufferUtilsPrograms[flags], nullptr, descriptorSet, &shaderParams,
384 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500385
386 commandBuffer->dispatch(UnsignedCeilDivide(params.size, 64), 1, 1);
387
388 descriptorPoolBinding.reset();
389
Jamie Madill7c985f52018-11-29 18:16:17 -0500390 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500391}
392
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100393angle::Result UtilsVk::copyBuffer(vk::Context *context,
394 vk::BufferHelper *dest,
395 vk::BufferHelper *src,
396 const CopyParameters &params)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500397{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100398 RendererVk *renderer = context->getRenderer();
399
400 ANGLE_TRY(ensureBufferCopyResourcesInitialized(context));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500401
402 vk::CommandBuffer *commandBuffer;
403 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
404
405 // Tell src we are going to read from it.
406 src->onRead(dest, VK_ACCESS_SHADER_READ_BIT);
407 // Tell dest it's being written to.
408 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
409
410 const vk::Format &destFormat = dest->getViewFormat();
411 const vk::Format &srcFormat = src->getViewFormat();
412
413 ASSERT(destFormat.vkFormatIsInt == srcFormat.vkFormatIsInt);
414 ASSERT(destFormat.vkFormatIsUnsigned == srcFormat.vkFormatIsUnsigned);
415
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100416 uint32_t flags = BufferUtils_comp::kIsCopy | GetBufferUtilsFlags(params.size, destFormat);
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500417
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100418 BufferUtilsShaderParams shaderParams;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500419 shaderParams.destOffset = params.destOffset;
420 shaderParams.size = params.size;
421 shaderParams.srcOffset = params.srcOffset;
422
423 VkDescriptorSet descriptorSet;
424 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
425 ANGLE_TRY(mDescriptorPools[Function::BufferCopy].allocateSets(
426 context, mDescriptorSetLayouts[Function::BufferCopy][kSetIndex].get().ptr(), 1,
427 &descriptorPoolBinding, &descriptorSet));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100428 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500429
430 VkWriteDescriptorSet writeInfo[2] = {};
431
432 writeInfo[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
433 writeInfo[0].dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100434 writeInfo[0].dstBinding = kBufferCopyDestinationBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500435 writeInfo[0].descriptorCount = 1;
436 writeInfo[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
437 writeInfo[0].pTexelBufferView = dest->getBufferView().ptr();
438
439 writeInfo[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
440 writeInfo[1].dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100441 writeInfo[1].dstBinding = kBufferCopySourceBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500442 writeInfo[1].descriptorCount = 1;
443 writeInfo[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
444 writeInfo[1].pTexelBufferView = src->getBufferView().ptr();
445
446 vkUpdateDescriptorSets(context->getDevice(), 2, writeInfo, 0, nullptr);
447
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100448 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
449 ANGLE_TRY(renderer->getShaderLibrary().getBufferUtils_comp(context, flags, &shader));
450
451 ANGLE_TRY(setupProgram(context, Function::BufferCopy, shader, nullptr,
452 &mBufferUtilsPrograms[flags], nullptr, descriptorSet, &shaderParams,
453 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500454
455 commandBuffer->dispatch(UnsignedCeilDivide(params.size, 64), 1, 1);
456
457 descriptorPoolBinding.reset();
458
Jamie Madill7c985f52018-11-29 18:16:17 -0500459 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500460}
461
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100462angle::Result UtilsVk::convertVertexBuffer(vk::Context *context,
463 vk::BufferHelper *dest,
464 vk::BufferHelper *src,
465 const ConvertVertexParameters &params)
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100466{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100467 RendererVk *renderer = context->getRenderer();
468
469 ANGLE_TRY(ensureConvertVertexResourcesInitialized(context));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100470
471 vk::CommandBuffer *commandBuffer;
472 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
473
474 // Tell src we are going to read from it.
475 src->onRead(dest, VK_ACCESS_SHADER_READ_BIT);
476 // Tell dest it's being written to.
477 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
478
479 ConvertVertexShaderParams shaderParams;
480 shaderParams.Ns = params.srcFormat->channelCount();
481 shaderParams.Bs = params.srcFormat->pixelBytes / params.srcFormat->channelCount();
482 shaderParams.Ss = params.srcStride;
483 shaderParams.Nd = params.destFormat->channelCount();
484 shaderParams.Bd = params.destFormat->pixelBytes / params.destFormat->channelCount();
485 shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
486 // The component size is expected to either be 1, 2 or 4 bytes.
487 ASSERT(4 % shaderParams.Bs == 0);
488 ASSERT(4 % shaderParams.Bd == 0);
489 shaderParams.Es = 4 / shaderParams.Bs;
490 shaderParams.Ed = 4 / shaderParams.Bd;
491 // Total number of output components is simply the number of vertices by number of components in
492 // each.
493 shaderParams.componentCount = params.vertexCount * shaderParams.Nd;
494 // Total number of 4-byte outputs is the number of components divided by how many components can
495 // fit in a 4-byte value. Note that this value is also the invocation size of the shader.
496 shaderParams.outputCount = shaderParams.componentCount / shaderParams.Ed;
497 shaderParams.srcOffset = params.srcOffset;
498 shaderParams.destOffset = params.destOffset;
499
500 uint32_t flags = GetConvertVertexFlags(params);
501
502 bool isAligned =
503 shaderParams.outputCount % 64 == 0 && shaderParams.componentCount % shaderParams.Ed == 0;
504 flags |= isAligned ? ConvertVertex_comp::kIsAligned : 0;
505
506 VkDescriptorSet descriptorSet;
507 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
508 ANGLE_TRY(mDescriptorPools[Function::ConvertVertexBuffer].allocateSets(
509 context, mDescriptorSetLayouts[Function::ConvertVertexBuffer][kSetIndex].get().ptr(), 1,
510 &descriptorPoolBinding, &descriptorSet));
511 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
512
513 VkWriteDescriptorSet writeInfo = {};
514 VkDescriptorBufferInfo buffers[2] = {
515 {dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
516 {src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
517 };
518 static_assert(kConvertVertexDestinationBinding + 1 == kConvertVertexSourceBinding,
519 "Update write info");
520
521 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
522 writeInfo.dstSet = descriptorSet;
523 writeInfo.dstBinding = kConvertVertexDestinationBinding;
524 writeInfo.descriptorCount = 2;
525 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
526 writeInfo.pBufferInfo = buffers;
527
528 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
529
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100530 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
531 ANGLE_TRY(renderer->getShaderLibrary().getConvertVertex_comp(context, flags, &shader));
532
533 ANGLE_TRY(setupProgram(context, Function::ConvertVertexBuffer, shader, nullptr,
534 &mConvertVertexPrograms[flags], nullptr, descriptorSet, &shaderParams,
535 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100536
537 commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
538
539 descriptorPoolBinding.reset();
540
541 return angle::Result::Continue;
542}
543
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100544angle::Result UtilsVk::startRenderPass(vk::Context *context,
545 vk::ImageHelper *image,
546 vk::ImageView *imageView,
547 const vk::RenderPassDesc &renderPassDesc,
548 const gl::Rectangle &renderArea,
549 vk::CommandBuffer **commandBufferOut)
550{
551 RendererVk *renderer = context->getRenderer();
552
553 vk::RenderPass *renderPass = nullptr;
554 ANGLE_TRY(renderer->getCompatibleRenderPass(context, renderPassDesc, &renderPass));
555
556 VkFramebufferCreateInfo framebufferInfo = {};
557
558 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
559 framebufferInfo.flags = 0;
560 framebufferInfo.renderPass = renderPass->getHandle();
561 framebufferInfo.attachmentCount = 1;
562 framebufferInfo.pAttachments = imageView->ptr();
563 framebufferInfo.width = renderArea.x + renderArea.width;
564 framebufferInfo.height = renderArea.y + renderArea.height;
565 framebufferInfo.layers = 1;
566
567 vk::Framebuffer framebuffer;
568 ANGLE_VK_TRY(context, framebuffer.init(context->getDevice(), framebufferInfo));
569
570 // TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
571 std::vector<VkClearValue> clearValues = {{}};
572 ASSERT(clearValues.size() == 1);
573
574 ANGLE_TRY(image->beginRenderPass(context, framebuffer, renderArea, renderPassDesc, clearValues,
575 commandBufferOut));
576
577 renderer->releaseObject(renderer->getCurrentQueueSerial(), &framebuffer);
578
579 return angle::Result::Continue;
580}
581
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100582angle::Result UtilsVk::clearImage(ContextVk *contextVk,
583 FramebufferVk *framebuffer,
584 const ClearImageParameters &params)
585{
586 RendererVk *renderer = contextVk->getRenderer();
587
588 ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
589
590 vk::CommandBuffer *commandBuffer;
591 if (!framebuffer->appendToStartedRenderPass(contextVk->getRenderer(), &commandBuffer))
592 {
593 ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, &commandBuffer))
594 }
595
596 ImageClearShaderParams shaderParams;
597 shaderParams.clearValue = params.clearValue;
598
599 vk::GraphicsPipelineDesc pipelineDesc;
600 pipelineDesc.initDefaults();
601 pipelineDesc.updateColorWriteMask(params.colorMaskFlags, *params.alphaMask);
602 pipelineDesc.updateRenderPassDesc(*params.renderPassDesc);
603
604 vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
605 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
606 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
607 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
608 ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, 0, &fragmentShader));
609
610 ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
611 &mImageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
612 sizeof(shaderParams), commandBuffer));
613
614 VkViewport viewport;
615 const gl::Rectangle &renderArea = framebuffer->getFramebuffer()->getRenderPassRenderArea();
616 bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
617 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, invertViewport, params.renderAreaHeight, &viewport);
618
619 VkRect2D scissor;
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500620 const gl::State &glState = contextVk->getState();
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100621 gl_vk::GetScissor(glState, invertViewport, renderArea, &scissor);
622
623 commandBuffer->setViewport(0, 1, &viewport);
624 commandBuffer->setScissor(0, 1, &scissor);
625 commandBuffer->draw(6, 1, 0, 0);
626
627 return angle::Result::Continue;
628}
629
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100630angle::Result UtilsVk::copyImage(vk::Context *context,
631 vk::ImageHelper *dest,
632 vk::ImageView *destView,
633 vk::ImageHelper *src,
634 vk::ImageView *srcView,
635 const CopyImageParameters &params)
636{
637 RendererVk *renderer = context->getRenderer();
638
639 ANGLE_TRY(ensureImageCopyResourcesInitialized(context));
640
641 const vk::Format &srcFormat = src->getFormat();
642 const vk::Format &destFormat = dest->getFormat();
643
644 ImageCopyShaderParams shaderParams;
645 shaderParams.flipY = params.flipY;
646 shaderParams.destHasLuminance = destFormat.angleFormat().luminanceBits > 0;
647 shaderParams.destIsAlpha =
648 destFormat.angleFormat().isLUMA() && destFormat.angleFormat().alphaBits > 0;
649 shaderParams.srcMip = params.srcMip;
650 shaderParams.srcOffset[0] = params.srcOffset[0];
651 shaderParams.srcOffset[1] = params.srcOffset[1];
652 shaderParams.destOffset[0] = params.destOffset[0];
653 shaderParams.destOffset[1] = params.destOffset[1];
654
655 if (params.flipY)
656 {
657 // If viewport is flipped, the shader expects srcOffset[1] to have the
658 // last row's index instead of the first's.
659 shaderParams.srcOffset[1] = params.srcHeight - shaderParams.srcOffset[1] - 1;
660 }
661
662 uint32_t flags = GetImageCopyFlags(srcFormat, destFormat);
663
664 VkDescriptorSet descriptorSet;
665 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
666 ANGLE_TRY(mDescriptorPools[Function::ImageCopy].allocateSets(
667 context, mDescriptorSetLayouts[Function::ImageCopy][kSetIndex].get().ptr(), 1,
668 &descriptorPoolBinding, &descriptorSet));
669 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
670
671 vk::RenderPassDesc renderPassDesc;
672 renderPassDesc.setSamples(dest->getSamples());
673 renderPassDesc.packAttachment(destFormat);
674
675 vk::GraphicsPipelineDesc pipelineDesc;
676 pipelineDesc.initDefaults();
677 pipelineDesc.updateRenderPassDesc(renderPassDesc);
678
679 gl::Rectangle renderArea;
680 renderArea.x = params.destOffset[0];
681 renderArea.y = params.destOffset[1];
682 renderArea.width = params.srcExtents[0];
683 renderArea.height = params.srcExtents[1];
684
685 // Change source layout outside render pass
686 vk::CommandBuffer *srcLayoutChange;
687 ANGLE_TRY(src->recordCommands(context, &srcLayoutChange));
688
689 src->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
690 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
691 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, srcLayoutChange);
692
693 // Change destination layout outside render pass as well
694 vk::CommandBuffer *destLayoutChange;
695 ANGLE_TRY(dest->recordCommands(context, &destLayoutChange));
696
697 dest->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT,
698 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
699 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
700 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, destLayoutChange);
701
702 vk::CommandBuffer *commandBuffer;
703 ANGLE_TRY(startRenderPass(context, dest, destView, renderPassDesc, renderArea, &commandBuffer));
704
705 // Source's layout change should happen before rendering
706 src->addReadDependency(dest);
707
708 VkDescriptorImageInfo imageInfo = {};
709 imageInfo.imageView = srcView->getHandle();
710 imageInfo.imageLayout = src->getCurrentLayout();
711
712 VkWriteDescriptorSet writeInfo = {};
713 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
714 writeInfo.dstSet = descriptorSet;
715 writeInfo.dstBinding = kImageCopySourceBinding;
716 writeInfo.descriptorCount = 1;
717 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
718 writeInfo.pImageInfo = &imageInfo;
719
720 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
721
722 vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
723 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
724 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
725 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(context, 0, &vertexShader));
726 ANGLE_TRY(shaderLibrary.getImageCopy_frag(context, flags, &fragmentShader));
727
728 ANGLE_TRY(setupProgram(context, Function::ImageCopy, fragmentShader, vertexShader,
729 &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
730 sizeof(shaderParams), commandBuffer));
731
732 VkViewport viewport;
733 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, dest->getExtents().height, &viewport);
734
735 VkRect2D scissor = gl_vk::GetRect(renderArea);
736
737 commandBuffer->setViewport(0, 1, &viewport);
738 commandBuffer->setScissor(0, 1, &scissor);
739 commandBuffer->draw(6, 1, 0, 0);
740
741 descriptorPoolBinding.reset();
742
743 return angle::Result::Continue;
744}
745
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500746} // namespace rx