Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GrVkMSAALoadManager.cpp
Go to the documentation of this file.
1/*
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
9
24
26 : fVertShaderModule(VK_NULL_HANDLE)
27 , fFragShaderModule(VK_NULL_HANDLE)
28 , fPipelineLayout(VK_NULL_HANDLE) {}
29
31
32bool GrVkMSAALoadManager::createMSAALoadProgram(GrVkGpu* gpu) {
33 TRACE_EVENT0("skia", TRACE_FUNC);
34
35 std::string vertShaderText;
36 vertShaderText.append(
37 "layout(vulkan, set=0, binding=0) uniform vertexUniformBuffer {"
38 "half4 uPosXform;"
39 "};"
40
41 "// MSAA Load Program VS\n"
42 "void main() {"
43 "float2 position = float2(sk_VertexID >> 1, sk_VertexID & 1);"
44 "sk_Position.xy = position * uPosXform.xy + uPosXform.zw;"
45 "sk_Position.zw = half2(0, 1);"
46 "}");
47
48 std::string fragShaderText;
49 fragShaderText.append(
50 "layout(vulkan, input_attachment_index=0, set=2, binding=0) subpassInput uInput;"
51
52 "// MSAA Load Program FS\n"
53 "void main() {"
54 "sk_FragColor = subpassLoad(uInput);"
55 "}");
56
57 SkSL::ProgramSettings settings;
58 std::string spirv;
61 &fVertShaderModule, &fShaderStageInfo[0], settings, &spirv,
62 &interface)) {
63 this->destroyResources(gpu);
64 return false;
65 }
66 SkASSERT(interface == SkSL::Program::Interface());
67
69 &fFragShaderModule, &fShaderStageInfo[1], settings, &spirv,
70 &interface)) {
71 this->destroyResources(gpu);
72 return false;
73 }
74 SkASSERT(interface == SkSL::Program::Interface());
75
76 VkDescriptorSetLayout dsLayout[GrVkUniformHandler::kDescSetCount];
77
78 GrVkResourceProvider& resourceProvider = gpu->resourceProvider();
79
81
82 // Even though we don't have a sampler we need to put a valid handle here (of zero samplers)
83 // since we set up our descriptor layout to be uniform, sampler, input.
84 //
85 // TODO: We should have a more general way for different pipelines to describe their descriptor
86 // layouts so that we don't have to use the compile time constants for the sets.
87 GrVkDescriptorSetManager::Handle samplerHandle;
88 resourceProvider.getZeroSamplerDescriptorSetHandle(&samplerHandle);
89
91 resourceProvider.getSamplerDSLayout(samplerHandle);
92
93 dsLayout[GrVkUniformHandler::kInputDescSet] = resourceProvider.getInputDSLayout();
94
95 // Create the VkPipelineLayout
96 VkPipelineLayoutCreateInfo layoutCreateInfo;
97 memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
99 layoutCreateInfo.pNext = nullptr;
100 layoutCreateInfo.flags = 0;
102 layoutCreateInfo.pSetLayouts = dsLayout;
103 layoutCreateInfo.pushConstantRangeCount = 0;
104 layoutCreateInfo.pPushConstantRanges = nullptr;
105
106 VkResult err = GR_VK_CALL(
107 gpu->vkInterface(),
108 CreatePipelineLayout(gpu->device(), &layoutCreateInfo, nullptr, &fPipelineLayout));
109 if (err) {
110 this->destroyResources(gpu);
111 return false;
112 }
113
114 return true;
115}
116
118 GrVkCommandBuffer* commandBuffer,
119 const GrVkRenderPass& renderPass,
120 GrAttachment* dst,
121 GrVkImage* src,
122 const SkIRect& rect) {
123 if (!dst) {
124 return false;
125 }
126 if (!src || !src->supportsInputAttachmentUsage()) {
127 return false;
128 }
129
130 if (VK_NULL_HANDLE == fVertShaderModule) {
131 SkASSERT(fFragShaderModule == VK_NULL_HANDLE && fPipelineLayout == VK_NULL_HANDLE);
132 if (!this->createMSAALoadProgram(gpu)) {
133 SkDebugf("Failed to create copy program.\n");
134 return false;
135 }
136 }
137 SkASSERT(fPipelineLayout != VK_NULL_HANDLE);
138
139 GrVkResourceProvider& resourceProv = gpu->resourceProvider();
140
142 resourceProv.findOrCreateMSAALoadPipeline(renderPass, dst->numSamples(),
143 fShaderStageInfo, fPipelineLayout);
144 if (!pipeline) {
145 return false;
146 }
147 commandBuffer->bindPipeline(gpu, std::move(pipeline));
148
149 // Set Dynamic viewport and stencil
150 // We always use one viewport the size of the RT
151 VkViewport viewport;
152 viewport.x = 0.0f;
153 viewport.y = 0.0f;
154 viewport.width = SkIntToScalar(dst->width());
155 viewport.height = SkIntToScalar(dst->height());
156 viewport.minDepth = 0.0f;
157 viewport.maxDepth = 1.0f;
158 commandBuffer->setViewport(gpu, 0, 1, &viewport);
159
160 // We assume the scissor is not enabled so just set it to the whole RT
161 VkRect2D scissor;
162 scissor.extent.width = dst->width();
163 scissor.extent.height = dst->height();
164 scissor.offset.x = 0;
165 scissor.offset.y = 0;
166 commandBuffer->setScissor(gpu, 0, 1, &scissor);
167
168 // Update and bind uniform descriptor set
169 int w = rect.width();
170 int h = rect.height();
171
172 // dst rect edges in NDC (-1 to 1)
173 int dw = dst->width();
174 int dh = dst->height();
175 float dx0 = 2.f * rect.fLeft / dw - 1.f;
176 float dx1 = 2.f * (rect.fLeft + w) / dw - 1.f;
177 float dy0 = 2.f * rect.fTop / dh - 1.f;
178 float dy1 = 2.f * (rect.fTop + h) / dh - 1.f;
179
180 float uniData[] = {dx1 - dx0, dy1 - dy0, dx0, dy0}; // posXform
181
182 GrResourceProvider* resourceProvider = gpu->getContext()->priv().resourceProvider();
183 // TODO: Is it worth holding onto the last used uniform buffer and tracking the width, height,
184 // dst width, and dst height so that we can use the buffer again without having to update the
185 // data?
186 sk_sp<GrGpuBuffer> uniformBuffer = resourceProvider->createBuffer(uniData,
187 sizeof(uniData),
190 if (!uniformBuffer) {
191 return false;
192 }
193 GrVkBuffer* vkUniformBuffer = static_cast<GrVkBuffer*>(uniformBuffer.get());
195 commandBuffer->bindDescriptorSets(gpu, fPipelineLayout,
197 /*setCount=*/1, vkUniformBuffer->uniformDescriptorSet(),
198 /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr);
199 commandBuffer->addGrBuffer(std::move(uniformBuffer));
200
201 // Update the input descriptor set
202 gr_rp<const GrVkDescriptorSet> inputDS = src->inputDescSetForMSAALoad(gpu);
203 if (!inputDS) {
204 return false;
205 }
206 commandBuffer->bindDescriptorSets(gpu, fPipelineLayout,
207 GrVkUniformHandler::kInputDescSet, /*setCount=*/1,
208 inputDS->descriptorSet(),
209 /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr);
210
211 // We don't need to add the src and dst resources here since those are all tracked by the main
212 // render pass code out in GrVkOpsRenderPass and GrVkRenderTarget::adResources.
213 commandBuffer->addRecycledResource(std::move(inputDS));
214
215 commandBuffer->draw(gpu, 4, 1, 0, 0);
216
217 return true;
218}
219
221 if (fVertShaderModule != VK_NULL_HANDLE) {
222 GR_VK_CALL(gpu->vkInterface(),
223 DestroyShaderModule(gpu->device(), fVertShaderModule, nullptr));
224 fVertShaderModule = VK_NULL_HANDLE;
225 }
226
227 if (fFragShaderModule != VK_NULL_HANDLE) {
228 GR_VK_CALL(gpu->vkInterface(),
229 DestroyShaderModule(gpu->device(), fFragShaderModule, nullptr));
230 fFragShaderModule = VK_NULL_HANDLE;
231 }
232
233 if (fPipelineLayout != VK_NULL_HANDLE) {
234 GR_VK_CALL(gpu->vkInterface(),
235 DestroyPipelineLayout(gpu->device(), fPipelineLayout, nullptr));
236 fPipelineLayout = VK_NULL_HANDLE;
237 }
238}
239
@ kDynamic_GrAccessPattern
bool GrCompileVkShaderModule(GrVkGpu *gpu, const std::string &shaderString, VkShaderStageFlagBits stage, VkShaderModule *shaderModule, VkPipelineShaderStageCreateInfo *stageInfo, const SkSL::ProgramSettings &settings, std::string *outSPIRV, SkSL::Program::Interface *outInterface)
Definition GrVkUtil.cpp:64
#define GR_VK_CALL(IFACE, X)
Definition GrVkUtil.h:24
#define SkASSERT(cond)
Definition SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define SkIntToScalar(x)
Definition SkScalar.h:57
#define TRACE_FUNC
GrResourceProvider * resourceProvider()
GrDirectContextPriv priv()
GrDirectContext * getContext()
Definition GrGpu.h:67
sk_sp< GrGpuBuffer > createBuffer(size_t size, GrGpuBufferType, GrAccessPattern, ZeroInit)
const VkDescriptorSet * uniformDescriptorSet() const
void setViewport(const GrVkGpu *gpu, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *viewports)
void bindPipeline(const GrVkGpu *gpu, sk_sp< const GrVkPipeline > pipeline)
void addRecycledResource(gr_rp< const GrRecycledResource > resource)
void setScissor(const GrVkGpu *gpu, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors)
void addGrBuffer(sk_sp< const GrBuffer > buffer)
void bindDescriptorSets(const GrVkGpu *gpu, VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, const VkDescriptorSet *descriptorSets, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets)
void draw(const GrVkGpu *gpu, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
const skgpu::VulkanInterface * vkInterface() const
Definition GrVkGpu.h:60
VkDevice device() const
Definition GrVkGpu.h:71
GrVkResourceProvider & resourceProvider()
Definition GrVkGpu.h:83
bool loadMSAAFromResolve(GrVkGpu *gpu, GrVkCommandBuffer *commandBuffer, const GrVkRenderPass &renderPass, GrAttachment *dst, GrVkImage *src, const SkIRect &srcRect)
void destroyResources(GrVkGpu *gpu)
VkDescriptorSetLayout getInputDSLayout() const
VkDescriptorSetLayout getUniformDSLayout() const
VkDescriptorSetLayout getSamplerDSLayout(const GrVkDescriptorSetManager::Handle &) const
void getZeroSamplerDescriptorSetHandle(GrVkDescriptorSetManager::Handle *handle)
sk_sp< const GrVkPipeline > findOrCreateMSAALoadPipeline(const GrVkRenderPass &renderPass, int numSamples, VkPipelineShaderStageCreateInfo *, VkPipelineLayout)
static constexpr int kDescSetCount
T * get() const
Definition SkRefCnt.h:303
SkScalar w
SkScalar h
uint32_t width
uint32_t height
VkPipelineLayoutCreateFlags flags
const VkPushConstantRange * pPushConstantRanges
const VkDescriptorSetLayout * pSetLayouts
VkExtent2D extent
VkOffset2D offset
#define TRACE_EVENT0(category_group, name)
@ VK_SHADER_STAGE_VERTEX_BIT
@ VK_SHADER_STAGE_FRAGMENT_BIT
VkFlags VkPipelineLayoutCreateFlags
VkResult
#define VK_NULL_HANDLE
Definition vulkan_core.h:46
@ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO