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