| 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_spv_module_t module = shaderc_compile_into_spv(compiler, | |
| 111 shaderString.c_str(), | |
| 112 strlen(shaderString.c
_str()), | |
| 113 shadercStage, | |
| 114 "shader", | |
| 115 "main", | |
| 116 options); | |
| 117 shaderc_compile_options_release(options); | |
| 118 #ifdef SK_DEBUG | |
| 119 if (shaderc_module_get_num_errors(module)) { | |
| 120 SkDebugf("%s\n", shaderString.c_str()); | |
| 121 SkDebugf("%s\n", shaderc_module_get_error_message(module)); | |
| 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_module_get_length(module); | |
| 132 moduleCreateInfo.pCode = (const uint32_t*)shaderc_module_get_bytes(module); | |
| 133 | |
| 134 VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateShaderModule(gpu->device
(), | |
| 135 &moduleCrea
teInfo, | |
| 136 nullptr, | |
| 137 shaderModul
e)); | |
| 138 shaderc_module_release(module); | |
| 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 |