blob: 4888e7350bc55b57de819d24d746ecd1093142af [file] [log] [blame]
Greg Daniela8c32102020-12-30 15:09:32 -05001/*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "src/gpu/vk/GrVkMSAALoadManager.h"
9
Greg Daniel8eb119a2021-02-04 09:41:19 -050010#include "include/gpu/GrDirectContext.h"
Greg Daniela8c32102020-12-30 15:09:32 -050011#include "src/core/SkTraceEvent.h"
Greg Daniel8eb119a2021-02-04 09:41:19 -050012#include "src/gpu/GrDirectContextPriv.h"
Greg Danielaf1d1932021-02-08 13:55:26 -050013#include "src/gpu/vk/GrVkBuffer.h"
Greg Daniela8c32102020-12-30 15:09:32 -050014#include "src/gpu/vk/GrVkCommandBuffer.h"
15#include "src/gpu/vk/GrVkDescriptorSet.h"
16#include "src/gpu/vk/GrVkGpu.h"
17#include "src/gpu/vk/GrVkImageView.h"
Greg Daniela8c32102020-12-30 15:09:32 -050018#include "src/gpu/vk/GrVkPipeline.h"
19#include "src/gpu/vk/GrVkRenderTarget.h"
20#include "src/gpu/vk/GrVkResourceProvider.h"
Greg Daniela8c32102020-12-30 15:09:32 -050021#include "src/gpu/vk/GrVkUtil.h"
22
23GrVkMSAALoadManager::GrVkMSAALoadManager()
24 : fVertShaderModule(VK_NULL_HANDLE)
25 , fFragShaderModule(VK_NULL_HANDLE)
26 , fPipelineLayout(VK_NULL_HANDLE) {}
27
28GrVkMSAALoadManager::~GrVkMSAALoadManager() {}
29
30bool GrVkMSAALoadManager::createMSAALoadProgram(GrVkGpu* gpu) {
31 TRACE_EVENT0("skia", TRACE_FUNC);
32
33 SkSL::String vertShaderText;
34 vertShaderText.append(
35 "#extension GL_ARB_separate_shader_objects : enable\n"
36 "#extension GL_ARB_shading_language_420pack : enable\n"
37
38 "layout(set = 0, binding = 0) uniform vertexUniformBuffer {"
39 "half4 uPosXform;"
40 "};"
41
42 "// MSAA Load Program VS\n"
43 "void main() {"
44 "float2 position = float2(sk_VertexID >> 1, sk_VertexID & 1);"
45 "sk_Position.xy = position * uPosXform.xy + uPosXform.zw;"
46 "sk_Position.zw = half2(0, 1);"
47 "}");
48
49 SkSL::String fragShaderText;
50 fragShaderText.append(
51 "#extension GL_ARB_separate_shader_objects : enable\n"
52 "#extension GL_ARB_shading_language_420pack : enable\n"
53
54 "layout(input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput uInput;"
55
56 "// MSAA Load Program FS\n"
57 "void main() {"
58 "sk_FragColor = subpassLoad(uInput);"
59 "}");
60
61 SkSL::Program::Settings settings;
62 SkSL::String spirv;
63 SkSL::Program::Inputs inputs;
64 if (!GrCompileVkShaderModule(gpu, vertShaderText, VK_SHADER_STAGE_VERTEX_BIT,
65 &fVertShaderModule, &fShaderStageInfo[0], settings, &spirv,
66 &inputs)) {
67 this->destroyResources(gpu);
68 return false;
69 }
70 SkASSERT(inputs.isEmpty());
71
72 if (!GrCompileVkShaderModule(gpu, fragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT,
73 &fFragShaderModule, &fShaderStageInfo[1], settings, &spirv,
74 &inputs)) {
75 this->destroyResources(gpu);
76 return false;
77 }
78 SkASSERT(inputs.isEmpty());
79
80 VkDescriptorSetLayout dsLayout[GrVkUniformHandler::kDescSetCount];
81
82 GrVkResourceProvider& resourceProvider = gpu->resourceProvider();
83
84 dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
85
86 // Even though we don't have a sampler we need to put a valid handle here (of zero samplers)
87 // since we set up our descriptor layout to be uniform, sampler, input.
88 //
89 // TODO: We should have a more general way for different pipelines to describe their descriptor
90 // layouts so that we don't have to use the compile time constants for the sets.
91 GrVkDescriptorSetManager::Handle samplerHandle;
92 resourceProvider.getZeroSamplerDescriptorSetHandle(&samplerHandle);
93
94 dsLayout[GrVkUniformHandler::kSamplerDescSet] =
95 resourceProvider.getSamplerDSLayout(samplerHandle);
96
97 dsLayout[GrVkUniformHandler::kInputDescSet] = resourceProvider.getInputDSLayout();
98
99 // Create the VkPipelineLayout
100 VkPipelineLayoutCreateInfo layoutCreateInfo;
101 memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
102 layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
103 layoutCreateInfo.pNext = nullptr;
104 layoutCreateInfo.flags = 0;
105 layoutCreateInfo.setLayoutCount = GrVkUniformHandler::kDescSetCount;
106 layoutCreateInfo.pSetLayouts = dsLayout;
107 layoutCreateInfo.pushConstantRangeCount = 0;
108 layoutCreateInfo.pPushConstantRanges = nullptr;
109
110 VkResult err = GR_VK_CALL(
111 gpu->vkInterface(),
112 CreatePipelineLayout(gpu->device(), &layoutCreateInfo, nullptr, &fPipelineLayout));
113 if (err) {
114 this->destroyResources(gpu);
115 return false;
116 }
117
Greg Daniela8c32102020-12-30 15:09:32 -0500118 return true;
119}
120
121bool GrVkMSAALoadManager::loadMSAAFromResolve(GrVkGpu* gpu,
122 GrVkCommandBuffer* commandBuffer,
123 const GrVkRenderPass& renderPass,
Greg Daniel10344252021-04-22 09:52:25 -0400124 GrAttachment* dst,
125 GrVkAttachment* src,
Greg Daniela8c32102020-12-30 15:09:32 -0500126 const SkIRect& rect) {
Greg Daniel10344252021-04-22 09:52:25 -0400127 if (!dst) {
Greg Daniela8c32102020-12-30 15:09:32 -0500128 return false;
129 }
Greg Daniel10344252021-04-22 09:52:25 -0400130 if (!src || !src->supportsInputAttachmentUsage()) {
Greg Daniela8c32102020-12-30 15:09:32 -0500131 return false;
132 }
133
134 if (VK_NULL_HANDLE == fVertShaderModule) {
Greg Daniel8eb119a2021-02-04 09:41:19 -0500135 SkASSERT(fFragShaderModule == VK_NULL_HANDLE && fPipelineLayout == VK_NULL_HANDLE);
Greg Daniela8c32102020-12-30 15:09:32 -0500136 if (!this->createMSAALoadProgram(gpu)) {
137 SkDebugf("Failed to create copy program.\n");
138 return false;
139 }
140 }
Greg Danielb8aa5f22020-12-30 16:57:32 -0500141 SkASSERT(fPipelineLayout != VK_NULL_HANDLE);
Greg Daniela8c32102020-12-30 15:09:32 -0500142
143 GrVkResourceProvider& resourceProv = gpu->resourceProvider();
144
Greg Daniel3ef052c2021-01-05 12:20:27 -0500145 sk_sp<const GrVkPipeline> pipeline =
Greg Daniel10344252021-04-22 09:52:25 -0400146 resourceProv.findOrCreateMSAALoadPipeline(renderPass, dst->numSamples(),
147 fShaderStageInfo, fPipelineLayout);
Greg Daniela8c32102020-12-30 15:09:32 -0500148 if (!pipeline) {
149 return false;
150 }
Greg Daniel3ef052c2021-01-05 12:20:27 -0500151 commandBuffer->bindPipeline(gpu, std::move(pipeline));
Greg Daniela8c32102020-12-30 15:09:32 -0500152
153 // Set Dynamic viewport and stencil
154 // We always use one viewport the size of the RT
155 VkViewport viewport;
156 viewport.x = 0.0f;
157 viewport.y = 0.0f;
158 viewport.width = SkIntToScalar(dst->width());
159 viewport.height = SkIntToScalar(dst->height());
160 viewport.minDepth = 0.0f;
161 viewport.maxDepth = 1.0f;
162 commandBuffer->setViewport(gpu, 0, 1, &viewport);
163
164 // We assume the scissor is not enabled so just set it to the whole RT
165 VkRect2D scissor;
166 scissor.extent.width = dst->width();
167 scissor.extent.height = dst->height();
168 scissor.offset.x = 0;
169 scissor.offset.y = 0;
170 commandBuffer->setScissor(gpu, 0, 1, &scissor);
171
172 // Update and bind uniform descriptor set
173 int w = rect.width();
174 int h = rect.height();
175
176 // dst rect edges in NDC (-1 to 1)
177 int dw = dst->width();
178 int dh = dst->height();
179 float dx0 = 2.f * rect.fLeft / dw - 1.f;
180 float dx1 = 2.f * (rect.fLeft + w) / dw - 1.f;
181 float dy0 = 2.f * rect.fTop / dh - 1.f;
182 float dy1 = 2.f * (rect.fTop + h) / dh - 1.f;
183
184 float uniData[] = {dx1 - dx0, dy1 - dy0, dx0, dy0}; // posXform
185
Greg Daniel8eb119a2021-02-04 09:41:19 -0500186 GrResourceProvider* resourceProvider = gpu->getContext()->priv().resourceProvider();
187 // TODO: Is it worth holding onto the last used uniform buffer and tracking the width, height,
188 // dst width, and dst height so that we can use the buffer again without having to update the
189 // data?
190 sk_sp<GrGpuBuffer> uniformBuffer = resourceProvider->createBuffer(
191 4 * sizeof(float), GrGpuBufferType::kUniform, kDynamic_GrAccessPattern, uniData);
192 if (!uniformBuffer) {
193 return false;
194 }
Greg Danielaf1d1932021-02-08 13:55:26 -0500195 GrVkBuffer* vkUniformBuffer = static_cast<GrVkBuffer*>(uniformBuffer.get());
Greg Daniela8c32102020-12-30 15:09:32 -0500196 static_assert(GrVkUniformHandler::kUniformBufferDescSet < GrVkUniformHandler::kInputDescSet);
197 commandBuffer->bindDescriptorSets(gpu, fPipelineLayout,
198 GrVkUniformHandler::kUniformBufferDescSet,
Greg Daniel8eb119a2021-02-04 09:41:19 -0500199 /*setCount=*/1, vkUniformBuffer->uniformDescriptorSet(),
Greg Daniela8c32102020-12-30 15:09:32 -0500200 /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr);
Greg Daniel8eb119a2021-02-04 09:41:19 -0500201 commandBuffer->addGrBuffer(std::move(uniformBuffer));
Greg Daniela8c32102020-12-30 15:09:32 -0500202
203 // Update the input descriptor set
Greg Daniel10344252021-04-22 09:52:25 -0400204 gr_rp<const GrVkDescriptorSet> inputDS = src->inputDescSetForMSAALoad(gpu);
Greg Daniela8c32102020-12-30 15:09:32 -0500205 if (!inputDS) {
206 return false;
207 }
208 commandBuffer->bindDescriptorSets(gpu, fPipelineLayout,
209 GrVkUniformHandler::kInputDescSet, /*setCount=*/1,
210 inputDS->descriptorSet(),
211 /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr);
212
213 // We don't need to add the src and dst resources here since those are all tracked by the main
214 // render pass code out in GrVkOpsRenderPass and GrVkRenderTarget::adResources.
Greg Daniel10344252021-04-22 09:52:25 -0400215 commandBuffer->addRecycledResource(std::move(inputDS));
Greg Daniela8c32102020-12-30 15:09:32 -0500216
217 commandBuffer->draw(gpu, 4, 1, 0, 0);
218
219 return true;
220}
221
222void GrVkMSAALoadManager::destroyResources(GrVkGpu* gpu) {
223 if (fVertShaderModule != VK_NULL_HANDLE) {
224 GR_VK_CALL(gpu->vkInterface(),
225 DestroyShaderModule(gpu->device(), fVertShaderModule, nullptr));
226 fVertShaderModule = VK_NULL_HANDLE;
227 }
228
229 if (fFragShaderModule != VK_NULL_HANDLE) {
230 GR_VK_CALL(gpu->vkInterface(),
231 DestroyShaderModule(gpu->device(), fFragShaderModule, nullptr));
232 fFragShaderModule = VK_NULL_HANDLE;
233 }
234
235 if (fPipelineLayout != VK_NULL_HANDLE) {
236 GR_VK_CALL(gpu->vkInterface(),
237 DestroyPipelineLayout(gpu->device(), fPipelineLayout, nullptr));
238 fPipelineLayout = VK_NULL_HANDLE;
239 }
Greg Daniela8c32102020-12-30 15:09:32 -0500240}
241