OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2016 Google Inc. | |
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 "vk/GrVkProgramBuilder.h" | |
9 | |
10 #include "vk/GrVkGpu.h" | |
11 #include "vk/GrVkRenderPass.h" | |
12 #include "vk/GrVkProgram.h" | |
13 | |
14 GrVkProgram* GrVkProgramBuilder::CreateProgram(GrVkGpu* gpu, | |
15 const DrawArgs& args, | |
16 GrPrimitiveType primitiveType, | |
17 const GrVkRenderPass& renderPass)
{ | |
18 // create a builder. This will be handed off to effects so they can use it
to add | |
19 // uniforms, varyings, textures, etc | |
20 GrVkProgramBuilder builder(gpu, args); | |
21 | |
22 GrGLSLExpr4 inputColor; | |
23 GrGLSLExpr4 inputCoverage; | |
24 | |
25 if (!builder.emitAndInstallProcs(&inputColor, | |
26 &inputCoverage, | |
27 gpu->vkCaps().maxSampledTextures())) { | |
28 builder.cleanupFragmentProcessors(); | |
29 return nullptr; | |
30 } | |
31 | |
32 return builder.finalize(args, primitiveType, renderPass); | |
33 } | |
34 | |
35 GrVkProgramBuilder::GrVkProgramBuilder(GrVkGpu* gpu, const DrawArgs& args) | |
36 : INHERITED(args) | |
37 , fGpu(gpu) | |
38 , fVaryingHandler(this) | |
39 , fUniformHandler(this) { | |
40 } | |
41 | |
42 const GrCaps* GrVkProgramBuilder::caps() const { | |
43 return fGpu->caps(); | |
44 } | |
45 const GrGLSLCaps* GrVkProgramBuilder::glslCaps() const { | |
46 return fGpu->vkCaps().glslCaps(); | |
47 } | |
48 | |
49 void GrVkProgramBuilder::finalizeFragmentOutputColor(GrGLSLShaderVar& outputColo
r) { | |
50 outputColor.setLayoutQualifier("location = 0"); | |
51 } | |
52 | |
53 void GrVkProgramBuilder::emitSamplers(const GrProcessor& processor, | |
54 GrGLSLTextureSampler::TextureSamplerArray*
outSamplers) { | |
55 int numTextures = processor.numTextures(); | |
56 UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextur
es); | |
57 SkString name; | |
58 for (int t = 0; t < numTextures; ++t) { | |
59 name.printf("%d", t); | |
60 localSamplerUniforms[t] = | |
61 fUniformHandler.addUniform(kFragment_GrShaderFlag, | |
62 kSampler2D_GrSLType, kDefault_GrSLPrecisi
on, | |
63 name.c_str()); | |
64 outSamplers->emplace_back(localSamplerUniforms[t], processor.textureAcce
ss(t)); | |
65 } | |
66 } | |
67 | |
68 VkShaderStageFlags visibility_to_vk_stage_flags(uint32_t visibility) { | |
69 VkShaderStageFlags flags = 0; | |
70 | |
71 if (visibility & kVertex_GrShaderFlag) { | |
72 flags |= VK_SHADER_STAGE_VERTEX_BIT; | |
73 } | |
74 if (visibility & kGeometry_GrShaderFlag) { | |
75 flags |= VK_SHADER_STAGE_GEOMETRY_BIT; | |
76 } | |
77 if (visibility & kFragment_GrShaderFlag) { | |
78 flags |= VK_SHADER_STAGE_FRAGMENT_BIT; | |
79 } | |
80 return flags; | |
81 } | |
82 | |
83 shaderc_shader_kind vk_shader_stage_to_shaderc_kind(VkShaderStageFlagBits stage)
{ | |
84 if (VK_SHADER_STAGE_VERTEX_BIT == stage) { | |
85 return shaderc_glsl_vertex_shader; | |
86 } | |
87 SkASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == stage); | |
88 return shaderc_glsl_fragment_shader; | |
89 } | |
90 | |
91 bool GrVkProgramBuilder::CreateVkShaderModule(const GrVkGpu* gpu, | |
92 VkShaderStageFlagBits stage, | |
93 const GrGLSLShaderBuilder& builder
, | |
94 VkShaderModule* shaderModule, | |
95 VkPipelineShaderStageCreateInfo* s
tageInfo) { | |
96 SkString shaderString; | |
97 for (int i = 0; i < builder.fCompilerStrings.count(); ++i) { | |
98 if (builder.fCompilerStrings[i]) { | |
99 shaderString.append(builder.fCompilerStrings[i]); | |
100 shaderString.append("\n"); | |
101 } | |
102 } | |
103 | |
104 shaderc_compiler_t compiler = gpu->shadercCompiler(); | |
105 | |
106 shaderc_compile_options_t options = shaderc_compile_options_initialize(); | |
107 shaderc_compile_options_set_forced_version_profile(options, 140, shaderc_pro
file_none); | |
108 | |
109 shaderc_shader_kind shadercStage = vk_shader_stage_to_shaderc_kind(stage); | |
110 shaderc_compilation_result_t result = shaderc_compile_into_spv(compiler, | |
111 shaderString.
c_str(), | |
112 strlen(shader
String.c_str()), | |
113 shadercStage, | |
114 "shader", | |
115 "main", | |
116 options); | |
117 shaderc_compile_options_release(options); | |
118 #ifdef SK_DEBUG | |
119 if (shaderc_result_get_num_errors(result)) { | |
120 SkDebugf("%s\n", shaderString.c_str()); | |
121 SkDebugf("%s\n", shaderc_result_get_error_message(result)); | |
122 return false; | |
123 } | |
124 #endif | |
125 | |
126 VkShaderModuleCreateInfo moduleCreateInfo; | |
127 memset(&moduleCreateInfo, 0, sizeof(VkShaderModuleCreateInfo)); | |
128 moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; | |
129 moduleCreateInfo.pNext = nullptr; | |
130 moduleCreateInfo.flags = 0; | |
131 moduleCreateInfo.codeSize = shaderc_result_get_length(result); | |
132 moduleCreateInfo.pCode = (const uint32_t*)shaderc_result_get_bytes(result); | |
133 | |
134 VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateShaderModule(gpu->device
(), | |
135 &moduleCrea
teInfo, | |
136 nullptr, | |
137 shaderModul
e)); | |
138 shaderc_result_release(result); | |
139 if (err) { | |
140 return false; | |
141 } | |
142 | |
143 memset(stageInfo, 0, sizeof(VkPipelineShaderStageCreateInfo)); | |
144 stageInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; | |
145 stageInfo->pNext = nullptr; | |
146 stageInfo->flags = 0; | |
147 stageInfo->stage = stage; | |
148 stageInfo->module = *shaderModule; | |
149 stageInfo->pName = "main"; | |
150 stageInfo->pSpecializationInfo = nullptr; | |
151 | |
152 return true; | |
153 } | |
154 | |
155 GrVkProgram* GrVkProgramBuilder::finalize(const DrawArgs& args, | |
156 GrPrimitiveType primitiveType, | |
157 const GrVkRenderPass& renderPass) { | |
158 VkDescriptorSetLayout dsLayout[2]; | |
159 VkPipelineLayout pipelineLayout; | |
160 VkShaderModule vertShaderModule; | |
161 VkShaderModule fragShaderModule; | |
162 | |
163 uint32_t numSamplers = fSamplerUniforms.count(); | |
164 | |
165 SkAutoTDeleteArray<VkDescriptorSetLayoutBinding> dsSamplerBindings( | |
166 new VkDescriptorSetLayoutBi
nding[numSamplers]); | |
167 for (uint32_t i = 0; i < numSamplers; ++i) { | |
168 UniformHandle uniHandle = fSamplerUniforms[i]; | |
169 GrVkUniformHandler::UniformInfo uniformInfo = fUniformHandler.getUniform
Info(uniHandle); | |
170 SkASSERT(kSampler2D_GrSLType == uniformInfo.fVariable.getType()); | |
171 SkASSERT(0 == uniformInfo.fSetNumber); | |
172 SkASSERT(uniformInfo.fBinding == i); | |
173 dsSamplerBindings[i].binding = uniformInfo.fBinding; | |
174 dsSamplerBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_
SAMPLER; | |
175 dsSamplerBindings[i].descriptorCount = 1; | |
176 dsSamplerBindings[i].stageFlags = visibility_to_vk_stage_flags(uniformIn
fo.fVisibility); | |
177 dsSamplerBindings[i].pImmutableSamplers = nullptr; | |
178 } | |
179 | |
180 VkDescriptorSetLayoutCreateInfo dsSamplerLayoutCreateInfo; | |
181 memset(&dsSamplerLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo
)); | |
182 dsSamplerLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CR
EATE_INFO; | |
183 dsSamplerLayoutCreateInfo.pNext = nullptr; | |
184 dsSamplerLayoutCreateInfo.flags = 0; | |
185 dsSamplerLayoutCreateInfo.bindingCount = fSamplerUniforms.count(); | |
186 // Setting to nullptr fixes an error in the param checker validation layer.
Even though | |
187 // bindingCount is 0 (which is valid), it still tries to validate pBindings
unless it is null. | |
188 dsSamplerLayoutCreateInfo.pBindings = fSamplerUniforms.count() ? dsSamplerBi
ndings.get() : | |
189 nullptr; | |
190 | |
191 GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), | |
192 CreateDescriptorSetLayout(fGpu->device(), | |
193 &dsSamplerLayoutCreateInfo, | |
194 nullptr, | |
195 &dsLayout[GrVkUniformHandler::
kSamplerDescSet])); | |
196 | |
197 // Create Uniform Buffer Descriptor | |
198 // We always attach uniform buffers to descriptor set 1. The vertex uniform
buffer will have | |
199 // binding 0 and the fragment binding 1. | |
200 VkDescriptorSetLayoutBinding dsUniBindings[2]; | |
201 memset(&dsUniBindings, 0, 2 * sizeof(VkDescriptorSetLayoutBinding)); | |
202 dsUniBindings[0].binding = GrVkUniformHandler::kVertexBinding; | |
203 dsUniBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; | |
204 dsUniBindings[0].descriptorCount = fUniformHandler.hasVertexUniforms() ? 1 :
0; | |
205 dsUniBindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; | |
206 dsUniBindings[0].pImmutableSamplers = nullptr; | |
207 dsUniBindings[1].binding = GrVkUniformHandler::kFragBinding; | |
208 dsUniBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; | |
209 dsUniBindings[1].descriptorCount = fUniformHandler.hasFragmentUniforms() ? 1
: 0; | |
210 dsUniBindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; | |
211 dsUniBindings[1].pImmutableSamplers = nullptr; | |
212 | |
213 VkDescriptorSetLayoutCreateInfo dsUniformLayoutCreateInfo; | |
214 memset(&dsUniformLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo
)); | |
215 dsUniformLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CR
EATE_INFO; | |
216 dsUniformLayoutCreateInfo.pNext = nullptr; | |
217 dsUniformLayoutCreateInfo.flags = 0; | |
218 dsUniformLayoutCreateInfo.bindingCount = 2; | |
219 dsUniformLayoutCreateInfo.pBindings = dsUniBindings; | |
220 | |
221 GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreateDescriptorSetLayout( | |
222 fGpu->device(), | |
223 &dsUniformLayoutCreateInfo, | |
224 nullptr, | |
225 &dsLayout[GrVkUniformHandler::kUnif
ormBufferDescSet])); | |
226 | |
227 // Create the VkPipelineLayout | |
228 VkPipelineLayoutCreateInfo layoutCreateInfo; | |
229 memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags)); | |
230 layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; | |
231 layoutCreateInfo.pNext = 0; | |
232 layoutCreateInfo.flags = 0; | |
233 layoutCreateInfo.setLayoutCount = 2; | |
234 layoutCreateInfo.pSetLayouts = dsLayout; | |
235 layoutCreateInfo.pushConstantRangeCount = 0; | |
236 layoutCreateInfo.pPushConstantRanges = nullptr; | |
237 | |
238 GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device()
, | |
239 &layoutCreateI
nfo, | |
240 nullptr, | |
241 &pipelineLayou
t)); | |
242 | |
243 // We need to enable the following extensions so that the compiler can corre
ctly make spir-v | |
244 // from our glsl shaders. | |
245 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable
\n"); | |
246 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable
\n"); | |
247 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enabl
e\n"); | |
248 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enabl
e\n"); | |
249 | |
250 this->finalizeShaders(); | |
251 | |
252 VkPipelineShaderStageCreateInfo shaderStageInfo[2]; | |
253 SkAssertResult(CreateVkShaderModule(fGpu, | |
254 VK_SHADER_STAGE_VERTEX_BIT, | |
255 fVS, | |
256 &vertShaderModule, | |
257 &shaderStageInfo[0])); | |
258 | |
259 SkAssertResult(CreateVkShaderModule(fGpu, | |
260 VK_SHADER_STAGE_FRAGMENT_BIT, | |
261 fFS, | |
262 &fragShaderModule, | |
263 &shaderStageInfo[1])); | |
264 | |
265 GrVkResourceProvider& resourceProvider = fGpu->resourceProvider(); | |
266 GrVkPipeline* pipeline = resourceProvider.createPipeline(*args.fPipeline, | |
267 *args.fPrimitivePro
cessor, | |
268 shaderStageInfo, | |
269 2, | |
270 primitiveType, | |
271 renderPass, | |
272 pipelineLayout); | |
273 GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShad
erModule, | |
274 nullptr)); | |
275 GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShad
erModule, | |
276 nullptr)); | |
277 | |
278 if (!pipeline) { | |
279 GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pi
pelineLayout, | |
280 nullptr)); | |
281 GR_VK_CALL(fGpu->vkInterface(), DestroyDescriptorSetLayout(fGpu->device(
), dsLayout[0], | |
282 nullptr)); | |
283 GR_VK_CALL(fGpu->vkInterface(), DestroyDescriptorSetLayout(fGpu->device(
), dsLayout[1], | |
284 nullptr)); | |
285 return nullptr; | |
286 } | |
287 | |
288 | |
289 GrVkDescriptorPool::DescriptorTypeCounts typeCounts; | |
290 typeCounts.setTypeCount(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2); | |
291 SkASSERT(numSamplers < 256); | |
292 typeCounts.setTypeCount(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, (uint8_t)
numSamplers); | |
293 GrVkDescriptorPool* descriptorPool = | |
294 fGpu->resourceProvider().findOrCreateCompatibleDescriptorPool(typeCounts
); | |
295 | |
296 VkDescriptorSetAllocateInfo dsAllocateInfo; | |
297 memset(&dsAllocateInfo, 0, sizeof(VkDescriptorSetAllocateInfo)); | |
298 dsAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; | |
299 dsAllocateInfo.pNext = nullptr; | |
300 dsAllocateInfo.descriptorPool = descriptorPool->descPool(); | |
301 dsAllocateInfo.descriptorSetCount = 2; | |
302 dsAllocateInfo.pSetLayouts = dsLayout; | |
303 | |
304 VkDescriptorSet descriptorSets[2]; | |
305 GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), AllocateDescriptorSets(fGpu->device
(), | |
306 &dsAllocateI
nfo, | |
307 descriptorSe
ts)); | |
308 | |
309 return new GrVkProgram(fGpu, | |
310 pipeline, | |
311 pipelineLayout, | |
312 dsLayout, | |
313 descriptorPool, | |
314 descriptorSets, | |
315 fUniformHandles, | |
316 fUniformHandler.fUniforms, | |
317 fUniformHandler.fCurrentVertexUBOOffset, | |
318 fUniformHandler.fCurrentFragmentUBOOffset, | |
319 numSamplers, | |
320 fGeometryProcessor, | |
321 fXferProcessor, | |
322 fFragmentProcessors); | |
323 } | |
OLD | NEW |