blob: 7c2ba26561c762561768a82571ab2e9790b25e90 [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 Youssefi4f3b2072019-01-01 14:48:25 -0500136
137uint32_t GetFormatDefaultChannelMask(const vk::Format &format)
138{
139 uint32_t mask = 0;
140
141 const angle::Format &angleFormat = format.angleFormat();
142 const angle::Format &textureFormat = format.textureFormat();
143
144 // Red can never be introduced due to format emulation (except for luma which is handled
145 // especially)
146 ASSERT(((angleFormat.redBits > 0) == (textureFormat.redBits > 0)) || angleFormat.isLUMA());
147 mask |= angleFormat.greenBits == 0 && textureFormat.greenBits > 0 ? 2 : 0;
148 mask |= angleFormat.blueBits == 0 && textureFormat.blueBits > 0 ? 4 : 0;
149 mask |= angleFormat.alphaBits == 0 && textureFormat.alphaBits > 0 ? 8 : 0;
150
151 return mask;
152}
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500153} // namespace
154
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100155UtilsVk::UtilsVk() = default;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500156
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100157UtilsVk::~UtilsVk() = default;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500158
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100159void UtilsVk::destroy(VkDevice device)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500160{
161 for (Function f : angle::AllEnums<Function>())
162 {
163 for (auto &descriptorSetLayout : mDescriptorSetLayouts[f])
164 {
165 descriptorSetLayout.reset();
166 }
167 mPipelineLayouts[f].reset();
168 mDescriptorPools[f].destroy(device);
169 }
170
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100171 for (vk::ShaderProgramHelper &program : mBufferUtilsPrograms)
172 {
173 program.destroy(device);
174 }
175 for (vk::ShaderProgramHelper &program : mConvertVertexPrograms)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500176 {
177 program.destroy(device);
178 }
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100179 mImageClearProgram.destroy(device);
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100180 for (vk::ShaderProgramHelper &program : mImageCopyPrograms)
181 {
182 program.destroy(device);
183 }
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500184}
185
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100186angle::Result UtilsVk::ensureResourcesInitialized(vk::Context *context,
187 Function function,
188 VkDescriptorPoolSize *setSizes,
189 size_t setSizesCount,
190 size_t pushConstantsSize)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500191{
192 RendererVk *renderer = context->getRenderer();
193
194 vk::DescriptorSetLayoutDesc descriptorSetDesc;
195
196 uint32_t currentBinding = 0;
197 for (size_t i = 0; i < setSizesCount; ++i)
198 {
199 descriptorSetDesc.update(currentBinding, setSizes[i].type, setSizes[i].descriptorCount);
200 currentBinding += setSizes[i].descriptorCount;
201 }
202
203 ANGLE_TRY(renderer->getDescriptorSetLayout(context, descriptorSetDesc,
204 &mDescriptorSetLayouts[function][kSetIndex]));
205
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100206 gl::ShaderType pushConstantsShaderStage = function >= Function::ComputeStartIndex
207 ? gl::ShaderType::Compute
208 : gl::ShaderType::Fragment;
209
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500210 // Corresponding pipeline layouts:
211 vk::PipelineLayoutDesc pipelineLayoutDesc;
212
213 pipelineLayoutDesc.updateDescriptorSetLayout(kSetIndex, descriptorSetDesc);
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100214 pipelineLayoutDesc.updatePushConstantRange(pushConstantsShaderStage, 0, pushConstantsSize);
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500215
216 ANGLE_TRY(renderer->getPipelineLayout(
217 context, pipelineLayoutDesc, mDescriptorSetLayouts[function], &mPipelineLayouts[function]));
218
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100219 if (setSizesCount > 0)
220 {
221 ANGLE_TRY(mDescriptorPools[function].init(context, setSizes, setSizesCount));
222 }
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500223
Jamie Madill7c985f52018-11-29 18:16:17 -0500224 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500225}
226
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100227angle::Result UtilsVk::ensureBufferClearResourcesInitialized(vk::Context *context)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500228{
229 if (mPipelineLayouts[Function::BufferClear].valid())
230 {
Jamie Madill7c985f52018-11-29 18:16:17 -0500231 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500232 }
233
234 VkDescriptorPoolSize setSizes[1] = {
235 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1},
236 };
237
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100238 return ensureResourcesInitialized(context, Function::BufferClear, setSizes, ArraySize(setSizes),
239 sizeof(BufferUtilsShaderParams));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500240}
241
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100242angle::Result UtilsVk::ensureBufferCopyResourcesInitialized(vk::Context *context)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500243{
244 if (mPipelineLayouts[Function::BufferCopy].valid())
245 {
Jamie Madill7c985f52018-11-29 18:16:17 -0500246 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500247 }
248
249 VkDescriptorPoolSize setSizes[2] = {
250 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1},
251 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1},
252 };
253
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100254 return ensureResourcesInitialized(context, Function::BufferCopy, setSizes, ArraySize(setSizes),
255 sizeof(BufferUtilsShaderParams));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500256}
257
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100258angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(vk::Context *context)
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100259{
260 if (mPipelineLayouts[Function::ConvertVertexBuffer].valid())
261 {
262 return angle::Result::Continue;
263 }
264
265 VkDescriptorPoolSize setSizes[2] = {
266 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
267 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
268 };
269
270 return ensureResourcesInitialized(context, Function::ConvertVertexBuffer, setSizes,
271 ArraySize(setSizes), sizeof(ConvertVertexShaderParams));
272}
273
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100274angle::Result UtilsVk::ensureImageClearResourcesInitialized(vk::Context *context)
275{
276 if (mPipelineLayouts[Function::ImageClear].valid())
277 {
278 return angle::Result::Continue;
279 }
280
281 // The shader does not use any descriptor sets.
282 return ensureResourcesInitialized(context, Function::ImageClear, nullptr, 0,
283 sizeof(ImageClearShaderParams));
284}
285
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100286angle::Result UtilsVk::ensureImageCopyResourcesInitialized(vk::Context *context)
287{
288 if (mPipelineLayouts[Function::ImageCopy].valid())
289 {
290 return angle::Result::Continue;
291 }
292
293 VkDescriptorPoolSize setSizes[1] = {
294 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
295 };
296
297 return ensureResourcesInitialized(context, Function::ImageCopy, setSizes, ArraySize(setSizes),
298 sizeof(ImageCopyShaderParams));
299}
300
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100301angle::Result UtilsVk::setupProgram(vk::Context *context,
302 Function function,
303 vk::RefCounted<vk::ShaderAndSerial> *fsCsShader,
304 vk::RefCounted<vk::ShaderAndSerial> *vsShader,
305 vk::ShaderProgramHelper *program,
306 const vk::GraphicsPipelineDesc *pipelineDesc,
307 const VkDescriptorSet descriptorSet,
308 const void *pushConstants,
309 size_t pushConstantsSize,
310 vk::CommandBuffer *commandBuffer)
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100311{
312 RendererVk *renderer = context->getRenderer();
313
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100314 bool isCompute = function >= Function::ComputeStartIndex;
315 VkPipelineBindPoint bindPoint =
316 isCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
317 VkShaderStageFlags pushConstantsShaderStage =
318 isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
319
320 // If compute, vsShader and pipelineDesc should be nullptr, and if not compute they shouldn't
321 // be.
322 ASSERT(isCompute != (vsShader && pipelineDesc));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100323
324 const vk::BindingPointer<vk::PipelineLayout> &pipelineLayout = mPipelineLayouts[function];
325
Jamie Madilldbc605c2019-01-04 16:39:14 -0500326 Serial serial = renderer->getCurrentQueueSerial();
327
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100328 if (isCompute)
329 {
Jamie Madill3f0c4a52019-01-10 10:20:35 -0500330 vk::PipelineAndSerial *pipelineAndSerial;
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100331 program->setShader(gl::ShaderType::Compute, fsCsShader);
332 ANGLE_TRY(program->getComputePipeline(context, pipelineLayout.get(), &pipelineAndSerial));
Jamie Madill3f0c4a52019-01-10 10:20:35 -0500333 pipelineAndSerial->updateSerial(serial);
334 commandBuffer->bindPipeline(bindPoint, pipelineAndSerial->get());
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100335 }
336 else
337 {
338 program->setShader(gl::ShaderType::Vertex, vsShader);
339 program->setShader(gl::ShaderType::Fragment, fsCsShader);
Jamie Madilldbc605c2019-01-04 16:39:14 -0500340
Jamie Madill3f0c4a52019-01-10 10:20:35 -0500341 // This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
342 const vk::GraphicsPipelineDesc *descPtr;
343 vk::PipelineHelper *helper;
344
Jamie Madilldbc605c2019-01-04 16:39:14 -0500345 ANGLE_TRY(program->getGraphicsPipeline(
346 context, &renderer->getRenderPassCache(), renderer->getPipelineCache(), serial,
Jamie Madill3f0c4a52019-01-10 10:20:35 -0500347 pipelineLayout.get(), *pipelineDesc, gl::AttributesMask(), &descPtr, &helper));
348 helper->updateSerial(serial);
349 commandBuffer->bindPipeline(bindPoint, helper->getPipeline());
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100350 }
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100351
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100352 if (descriptorSet != VK_NULL_HANDLE)
353 {
354 commandBuffer->bindDescriptorSets(bindPoint, pipelineLayout.get(), 0, 1, &descriptorSet, 0,
355 nullptr);
356 }
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100357
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100358 commandBuffer->pushConstants(pipelineLayout.get(), pushConstantsShaderStage, 0,
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100359 pushConstantsSize, pushConstants);
360
361 return angle::Result::Continue;
362}
363
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100364angle::Result UtilsVk::clearBuffer(vk::Context *context,
365 vk::BufferHelper *dest,
366 const ClearParameters &params)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500367{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100368 RendererVk *renderer = context->getRenderer();
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500369
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100370 ANGLE_TRY(ensureBufferClearResourcesInitialized(context));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500371
372 vk::CommandBuffer *commandBuffer;
373 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
374
375 // Tell dest it's being written to.
376 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
377
378 const vk::Format &destFormat = dest->getViewFormat();
379
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100380 uint32_t flags = BufferUtils_comp::kIsClear | GetBufferUtilsFlags(params.size, destFormat);
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500381
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100382 BufferUtilsShaderParams shaderParams;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500383 shaderParams.destOffset = params.offset;
384 shaderParams.size = params.size;
385 shaderParams.clearValue = params.clearValue;
386
387 VkDescriptorSet descriptorSet;
388 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
389 ANGLE_TRY(mDescriptorPools[Function::BufferClear].allocateSets(
390 context, mDescriptorSetLayouts[Function::BufferClear][kSetIndex].get().ptr(), 1,
391 &descriptorPoolBinding, &descriptorSet));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100392 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500393
394 VkWriteDescriptorSet writeInfo = {};
395
396 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
397 writeInfo.dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100398 writeInfo.dstBinding = kBufferClearOutputBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500399 writeInfo.descriptorCount = 1;
400 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
401 writeInfo.pTexelBufferView = dest->getBufferView().ptr();
402
403 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
404
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100405 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
406 ANGLE_TRY(renderer->getShaderLibrary().getBufferUtils_comp(context, flags, &shader));
407
408 ANGLE_TRY(setupProgram(context, Function::BufferClear, shader, nullptr,
409 &mBufferUtilsPrograms[flags], nullptr, descriptorSet, &shaderParams,
410 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500411
412 commandBuffer->dispatch(UnsignedCeilDivide(params.size, 64), 1, 1);
413
414 descriptorPoolBinding.reset();
415
Jamie Madill7c985f52018-11-29 18:16:17 -0500416 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500417}
418
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100419angle::Result UtilsVk::copyBuffer(vk::Context *context,
420 vk::BufferHelper *dest,
421 vk::BufferHelper *src,
422 const CopyParameters &params)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500423{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100424 RendererVk *renderer = context->getRenderer();
425
426 ANGLE_TRY(ensureBufferCopyResourcesInitialized(context));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500427
428 vk::CommandBuffer *commandBuffer;
429 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
430
431 // Tell src we are going to read from it.
432 src->onRead(dest, VK_ACCESS_SHADER_READ_BIT);
433 // Tell dest it's being written to.
434 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
435
436 const vk::Format &destFormat = dest->getViewFormat();
437 const vk::Format &srcFormat = src->getViewFormat();
438
439 ASSERT(destFormat.vkFormatIsInt == srcFormat.vkFormatIsInt);
440 ASSERT(destFormat.vkFormatIsUnsigned == srcFormat.vkFormatIsUnsigned);
441
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100442 uint32_t flags = BufferUtils_comp::kIsCopy | GetBufferUtilsFlags(params.size, destFormat);
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500443
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100444 BufferUtilsShaderParams shaderParams;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500445 shaderParams.destOffset = params.destOffset;
446 shaderParams.size = params.size;
447 shaderParams.srcOffset = params.srcOffset;
448
449 VkDescriptorSet descriptorSet;
450 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
451 ANGLE_TRY(mDescriptorPools[Function::BufferCopy].allocateSets(
452 context, mDescriptorSetLayouts[Function::BufferCopy][kSetIndex].get().ptr(), 1,
453 &descriptorPoolBinding, &descriptorSet));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100454 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500455
456 VkWriteDescriptorSet writeInfo[2] = {};
457
458 writeInfo[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
459 writeInfo[0].dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100460 writeInfo[0].dstBinding = kBufferCopyDestinationBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500461 writeInfo[0].descriptorCount = 1;
462 writeInfo[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
463 writeInfo[0].pTexelBufferView = dest->getBufferView().ptr();
464
465 writeInfo[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
466 writeInfo[1].dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100467 writeInfo[1].dstBinding = kBufferCopySourceBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500468 writeInfo[1].descriptorCount = 1;
469 writeInfo[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
470 writeInfo[1].pTexelBufferView = src->getBufferView().ptr();
471
472 vkUpdateDescriptorSets(context->getDevice(), 2, writeInfo, 0, nullptr);
473
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100474 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
475 ANGLE_TRY(renderer->getShaderLibrary().getBufferUtils_comp(context, flags, &shader));
476
477 ANGLE_TRY(setupProgram(context, Function::BufferCopy, shader, nullptr,
478 &mBufferUtilsPrograms[flags], nullptr, descriptorSet, &shaderParams,
479 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500480
481 commandBuffer->dispatch(UnsignedCeilDivide(params.size, 64), 1, 1);
482
483 descriptorPoolBinding.reset();
484
Jamie Madill7c985f52018-11-29 18:16:17 -0500485 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500486}
487
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100488angle::Result UtilsVk::convertVertexBuffer(vk::Context *context,
489 vk::BufferHelper *dest,
490 vk::BufferHelper *src,
491 const ConvertVertexParameters &params)
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100492{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100493 RendererVk *renderer = context->getRenderer();
494
495 ANGLE_TRY(ensureConvertVertexResourcesInitialized(context));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100496
497 vk::CommandBuffer *commandBuffer;
498 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
499
500 // Tell src we are going to read from it.
501 src->onRead(dest, VK_ACCESS_SHADER_READ_BIT);
502 // Tell dest it's being written to.
503 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
504
505 ConvertVertexShaderParams shaderParams;
506 shaderParams.Ns = params.srcFormat->channelCount();
507 shaderParams.Bs = params.srcFormat->pixelBytes / params.srcFormat->channelCount();
508 shaderParams.Ss = params.srcStride;
509 shaderParams.Nd = params.destFormat->channelCount();
510 shaderParams.Bd = params.destFormat->pixelBytes / params.destFormat->channelCount();
511 shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
512 // The component size is expected to either be 1, 2 or 4 bytes.
513 ASSERT(4 % shaderParams.Bs == 0);
514 ASSERT(4 % shaderParams.Bd == 0);
515 shaderParams.Es = 4 / shaderParams.Bs;
516 shaderParams.Ed = 4 / shaderParams.Bd;
517 // Total number of output components is simply the number of vertices by number of components in
518 // each.
519 shaderParams.componentCount = params.vertexCount * shaderParams.Nd;
520 // Total number of 4-byte outputs is the number of components divided by how many components can
521 // fit in a 4-byte value. Note that this value is also the invocation size of the shader.
522 shaderParams.outputCount = shaderParams.componentCount / shaderParams.Ed;
523 shaderParams.srcOffset = params.srcOffset;
524 shaderParams.destOffset = params.destOffset;
525
526 uint32_t flags = GetConvertVertexFlags(params);
527
528 bool isAligned =
529 shaderParams.outputCount % 64 == 0 && shaderParams.componentCount % shaderParams.Ed == 0;
530 flags |= isAligned ? ConvertVertex_comp::kIsAligned : 0;
531
532 VkDescriptorSet descriptorSet;
533 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
534 ANGLE_TRY(mDescriptorPools[Function::ConvertVertexBuffer].allocateSets(
535 context, mDescriptorSetLayouts[Function::ConvertVertexBuffer][kSetIndex].get().ptr(), 1,
536 &descriptorPoolBinding, &descriptorSet));
537 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
538
539 VkWriteDescriptorSet writeInfo = {};
540 VkDescriptorBufferInfo buffers[2] = {
541 {dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
542 {src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
543 };
544 static_assert(kConvertVertexDestinationBinding + 1 == kConvertVertexSourceBinding,
545 "Update write info");
546
547 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
548 writeInfo.dstSet = descriptorSet;
549 writeInfo.dstBinding = kConvertVertexDestinationBinding;
550 writeInfo.descriptorCount = 2;
551 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
552 writeInfo.pBufferInfo = buffers;
553
554 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
555
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100556 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
557 ANGLE_TRY(renderer->getShaderLibrary().getConvertVertex_comp(context, flags, &shader));
558
559 ANGLE_TRY(setupProgram(context, Function::ConvertVertexBuffer, shader, nullptr,
560 &mConvertVertexPrograms[flags], nullptr, descriptorSet, &shaderParams,
561 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100562
563 commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
564
565 descriptorPoolBinding.reset();
566
567 return angle::Result::Continue;
568}
569
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100570angle::Result UtilsVk::startRenderPass(vk::Context *context,
571 vk::ImageHelper *image,
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500572 const vk::ImageView *imageView,
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100573 const vk::RenderPassDesc &renderPassDesc,
574 const gl::Rectangle &renderArea,
575 vk::CommandBuffer **commandBufferOut)
576{
577 RendererVk *renderer = context->getRenderer();
578
579 vk::RenderPass *renderPass = nullptr;
580 ANGLE_TRY(renderer->getCompatibleRenderPass(context, renderPassDesc, &renderPass));
581
582 VkFramebufferCreateInfo framebufferInfo = {};
583
584 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
585 framebufferInfo.flags = 0;
586 framebufferInfo.renderPass = renderPass->getHandle();
587 framebufferInfo.attachmentCount = 1;
588 framebufferInfo.pAttachments = imageView->ptr();
589 framebufferInfo.width = renderArea.x + renderArea.width;
590 framebufferInfo.height = renderArea.y + renderArea.height;
591 framebufferInfo.layers = 1;
592
593 vk::Framebuffer framebuffer;
594 ANGLE_VK_TRY(context, framebuffer.init(context->getDevice(), framebufferInfo));
595
596 // TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
597 std::vector<VkClearValue> clearValues = {{}};
598 ASSERT(clearValues.size() == 1);
599
600 ANGLE_TRY(image->beginRenderPass(context, framebuffer, renderArea, renderPassDesc, clearValues,
601 commandBufferOut));
602
603 renderer->releaseObject(renderer->getCurrentQueueSerial(), &framebuffer);
604
605 return angle::Result::Continue;
606}
607
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100608angle::Result UtilsVk::clearImage(ContextVk *contextVk,
609 FramebufferVk *framebuffer,
610 const ClearImageParameters &params)
611{
612 RendererVk *renderer = contextVk->getRenderer();
613
614 ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
615
616 vk::CommandBuffer *commandBuffer;
617 if (!framebuffer->appendToStartedRenderPass(contextVk->getRenderer(), &commandBuffer))
618 {
619 ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, &commandBuffer))
620 }
621
622 ImageClearShaderParams shaderParams;
623 shaderParams.clearValue = params.clearValue;
624
625 vk::GraphicsPipelineDesc pipelineDesc;
626 pipelineDesc.initDefaults();
Jamie Madill3f0c4a52019-01-10 10:20:35 -0500627 pipelineDesc.setColorWriteMask(params.colorMaskFlags, *params.alphaMask);
628 pipelineDesc.setRenderPassDesc(*params.renderPassDesc);
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100629
630 vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
631 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
632 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
633 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
634 ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, 0, &fragmentShader));
635
636 ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
637 &mImageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
638 sizeof(shaderParams), commandBuffer));
639
640 VkViewport viewport;
641 const gl::Rectangle &renderArea = framebuffer->getFramebuffer()->getRenderPassRenderArea();
642 bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
643 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, invertViewport, params.renderAreaHeight, &viewport);
644
645 VkRect2D scissor;
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500646 const gl::State &glState = contextVk->getState();
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100647 gl_vk::GetScissor(glState, invertViewport, renderArea, &scissor);
648
649 commandBuffer->setViewport(0, 1, &viewport);
650 commandBuffer->setScissor(0, 1, &scissor);
651 commandBuffer->draw(6, 1, 0, 0);
652
653 return angle::Result::Continue;
654}
655
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100656angle::Result UtilsVk::copyImage(vk::Context *context,
657 vk::ImageHelper *dest,
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500658 const vk::ImageView *destView,
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100659 vk::ImageHelper *src,
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500660 const vk::ImageView *srcView,
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100661 const CopyImageParameters &params)
662{
663 RendererVk *renderer = context->getRenderer();
664
665 ANGLE_TRY(ensureImageCopyResourcesInitialized(context));
666
667 const vk::Format &srcFormat = src->getFormat();
668 const vk::Format &destFormat = dest->getFormat();
669
670 ImageCopyShaderParams shaderParams;
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500671 shaderParams.flipY = params.srcFlipY || params.destFlipY;
672 shaderParams.premultiplyAlpha = params.srcPremultiplyAlpha;
673 shaderParams.unmultiplyAlpha = params.srcUnmultiplyAlpha;
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100674 shaderParams.destHasLuminance = destFormat.angleFormat().luminanceBits > 0;
675 shaderParams.destIsAlpha =
676 destFormat.angleFormat().isLUMA() && destFormat.angleFormat().alphaBits > 0;
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500677 shaderParams.destDefaultChannelsMask = GetFormatDefaultChannelMask(destFormat);
678 shaderParams.srcMip = params.srcMip;
679 shaderParams.srcLayer = params.srcLayer;
680 shaderParams.srcOffset[0] = params.srcOffset[0];
681 shaderParams.srcOffset[1] = params.srcOffset[1];
682 shaderParams.destOffset[0] = params.destOffset[0];
683 shaderParams.destOffset[1] = params.destOffset[1];
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100684
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500685 ASSERT(!(params.srcFlipY && params.destFlipY));
686 if (params.srcFlipY)
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100687 {
688 // If viewport is flipped, the shader expects srcOffset[1] to have the
689 // last row's index instead of the first's.
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500690 shaderParams.srcOffset[1] = params.srcHeight - params.srcOffset[1] - 1;
691 }
692 else if (params.destFlipY)
693 {
694 // If image is flipped during copy, the shader uses the same code path as above,
695 // with srcOffset being set to the last row's index instead of the first's.
696 shaderParams.srcOffset[1] = params.srcOffset[1] + params.srcExtents[1] - 1;
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100697 }
698
699 uint32_t flags = GetImageCopyFlags(srcFormat, destFormat);
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500700 flags |= src->getLayerCount() > 1 ? ImageCopy_frag::kSrcIsArray : 0;
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100701
702 VkDescriptorSet descriptorSet;
703 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
704 ANGLE_TRY(mDescriptorPools[Function::ImageCopy].allocateSets(
705 context, mDescriptorSetLayouts[Function::ImageCopy][kSetIndex].get().ptr(), 1,
706 &descriptorPoolBinding, &descriptorSet));
707 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
708
709 vk::RenderPassDesc renderPassDesc;
710 renderPassDesc.setSamples(dest->getSamples());
711 renderPassDesc.packAttachment(destFormat);
712
713 vk::GraphicsPipelineDesc pipelineDesc;
714 pipelineDesc.initDefaults();
Jamie Madill3f0c4a52019-01-10 10:20:35 -0500715 pipelineDesc.setRenderPassDesc(renderPassDesc);
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100716
717 gl::Rectangle renderArea;
718 renderArea.x = params.destOffset[0];
719 renderArea.y = params.destOffset[1];
720 renderArea.width = params.srcExtents[0];
721 renderArea.height = params.srcExtents[1];
722
723 // Change source layout outside render pass
Shahbaz Youssefib5ba5492019-01-02 15:19:22 -0500724 if (src->getCurrentLayout() != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
725 {
726 vk::CommandBuffer *srcLayoutChange;
727 ANGLE_TRY(src->recordCommands(context, &srcLayoutChange));
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100728
Shahbaz Youssefib5ba5492019-01-02 15:19:22 -0500729 src->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT,
730 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
731 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
732 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, srcLayoutChange);
733 }
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100734
735 // Change destination layout outside render pass as well
736 vk::CommandBuffer *destLayoutChange;
737 ANGLE_TRY(dest->recordCommands(context, &destLayoutChange));
738
739 dest->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT,
740 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
741 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
742 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, destLayoutChange);
743
744 vk::CommandBuffer *commandBuffer;
745 ANGLE_TRY(startRenderPass(context, dest, destView, renderPassDesc, renderArea, &commandBuffer));
746
747 // Source's layout change should happen before rendering
748 src->addReadDependency(dest);
749
750 VkDescriptorImageInfo imageInfo = {};
751 imageInfo.imageView = srcView->getHandle();
752 imageInfo.imageLayout = src->getCurrentLayout();
753
754 VkWriteDescriptorSet writeInfo = {};
755 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
756 writeInfo.dstSet = descriptorSet;
757 writeInfo.dstBinding = kImageCopySourceBinding;
758 writeInfo.descriptorCount = 1;
759 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
760 writeInfo.pImageInfo = &imageInfo;
761
762 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
763
764 vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
765 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
766 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
767 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(context, 0, &vertexShader));
768 ANGLE_TRY(shaderLibrary.getImageCopy_frag(context, flags, &fragmentShader));
769
770 ANGLE_TRY(setupProgram(context, Function::ImageCopy, fragmentShader, vertexShader,
771 &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
772 sizeof(shaderParams), commandBuffer));
773
774 VkViewport viewport;
775 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, dest->getExtents().height, &viewport);
776
777 VkRect2D scissor = gl_vk::GetRect(renderArea);
778
779 commandBuffer->setViewport(0, 1, &viewport);
780 commandBuffer->setScissor(0, 1, &scissor);
781 commandBuffer->draw(6, 1, 0, 0);
782
783 descriptorPoolBinding.reset();
784
785 return angle::Result::Continue;
786}
787
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500788} // namespace rx