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 |