blob: 31168c3f26d741078f0d0c83778cd0d98dce7a52 [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
Jamie Madilldbc605c2019-01-04 16:39:14 -0500309 Serial serial = renderer->getCurrentQueueSerial();
310
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100311 vk::PipelineAndSerial *pipelineAndSerial;
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100312 if (isCompute)
313 {
314 program->setShader(gl::ShaderType::Compute, fsCsShader);
315 ANGLE_TRY(program->getComputePipeline(context, pipelineLayout.get(), &pipelineAndSerial));
316 }
317 else
318 {
319 program->setShader(gl::ShaderType::Vertex, vsShader);
320 program->setShader(gl::ShaderType::Fragment, fsCsShader);
Jamie Madilldbc605c2019-01-04 16:39:14 -0500321
322 ANGLE_TRY(program->getGraphicsPipeline(
323 context, &renderer->getRenderPassCache(), renderer->getPipelineCache(), serial,
324 pipelineLayout.get(), *pipelineDesc, gl::AttributesMask(), &pipelineAndSerial));
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100325 }
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100326
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100327 commandBuffer->bindPipeline(bindPoint, pipelineAndSerial->get());
Jamie Madilldbc605c2019-01-04 16:39:14 -0500328 pipelineAndSerial->updateSerial(serial);
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100329
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100330 if (descriptorSet != VK_NULL_HANDLE)
331 {
332 commandBuffer->bindDescriptorSets(bindPoint, pipelineLayout.get(), 0, 1, &descriptorSet, 0,
333 nullptr);
334 }
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100335
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100336 commandBuffer->pushConstants(pipelineLayout.get(), pushConstantsShaderStage, 0,
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100337 pushConstantsSize, pushConstants);
338
339 return angle::Result::Continue;
340}
341
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100342angle::Result UtilsVk::clearBuffer(vk::Context *context,
343 vk::BufferHelper *dest,
344 const ClearParameters &params)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500345{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100346 RendererVk *renderer = context->getRenderer();
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500347
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100348 ANGLE_TRY(ensureBufferClearResourcesInitialized(context));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500349
350 vk::CommandBuffer *commandBuffer;
351 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
352
353 // Tell dest it's being written to.
354 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
355
356 const vk::Format &destFormat = dest->getViewFormat();
357
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100358 uint32_t flags = BufferUtils_comp::kIsClear | GetBufferUtilsFlags(params.size, destFormat);
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500359
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100360 BufferUtilsShaderParams shaderParams;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500361 shaderParams.destOffset = params.offset;
362 shaderParams.size = params.size;
363 shaderParams.clearValue = params.clearValue;
364
365 VkDescriptorSet descriptorSet;
366 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
367 ANGLE_TRY(mDescriptorPools[Function::BufferClear].allocateSets(
368 context, mDescriptorSetLayouts[Function::BufferClear][kSetIndex].get().ptr(), 1,
369 &descriptorPoolBinding, &descriptorSet));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100370 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500371
372 VkWriteDescriptorSet writeInfo = {};
373
374 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
375 writeInfo.dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100376 writeInfo.dstBinding = kBufferClearOutputBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500377 writeInfo.descriptorCount = 1;
378 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
379 writeInfo.pTexelBufferView = dest->getBufferView().ptr();
380
381 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
382
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100383 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
384 ANGLE_TRY(renderer->getShaderLibrary().getBufferUtils_comp(context, flags, &shader));
385
386 ANGLE_TRY(setupProgram(context, Function::BufferClear, shader, nullptr,
387 &mBufferUtilsPrograms[flags], nullptr, descriptorSet, &shaderParams,
388 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500389
390 commandBuffer->dispatch(UnsignedCeilDivide(params.size, 64), 1, 1);
391
392 descriptorPoolBinding.reset();
393
Jamie Madill7c985f52018-11-29 18:16:17 -0500394 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500395}
396
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100397angle::Result UtilsVk::copyBuffer(vk::Context *context,
398 vk::BufferHelper *dest,
399 vk::BufferHelper *src,
400 const CopyParameters &params)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500401{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100402 RendererVk *renderer = context->getRenderer();
403
404 ANGLE_TRY(ensureBufferCopyResourcesInitialized(context));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500405
406 vk::CommandBuffer *commandBuffer;
407 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
408
409 // Tell src we are going to read from it.
410 src->onRead(dest, VK_ACCESS_SHADER_READ_BIT);
411 // Tell dest it's being written to.
412 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
413
414 const vk::Format &destFormat = dest->getViewFormat();
415 const vk::Format &srcFormat = src->getViewFormat();
416
417 ASSERT(destFormat.vkFormatIsInt == srcFormat.vkFormatIsInt);
418 ASSERT(destFormat.vkFormatIsUnsigned == srcFormat.vkFormatIsUnsigned);
419
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100420 uint32_t flags = BufferUtils_comp::kIsCopy | GetBufferUtilsFlags(params.size, destFormat);
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500421
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100422 BufferUtilsShaderParams shaderParams;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500423 shaderParams.destOffset = params.destOffset;
424 shaderParams.size = params.size;
425 shaderParams.srcOffset = params.srcOffset;
426
427 VkDescriptorSet descriptorSet;
428 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
429 ANGLE_TRY(mDescriptorPools[Function::BufferCopy].allocateSets(
430 context, mDescriptorSetLayouts[Function::BufferCopy][kSetIndex].get().ptr(), 1,
431 &descriptorPoolBinding, &descriptorSet));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100432 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500433
434 VkWriteDescriptorSet writeInfo[2] = {};
435
436 writeInfo[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
437 writeInfo[0].dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100438 writeInfo[0].dstBinding = kBufferCopyDestinationBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500439 writeInfo[0].descriptorCount = 1;
440 writeInfo[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
441 writeInfo[0].pTexelBufferView = dest->getBufferView().ptr();
442
443 writeInfo[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
444 writeInfo[1].dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100445 writeInfo[1].dstBinding = kBufferCopySourceBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500446 writeInfo[1].descriptorCount = 1;
447 writeInfo[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
448 writeInfo[1].pTexelBufferView = src->getBufferView().ptr();
449
450 vkUpdateDescriptorSets(context->getDevice(), 2, writeInfo, 0, nullptr);
451
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100452 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
453 ANGLE_TRY(renderer->getShaderLibrary().getBufferUtils_comp(context, flags, &shader));
454
455 ANGLE_TRY(setupProgram(context, Function::BufferCopy, shader, nullptr,
456 &mBufferUtilsPrograms[flags], nullptr, descriptorSet, &shaderParams,
457 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500458
459 commandBuffer->dispatch(UnsignedCeilDivide(params.size, 64), 1, 1);
460
461 descriptorPoolBinding.reset();
462
Jamie Madill7c985f52018-11-29 18:16:17 -0500463 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500464}
465
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100466angle::Result UtilsVk::convertVertexBuffer(vk::Context *context,
467 vk::BufferHelper *dest,
468 vk::BufferHelper *src,
469 const ConvertVertexParameters &params)
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100470{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100471 RendererVk *renderer = context->getRenderer();
472
473 ANGLE_TRY(ensureConvertVertexResourcesInitialized(context));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100474
475 vk::CommandBuffer *commandBuffer;
476 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
477
478 // Tell src we are going to read from it.
479 src->onRead(dest, VK_ACCESS_SHADER_READ_BIT);
480 // Tell dest it's being written to.
481 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
482
483 ConvertVertexShaderParams shaderParams;
484 shaderParams.Ns = params.srcFormat->channelCount();
485 shaderParams.Bs = params.srcFormat->pixelBytes / params.srcFormat->channelCount();
486 shaderParams.Ss = params.srcStride;
487 shaderParams.Nd = params.destFormat->channelCount();
488 shaderParams.Bd = params.destFormat->pixelBytes / params.destFormat->channelCount();
489 shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
490 // The component size is expected to either be 1, 2 or 4 bytes.
491 ASSERT(4 % shaderParams.Bs == 0);
492 ASSERT(4 % shaderParams.Bd == 0);
493 shaderParams.Es = 4 / shaderParams.Bs;
494 shaderParams.Ed = 4 / shaderParams.Bd;
495 // Total number of output components is simply the number of vertices by number of components in
496 // each.
497 shaderParams.componentCount = params.vertexCount * shaderParams.Nd;
498 // Total number of 4-byte outputs is the number of components divided by how many components can
499 // fit in a 4-byte value. Note that this value is also the invocation size of the shader.
500 shaderParams.outputCount = shaderParams.componentCount / shaderParams.Ed;
501 shaderParams.srcOffset = params.srcOffset;
502 shaderParams.destOffset = params.destOffset;
503
504 uint32_t flags = GetConvertVertexFlags(params);
505
506 bool isAligned =
507 shaderParams.outputCount % 64 == 0 && shaderParams.componentCount % shaderParams.Ed == 0;
508 flags |= isAligned ? ConvertVertex_comp::kIsAligned : 0;
509
510 VkDescriptorSet descriptorSet;
511 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
512 ANGLE_TRY(mDescriptorPools[Function::ConvertVertexBuffer].allocateSets(
513 context, mDescriptorSetLayouts[Function::ConvertVertexBuffer][kSetIndex].get().ptr(), 1,
514 &descriptorPoolBinding, &descriptorSet));
515 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
516
517 VkWriteDescriptorSet writeInfo = {};
518 VkDescriptorBufferInfo buffers[2] = {
519 {dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
520 {src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
521 };
522 static_assert(kConvertVertexDestinationBinding + 1 == kConvertVertexSourceBinding,
523 "Update write info");
524
525 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
526 writeInfo.dstSet = descriptorSet;
527 writeInfo.dstBinding = kConvertVertexDestinationBinding;
528 writeInfo.descriptorCount = 2;
529 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
530 writeInfo.pBufferInfo = buffers;
531
532 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
533
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100534 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
535 ANGLE_TRY(renderer->getShaderLibrary().getConvertVertex_comp(context, flags, &shader));
536
537 ANGLE_TRY(setupProgram(context, Function::ConvertVertexBuffer, shader, nullptr,
538 &mConvertVertexPrograms[flags], nullptr, descriptorSet, &shaderParams,
539 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100540
541 commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
542
543 descriptorPoolBinding.reset();
544
545 return angle::Result::Continue;
546}
547
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100548angle::Result UtilsVk::startRenderPass(vk::Context *context,
549 vk::ImageHelper *image,
550 vk::ImageView *imageView,
551 const vk::RenderPassDesc &renderPassDesc,
552 const gl::Rectangle &renderArea,
553 vk::CommandBuffer **commandBufferOut)
554{
555 RendererVk *renderer = context->getRenderer();
556
557 vk::RenderPass *renderPass = nullptr;
558 ANGLE_TRY(renderer->getCompatibleRenderPass(context, renderPassDesc, &renderPass));
559
560 VkFramebufferCreateInfo framebufferInfo = {};
561
562 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
563 framebufferInfo.flags = 0;
564 framebufferInfo.renderPass = renderPass->getHandle();
565 framebufferInfo.attachmentCount = 1;
566 framebufferInfo.pAttachments = imageView->ptr();
567 framebufferInfo.width = renderArea.x + renderArea.width;
568 framebufferInfo.height = renderArea.y + renderArea.height;
569 framebufferInfo.layers = 1;
570
571 vk::Framebuffer framebuffer;
572 ANGLE_VK_TRY(context, framebuffer.init(context->getDevice(), framebufferInfo));
573
574 // TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
575 std::vector<VkClearValue> clearValues = {{}};
576 ASSERT(clearValues.size() == 1);
577
578 ANGLE_TRY(image->beginRenderPass(context, framebuffer, renderArea, renderPassDesc, clearValues,
579 commandBufferOut));
580
581 renderer->releaseObject(renderer->getCurrentQueueSerial(), &framebuffer);
582
583 return angle::Result::Continue;
584}
585
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100586angle::Result UtilsVk::clearImage(ContextVk *contextVk,
587 FramebufferVk *framebuffer,
588 const ClearImageParameters &params)
589{
590 RendererVk *renderer = contextVk->getRenderer();
591
592 ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
593
594 vk::CommandBuffer *commandBuffer;
595 if (!framebuffer->appendToStartedRenderPass(contextVk->getRenderer(), &commandBuffer))
596 {
597 ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, &commandBuffer))
598 }
599
600 ImageClearShaderParams shaderParams;
601 shaderParams.clearValue = params.clearValue;
602
603 vk::GraphicsPipelineDesc pipelineDesc;
604 pipelineDesc.initDefaults();
605 pipelineDesc.updateColorWriteMask(params.colorMaskFlags, *params.alphaMask);
606 pipelineDesc.updateRenderPassDesc(*params.renderPassDesc);
607
608 vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
609 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
610 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
611 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
612 ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, 0, &fragmentShader));
613
614 ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
615 &mImageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
616 sizeof(shaderParams), commandBuffer));
617
618 VkViewport viewport;
619 const gl::Rectangle &renderArea = framebuffer->getFramebuffer()->getRenderPassRenderArea();
620 bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
621 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, invertViewport, params.renderAreaHeight, &viewport);
622
623 VkRect2D scissor;
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500624 const gl::State &glState = contextVk->getState();
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100625 gl_vk::GetScissor(glState, invertViewport, renderArea, &scissor);
626
627 commandBuffer->setViewport(0, 1, &viewport);
628 commandBuffer->setScissor(0, 1, &scissor);
629 commandBuffer->draw(6, 1, 0, 0);
630
631 return angle::Result::Continue;
632}
633
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100634angle::Result UtilsVk::copyImage(vk::Context *context,
635 vk::ImageHelper *dest,
636 vk::ImageView *destView,
637 vk::ImageHelper *src,
638 vk::ImageView *srcView,
639 const CopyImageParameters &params)
640{
641 RendererVk *renderer = context->getRenderer();
642
643 ANGLE_TRY(ensureImageCopyResourcesInitialized(context));
644
645 const vk::Format &srcFormat = src->getFormat();
646 const vk::Format &destFormat = dest->getFormat();
647
648 ImageCopyShaderParams shaderParams;
649 shaderParams.flipY = params.flipY;
650 shaderParams.destHasLuminance = destFormat.angleFormat().luminanceBits > 0;
651 shaderParams.destIsAlpha =
652 destFormat.angleFormat().isLUMA() && destFormat.angleFormat().alphaBits > 0;
653 shaderParams.srcMip = params.srcMip;
654 shaderParams.srcOffset[0] = params.srcOffset[0];
655 shaderParams.srcOffset[1] = params.srcOffset[1];
656 shaderParams.destOffset[0] = params.destOffset[0];
657 shaderParams.destOffset[1] = params.destOffset[1];
658
659 if (params.flipY)
660 {
661 // If viewport is flipped, the shader expects srcOffset[1] to have the
662 // last row's index instead of the first's.
663 shaderParams.srcOffset[1] = params.srcHeight - shaderParams.srcOffset[1] - 1;
664 }
665
666 uint32_t flags = GetImageCopyFlags(srcFormat, destFormat);
667
668 VkDescriptorSet descriptorSet;
669 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
670 ANGLE_TRY(mDescriptorPools[Function::ImageCopy].allocateSets(
671 context, mDescriptorSetLayouts[Function::ImageCopy][kSetIndex].get().ptr(), 1,
672 &descriptorPoolBinding, &descriptorSet));
673 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
674
675 vk::RenderPassDesc renderPassDesc;
676 renderPassDesc.setSamples(dest->getSamples());
677 renderPassDesc.packAttachment(destFormat);
678
679 vk::GraphicsPipelineDesc pipelineDesc;
680 pipelineDesc.initDefaults();
681 pipelineDesc.updateRenderPassDesc(renderPassDesc);
682
683 gl::Rectangle renderArea;
684 renderArea.x = params.destOffset[0];
685 renderArea.y = params.destOffset[1];
686 renderArea.width = params.srcExtents[0];
687 renderArea.height = params.srcExtents[1];
688
689 // Change source layout outside render pass
690 vk::CommandBuffer *srcLayoutChange;
691 ANGLE_TRY(src->recordCommands(context, &srcLayoutChange));
692
693 src->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
694 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
695 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, srcLayoutChange);
696
697 // Change destination layout outside render pass as well
698 vk::CommandBuffer *destLayoutChange;
699 ANGLE_TRY(dest->recordCommands(context, &destLayoutChange));
700
701 dest->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT,
702 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
703 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
704 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, destLayoutChange);
705
706 vk::CommandBuffer *commandBuffer;
707 ANGLE_TRY(startRenderPass(context, dest, destView, renderPassDesc, renderArea, &commandBuffer));
708
709 // Source's layout change should happen before rendering
710 src->addReadDependency(dest);
711
712 VkDescriptorImageInfo imageInfo = {};
713 imageInfo.imageView = srcView->getHandle();
714 imageInfo.imageLayout = src->getCurrentLayout();
715
716 VkWriteDescriptorSet writeInfo = {};
717 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
718 writeInfo.dstSet = descriptorSet;
719 writeInfo.dstBinding = kImageCopySourceBinding;
720 writeInfo.descriptorCount = 1;
721 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
722 writeInfo.pImageInfo = &imageInfo;
723
724 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
725
726 vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
727 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
728 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
729 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(context, 0, &vertexShader));
730 ANGLE_TRY(shaderLibrary.getImageCopy_frag(context, flags, &fragmentShader));
731
732 ANGLE_TRY(setupProgram(context, Function::ImageCopy, fragmentShader, vertexShader,
733 &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
734 sizeof(shaderParams), commandBuffer));
735
736 VkViewport viewport;
737 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, dest->getExtents().height, &viewport);
738
739 VkRect2D scissor = gl_vk::GetRect(renderArea);
740
741 commandBuffer->setViewport(0, 1, &viewport);
742 commandBuffer->setScissor(0, 1, &scissor);
743 commandBuffer->draw(6, 1, 0, 0);
744
745 descriptorPoolBinding.reset();
746
747 return angle::Result::Continue;
748}
749
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500750} // namespace rx