blob: 5fae062b7599ee97c3c6f75386079c3997069479 [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 Youssefi611bbaa2018-12-06 01:59:53 +0100328 vk::PipelineAndSerial *pipelineAndSerial;
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100329 if (isCompute)
330 {
331 program->setShader(gl::ShaderType::Compute, fsCsShader);
332 ANGLE_TRY(program->getComputePipeline(context, pipelineLayout.get(), &pipelineAndSerial));
333 }
334 else
335 {
336 program->setShader(gl::ShaderType::Vertex, vsShader);
337 program->setShader(gl::ShaderType::Fragment, fsCsShader);
Jamie Madilldbc605c2019-01-04 16:39:14 -0500338
339 ANGLE_TRY(program->getGraphicsPipeline(
340 context, &renderer->getRenderPassCache(), renderer->getPipelineCache(), serial,
341 pipelineLayout.get(), *pipelineDesc, gl::AttributesMask(), &pipelineAndSerial));
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100342 }
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100343
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100344 commandBuffer->bindPipeline(bindPoint, pipelineAndSerial->get());
Jamie Madilldbc605c2019-01-04 16:39:14 -0500345 pipelineAndSerial->updateSerial(serial);
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100346
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100347 if (descriptorSet != VK_NULL_HANDLE)
348 {
349 commandBuffer->bindDescriptorSets(bindPoint, pipelineLayout.get(), 0, 1, &descriptorSet, 0,
350 nullptr);
351 }
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100352
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100353 commandBuffer->pushConstants(pipelineLayout.get(), pushConstantsShaderStage, 0,
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100354 pushConstantsSize, pushConstants);
355
356 return angle::Result::Continue;
357}
358
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100359angle::Result UtilsVk::clearBuffer(vk::Context *context,
360 vk::BufferHelper *dest,
361 const ClearParameters &params)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500362{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100363 RendererVk *renderer = context->getRenderer();
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500364
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100365 ANGLE_TRY(ensureBufferClearResourcesInitialized(context));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500366
367 vk::CommandBuffer *commandBuffer;
368 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
369
370 // Tell dest it's being written to.
371 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
372
373 const vk::Format &destFormat = dest->getViewFormat();
374
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100375 uint32_t flags = BufferUtils_comp::kIsClear | GetBufferUtilsFlags(params.size, destFormat);
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500376
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100377 BufferUtilsShaderParams shaderParams;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500378 shaderParams.destOffset = params.offset;
379 shaderParams.size = params.size;
380 shaderParams.clearValue = params.clearValue;
381
382 VkDescriptorSet descriptorSet;
383 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
384 ANGLE_TRY(mDescriptorPools[Function::BufferClear].allocateSets(
385 context, mDescriptorSetLayouts[Function::BufferClear][kSetIndex].get().ptr(), 1,
386 &descriptorPoolBinding, &descriptorSet));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100387 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500388
389 VkWriteDescriptorSet writeInfo = {};
390
391 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
392 writeInfo.dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100393 writeInfo.dstBinding = kBufferClearOutputBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500394 writeInfo.descriptorCount = 1;
395 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
396 writeInfo.pTexelBufferView = dest->getBufferView().ptr();
397
398 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
399
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100400 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
401 ANGLE_TRY(renderer->getShaderLibrary().getBufferUtils_comp(context, flags, &shader));
402
403 ANGLE_TRY(setupProgram(context, Function::BufferClear, shader, nullptr,
404 &mBufferUtilsPrograms[flags], nullptr, descriptorSet, &shaderParams,
405 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500406
407 commandBuffer->dispatch(UnsignedCeilDivide(params.size, 64), 1, 1);
408
409 descriptorPoolBinding.reset();
410
Jamie Madill7c985f52018-11-29 18:16:17 -0500411 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500412}
413
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100414angle::Result UtilsVk::copyBuffer(vk::Context *context,
415 vk::BufferHelper *dest,
416 vk::BufferHelper *src,
417 const CopyParameters &params)
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500418{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100419 RendererVk *renderer = context->getRenderer();
420
421 ANGLE_TRY(ensureBufferCopyResourcesInitialized(context));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500422
423 vk::CommandBuffer *commandBuffer;
424 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
425
426 // Tell src we are going to read from it.
427 src->onRead(dest, VK_ACCESS_SHADER_READ_BIT);
428 // Tell dest it's being written to.
429 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
430
431 const vk::Format &destFormat = dest->getViewFormat();
432 const vk::Format &srcFormat = src->getViewFormat();
433
434 ASSERT(destFormat.vkFormatIsInt == srcFormat.vkFormatIsInt);
435 ASSERT(destFormat.vkFormatIsUnsigned == srcFormat.vkFormatIsUnsigned);
436
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100437 uint32_t flags = BufferUtils_comp::kIsCopy | GetBufferUtilsFlags(params.size, destFormat);
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500438
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100439 BufferUtilsShaderParams shaderParams;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500440 shaderParams.destOffset = params.destOffset;
441 shaderParams.size = params.size;
442 shaderParams.srcOffset = params.srcOffset;
443
444 VkDescriptorSet descriptorSet;
445 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
446 ANGLE_TRY(mDescriptorPools[Function::BufferCopy].allocateSets(
447 context, mDescriptorSetLayouts[Function::BufferCopy][kSetIndex].get().ptr(), 1,
448 &descriptorPoolBinding, &descriptorSet));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100449 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500450
451 VkWriteDescriptorSet writeInfo[2] = {};
452
453 writeInfo[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
454 writeInfo[0].dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100455 writeInfo[0].dstBinding = kBufferCopyDestinationBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500456 writeInfo[0].descriptorCount = 1;
457 writeInfo[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
458 writeInfo[0].pTexelBufferView = dest->getBufferView().ptr();
459
460 writeInfo[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
461 writeInfo[1].dstSet = descriptorSet;
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100462 writeInfo[1].dstBinding = kBufferCopySourceBinding;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500463 writeInfo[1].descriptorCount = 1;
464 writeInfo[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
465 writeInfo[1].pTexelBufferView = src->getBufferView().ptr();
466
467 vkUpdateDescriptorSets(context->getDevice(), 2, writeInfo, 0, nullptr);
468
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100469 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
470 ANGLE_TRY(renderer->getShaderLibrary().getBufferUtils_comp(context, flags, &shader));
471
472 ANGLE_TRY(setupProgram(context, Function::BufferCopy, shader, nullptr,
473 &mBufferUtilsPrograms[flags], nullptr, descriptorSet, &shaderParams,
474 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500475
476 commandBuffer->dispatch(UnsignedCeilDivide(params.size, 64), 1, 1);
477
478 descriptorPoolBinding.reset();
479
Jamie Madill7c985f52018-11-29 18:16:17 -0500480 return angle::Result::Continue;
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500481}
482
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100483angle::Result UtilsVk::convertVertexBuffer(vk::Context *context,
484 vk::BufferHelper *dest,
485 vk::BufferHelper *src,
486 const ConvertVertexParameters &params)
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100487{
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100488 RendererVk *renderer = context->getRenderer();
489
490 ANGLE_TRY(ensureConvertVertexResourcesInitialized(context));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100491
492 vk::CommandBuffer *commandBuffer;
493 ANGLE_TRY(dest->recordCommands(context, &commandBuffer));
494
495 // Tell src we are going to read from it.
496 src->onRead(dest, VK_ACCESS_SHADER_READ_BIT);
497 // Tell dest it's being written to.
498 dest->onWrite(VK_ACCESS_SHADER_WRITE_BIT);
499
500 ConvertVertexShaderParams shaderParams;
501 shaderParams.Ns = params.srcFormat->channelCount();
502 shaderParams.Bs = params.srcFormat->pixelBytes / params.srcFormat->channelCount();
503 shaderParams.Ss = params.srcStride;
504 shaderParams.Nd = params.destFormat->channelCount();
505 shaderParams.Bd = params.destFormat->pixelBytes / params.destFormat->channelCount();
506 shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
507 // The component size is expected to either be 1, 2 or 4 bytes.
508 ASSERT(4 % shaderParams.Bs == 0);
509 ASSERT(4 % shaderParams.Bd == 0);
510 shaderParams.Es = 4 / shaderParams.Bs;
511 shaderParams.Ed = 4 / shaderParams.Bd;
512 // Total number of output components is simply the number of vertices by number of components in
513 // each.
514 shaderParams.componentCount = params.vertexCount * shaderParams.Nd;
515 // Total number of 4-byte outputs is the number of components divided by how many components can
516 // fit in a 4-byte value. Note that this value is also the invocation size of the shader.
517 shaderParams.outputCount = shaderParams.componentCount / shaderParams.Ed;
518 shaderParams.srcOffset = params.srcOffset;
519 shaderParams.destOffset = params.destOffset;
520
521 uint32_t flags = GetConvertVertexFlags(params);
522
523 bool isAligned =
524 shaderParams.outputCount % 64 == 0 && shaderParams.componentCount % shaderParams.Ed == 0;
525 flags |= isAligned ? ConvertVertex_comp::kIsAligned : 0;
526
527 VkDescriptorSet descriptorSet;
528 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
529 ANGLE_TRY(mDescriptorPools[Function::ConvertVertexBuffer].allocateSets(
530 context, mDescriptorSetLayouts[Function::ConvertVertexBuffer][kSetIndex].get().ptr(), 1,
531 &descriptorPoolBinding, &descriptorSet));
532 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
533
534 VkWriteDescriptorSet writeInfo = {};
535 VkDescriptorBufferInfo buffers[2] = {
536 {dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
537 {src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
538 };
539 static_assert(kConvertVertexDestinationBinding + 1 == kConvertVertexSourceBinding,
540 "Update write info");
541
542 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
543 writeInfo.dstSet = descriptorSet;
544 writeInfo.dstBinding = kConvertVertexDestinationBinding;
545 writeInfo.descriptorCount = 2;
546 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
547 writeInfo.pBufferInfo = buffers;
548
549 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
550
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100551 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
552 ANGLE_TRY(renderer->getShaderLibrary().getConvertVertex_comp(context, flags, &shader));
553
554 ANGLE_TRY(setupProgram(context, Function::ConvertVertexBuffer, shader, nullptr,
555 &mConvertVertexPrograms[flags], nullptr, descriptorSet, &shaderParams,
556 sizeof(shaderParams), commandBuffer));
Shahbaz Youssefi611bbaa2018-12-06 01:59:53 +0100557
558 commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
559
560 descriptorPoolBinding.reset();
561
562 return angle::Result::Continue;
563}
564
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100565angle::Result UtilsVk::startRenderPass(vk::Context *context,
566 vk::ImageHelper *image,
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500567 const vk::ImageView *imageView,
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100568 const vk::RenderPassDesc &renderPassDesc,
569 const gl::Rectangle &renderArea,
570 vk::CommandBuffer **commandBufferOut)
571{
572 RendererVk *renderer = context->getRenderer();
573
574 vk::RenderPass *renderPass = nullptr;
575 ANGLE_TRY(renderer->getCompatibleRenderPass(context, renderPassDesc, &renderPass));
576
577 VkFramebufferCreateInfo framebufferInfo = {};
578
579 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
580 framebufferInfo.flags = 0;
581 framebufferInfo.renderPass = renderPass->getHandle();
582 framebufferInfo.attachmentCount = 1;
583 framebufferInfo.pAttachments = imageView->ptr();
584 framebufferInfo.width = renderArea.x + renderArea.width;
585 framebufferInfo.height = renderArea.y + renderArea.height;
586 framebufferInfo.layers = 1;
587
588 vk::Framebuffer framebuffer;
589 ANGLE_VK_TRY(context, framebuffer.init(context->getDevice(), framebufferInfo));
590
591 // TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
592 std::vector<VkClearValue> clearValues = {{}};
593 ASSERT(clearValues.size() == 1);
594
595 ANGLE_TRY(image->beginRenderPass(context, framebuffer, renderArea, renderPassDesc, clearValues,
596 commandBufferOut));
597
598 renderer->releaseObject(renderer->getCurrentQueueSerial(), &framebuffer);
599
600 return angle::Result::Continue;
601}
602
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100603angle::Result UtilsVk::clearImage(ContextVk *contextVk,
604 FramebufferVk *framebuffer,
605 const ClearImageParameters &params)
606{
607 RendererVk *renderer = contextVk->getRenderer();
608
609 ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
610
611 vk::CommandBuffer *commandBuffer;
612 if (!framebuffer->appendToStartedRenderPass(contextVk->getRenderer(), &commandBuffer))
613 {
614 ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, &commandBuffer))
615 }
616
617 ImageClearShaderParams shaderParams;
618 shaderParams.clearValue = params.clearValue;
619
620 vk::GraphicsPipelineDesc pipelineDesc;
621 pipelineDesc.initDefaults();
622 pipelineDesc.updateColorWriteMask(params.colorMaskFlags, *params.alphaMask);
623 pipelineDesc.updateRenderPassDesc(*params.renderPassDesc);
624
625 vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
626 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
627 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
628 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
629 ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, 0, &fragmentShader));
630
631 ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
632 &mImageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
633 sizeof(shaderParams), commandBuffer));
634
635 VkViewport viewport;
636 const gl::Rectangle &renderArea = framebuffer->getFramebuffer()->getRenderPassRenderArea();
637 bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
638 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, invertViewport, params.renderAreaHeight, &viewport);
639
640 VkRect2D scissor;
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500641 const gl::State &glState = contextVk->getState();
Shahbaz Youssefie3219402018-12-08 16:54:14 +0100642 gl_vk::GetScissor(glState, invertViewport, renderArea, &scissor);
643
644 commandBuffer->setViewport(0, 1, &viewport);
645 commandBuffer->setScissor(0, 1, &scissor);
646 commandBuffer->draw(6, 1, 0, 0);
647
648 return angle::Result::Continue;
649}
650
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100651angle::Result UtilsVk::copyImage(vk::Context *context,
652 vk::ImageHelper *dest,
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500653 const vk::ImageView *destView,
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100654 vk::ImageHelper *src,
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500655 const vk::ImageView *srcView,
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100656 const CopyImageParameters &params)
657{
658 RendererVk *renderer = context->getRenderer();
659
660 ANGLE_TRY(ensureImageCopyResourcesInitialized(context));
661
662 const vk::Format &srcFormat = src->getFormat();
663 const vk::Format &destFormat = dest->getFormat();
664
665 ImageCopyShaderParams shaderParams;
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500666 shaderParams.flipY = params.srcFlipY || params.destFlipY;
667 shaderParams.premultiplyAlpha = params.srcPremultiplyAlpha;
668 shaderParams.unmultiplyAlpha = params.srcUnmultiplyAlpha;
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100669 shaderParams.destHasLuminance = destFormat.angleFormat().luminanceBits > 0;
670 shaderParams.destIsAlpha =
671 destFormat.angleFormat().isLUMA() && destFormat.angleFormat().alphaBits > 0;
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500672 shaderParams.destDefaultChannelsMask = GetFormatDefaultChannelMask(destFormat);
673 shaderParams.srcMip = params.srcMip;
674 shaderParams.srcLayer = params.srcLayer;
675 shaderParams.srcOffset[0] = params.srcOffset[0];
676 shaderParams.srcOffset[1] = params.srcOffset[1];
677 shaderParams.destOffset[0] = params.destOffset[0];
678 shaderParams.destOffset[1] = params.destOffset[1];
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100679
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500680 ASSERT(!(params.srcFlipY && params.destFlipY));
681 if (params.srcFlipY)
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100682 {
683 // If viewport is flipped, the shader expects srcOffset[1] to have the
684 // last row's index instead of the first's.
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500685 shaderParams.srcOffset[1] = params.srcHeight - params.srcOffset[1] - 1;
686 }
687 else if (params.destFlipY)
688 {
689 // If image is flipped during copy, the shader uses the same code path as above,
690 // with srcOffset being set to the last row's index instead of the first's.
691 shaderParams.srcOffset[1] = params.srcOffset[1] + params.srcExtents[1] - 1;
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100692 }
693
694 uint32_t flags = GetImageCopyFlags(srcFormat, destFormat);
Shahbaz Youssefi4f3b2072019-01-01 14:48:25 -0500695 flags |= src->getLayerCount() > 1 ? ImageCopy_frag::kSrcIsArray : 0;
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +0100696
697 VkDescriptorSet descriptorSet;
698 vk::SharedDescriptorPoolBinding descriptorPoolBinding;
699 ANGLE_TRY(mDescriptorPools[Function::ImageCopy].allocateSets(
700 context, mDescriptorSetLayouts[Function::ImageCopy][kSetIndex].get().ptr(), 1,
701 &descriptorPoolBinding, &descriptorSet));
702 descriptorPoolBinding.get().updateSerial(context->getRenderer()->getCurrentQueueSerial());
703
704 vk::RenderPassDesc renderPassDesc;
705 renderPassDesc.setSamples(dest->getSamples());
706 renderPassDesc.packAttachment(destFormat);
707
708 vk::GraphicsPipelineDesc pipelineDesc;
709 pipelineDesc.initDefaults();
710 pipelineDesc.updateRenderPassDesc(renderPassDesc);
711
712 gl::Rectangle renderArea;
713 renderArea.x = params.destOffset[0];
714 renderArea.y = params.destOffset[1];
715 renderArea.width = params.srcExtents[0];
716 renderArea.height = params.srcExtents[1];
717
718 // Change source layout outside render pass
719 vk::CommandBuffer *srcLayoutChange;
720 ANGLE_TRY(src->recordCommands(context, &srcLayoutChange));
721
722 src->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
723 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
724 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, srcLayoutChange);
725
726 // Change destination layout outside render pass as well
727 vk::CommandBuffer *destLayoutChange;
728 ANGLE_TRY(dest->recordCommands(context, &destLayoutChange));
729
730 dest->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT,
731 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
732 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
733 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, destLayoutChange);
734
735 vk::CommandBuffer *commandBuffer;
736 ANGLE_TRY(startRenderPass(context, dest, destView, renderPassDesc, renderArea, &commandBuffer));
737
738 // Source's layout change should happen before rendering
739 src->addReadDependency(dest);
740
741 VkDescriptorImageInfo imageInfo = {};
742 imageInfo.imageView = srcView->getHandle();
743 imageInfo.imageLayout = src->getCurrentLayout();
744
745 VkWriteDescriptorSet writeInfo = {};
746 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
747 writeInfo.dstSet = descriptorSet;
748 writeInfo.dstBinding = kImageCopySourceBinding;
749 writeInfo.descriptorCount = 1;
750 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
751 writeInfo.pImageInfo = &imageInfo;
752
753 vkUpdateDescriptorSets(context->getDevice(), 1, &writeInfo, 0, nullptr);
754
755 vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
756 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
757 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
758 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(context, 0, &vertexShader));
759 ANGLE_TRY(shaderLibrary.getImageCopy_frag(context, flags, &fragmentShader));
760
761 ANGLE_TRY(setupProgram(context, Function::ImageCopy, fragmentShader, vertexShader,
762 &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
763 sizeof(shaderParams), commandBuffer));
764
765 VkViewport viewport;
766 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, dest->getExtents().height, &viewport);
767
768 VkRect2D scissor = gl_vk::GetRect(renderArea);
769
770 commandBuffer->setViewport(0, 1, &viewport);
771 commandBuffer->setScissor(0, 1, &scissor);
772 commandBuffer->draw(6, 1, 0, 0);
773
774 descriptorPoolBinding.reset();
775
776 return angle::Result::Continue;
777}
778
Shahbaz Youssefi8f1b7a62018-11-14 16:02:54 -0500779} // namespace rx