123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- /*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/gpu/GrContext.h"
- #include "src/gpu/GrContextPriv.h"
- #include "src/gpu/GrPersistentCacheUtils.h"
- #include "src/gpu/GrShaderCaps.h"
- #include "src/gpu/GrShaderUtils.h"
- #include "src/gpu/GrStencilSettings.h"
- #include "src/gpu/vk/GrVkDescriptorSetManager.h"
- #include "src/gpu/vk/GrVkGpu.h"
- #include "src/gpu/vk/GrVkPipelineStateBuilder.h"
- #include "src/gpu/vk/GrVkRenderPass.h"
- #include "src/gpu/vk/GrVkRenderTarget.h"
- typedef size_t shader_size;
- GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
- GrVkGpu* gpu,
- GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
- const GrPrimitiveProcessor& primProc,
- const GrTextureProxy* const primProcProxies[],
- const GrPipeline& pipeline,
- const GrStencilSettings& stencil,
- GrPrimitiveType primitiveType,
- Desc* desc,
- VkRenderPass compatibleRenderPass) {
- // create a builder. This will be handed off to effects so they can use it to add
- // uniforms, varyings, textures, etc
- GrVkPipelineStateBuilder builder(gpu, renderTarget, origin, pipeline, primProc,
- primProcProxies, desc);
- if (!builder.emitAndInstallProcs()) {
- return nullptr;
- }
- return builder.finalize(stencil, primitiveType, compatibleRenderPass, desc);
- }
- GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
- GrRenderTarget* renderTarget,
- GrSurfaceOrigin origin,
- const GrPipeline& pipeline,
- const GrPrimitiveProcessor& primProc,
- const GrTextureProxy* const primProcProxies[],
- GrProgramDesc* desc)
- : INHERITED(renderTarget, origin, primProc, primProcProxies, pipeline, desc)
- , fGpu(gpu)
- , fVaryingHandler(this)
- , fUniformHandler(this) {}
- const GrCaps* GrVkPipelineStateBuilder::caps() const {
- return fGpu->caps();
- }
- void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
- outputColor.addLayoutQualifier("location = 0, index = 0");
- }
- void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
- outputColor.addLayoutQualifier("location = 0, index = 1");
- }
- bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
- const SkSL::String& sksl,
- VkShaderModule* shaderModule,
- VkPipelineShaderStageCreateInfo* stageInfo,
- const SkSL::Program::Settings& settings,
- Desc* desc,
- SkSL::String* outSPIRV,
- SkSL::Program::Inputs* outInputs) {
- if (!GrCompileVkShaderModule(fGpu, sksl, stage, shaderModule,
- stageInfo, settings, outSPIRV, outInputs)) {
- return false;
- }
- if (outInputs->fRTHeight) {
- this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
- }
- return true;
- }
- bool GrVkPipelineStateBuilder::installVkShaderModule(VkShaderStageFlagBits stage,
- const GrGLSLShaderBuilder& builder,
- VkShaderModule* shaderModule,
- VkPipelineShaderStageCreateInfo* stageInfo,
- SkSL::String spirv,
- SkSL::Program::Inputs inputs) {
- if (!GrInstallVkShaderModule(fGpu, spirv, stage, shaderModule, stageInfo)) {
- return false;
- }
- if (inputs.fRTHeight) {
- this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
- }
- return true;
- }
- static constexpr SkFourByteTag kSPIRV_Tag = SkSetFourByteTag('S', 'P', 'R', 'V');
- static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
- int GrVkPipelineStateBuilder::loadShadersFromCache(const SkData& cached,
- VkShaderModule outShaderModules[],
- VkPipelineShaderStageCreateInfo* outStageInfo) {
- SkSL::String shaders[kGrShaderTypeCount];
- SkSL::Program::Inputs inputs[kGrShaderTypeCount];
- if (kSPIRV_Tag != GrPersistentCacheUtils::UnpackCachedShaders(&cached, shaders,
- inputs, kGrShaderTypeCount)) {
- return 0;
- }
- SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
- fVS,
- &outShaderModules[kVertex_GrShaderType],
- &outStageInfo[0],
- shaders[kVertex_GrShaderType],
- inputs[kVertex_GrShaderType]));
- SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
- fFS,
- &outShaderModules[kFragment_GrShaderType],
- &outStageInfo[1],
- shaders[kFragment_GrShaderType],
- inputs[kFragment_GrShaderType]));
- if (!shaders[kGeometry_GrShaderType].empty()) {
- SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
- fGS,
- &outShaderModules[kGeometry_GrShaderType],
- &outStageInfo[2],
- shaders[kGeometry_GrShaderType],
- inputs[kGeometry_GrShaderType]));
- return 3;
- } else {
- return 2;
- }
- }
- void GrVkPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[],
- const SkSL::Program::Inputs inputs[],
- bool isSkSL) {
- Desc* desc = static_cast<Desc*>(this->desc());
- sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
- sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kSPIRV_Tag,
- shaders,
- inputs, kGrShaderTypeCount);
- this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
- }
- GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
- GrPrimitiveType primitiveType,
- VkRenderPass compatibleRenderPass,
- Desc* desc) {
- VkDescriptorSetLayout dsLayout[2];
- VkPipelineLayout pipelineLayout;
- VkShaderModule shaderModules[kGrShaderTypeCount] = { VK_NULL_HANDLE,
- VK_NULL_HANDLE,
- VK_NULL_HANDLE };
- GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
- // These layouts are not owned by the PipelineStateBuilder and thus should not be destroyed
- dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
- GrVkDescriptorSetManager::Handle samplerDSHandle;
- resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- fUniformHandler, &samplerDSHandle);
- dsLayout[GrVkUniformHandler::kSamplerDescSet] =
- resourceProvider.getSamplerDSLayout(samplerDSHandle);
- // Create the VkPipelineLayout
- VkPipelineLayoutCreateInfo layoutCreateInfo;
- memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
- layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
- layoutCreateInfo.pNext = 0;
- layoutCreateInfo.flags = 0;
- layoutCreateInfo.setLayoutCount = 2;
- layoutCreateInfo.pSetLayouts = dsLayout;
- layoutCreateInfo.pushConstantRangeCount = 0;
- layoutCreateInfo.pPushConstantRanges = nullptr;
- GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device(),
- &layoutCreateInfo,
- nullptr,
- &pipelineLayout));
- // We need to enable the following extensions so that the compiler can correctly make spir-v
- // from our glsl shaders.
- fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
- fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
- fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
- fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
- this->finalizeShaders();
- VkPipelineShaderStageCreateInfo shaderStageInfo[3];
- SkSL::Program::Settings settings;
- settings.fCaps = this->caps()->shaderCaps();
- settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
- settings.fSharpenTextures =
- this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
- SkASSERT(!this->fragColorIsInOut());
- sk_sp<SkData> cached;
- auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
- if (persistentCache) {
- sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
- cached = persistentCache->load(*key);
- }
- bool binaryCache = true;
- #if GR_TEST_UTILS
- binaryCache = !fGpu->getContext()->priv().options().fCacheSKSL;
- #endif
- int numShaderStages = 0;
- if (cached && binaryCache) {
- numShaderStages = this->loadShadersFromCache(*cached, shaderModules, shaderStageInfo);
- }
- if (!numShaderStages) {
- numShaderStages = 2; // We always have at least vertex and fragment stages.
- SkSL::String shaders[kGrShaderTypeCount];
- SkSL::Program::Inputs inputs[kGrShaderTypeCount];
- SkSL::String* sksl[kGrShaderTypeCount] = {
- &fVS.fCompilerString,
- &fGS.fCompilerString,
- &fFS.fCompilerString,
- };
- #if GR_TEST_UTILS
- SkSL::String cached_sksl[kGrShaderTypeCount];
- if (cached) {
- if (kSKSL_Tag == GrPersistentCacheUtils::UnpackCachedShaders(
- cached.get(), cached_sksl, inputs, kGrShaderTypeCount)) {
- for (int i = 0; i < kGrShaderTypeCount; ++i) {
- sksl[i] = &cached_sksl[i];
- }
- }
- }
- #endif
- bool success = this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
- *sksl[kVertex_GrShaderType],
- &shaderModules[kVertex_GrShaderType],
- &shaderStageInfo[0],
- settings,
- desc,
- &shaders[kVertex_GrShaderType],
- &inputs[kVertex_GrShaderType]);
- success = success && this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
- *sksl[kFragment_GrShaderType],
- &shaderModules[kFragment_GrShaderType],
- &shaderStageInfo[1],
- settings,
- desc,
- &shaders[kFragment_GrShaderType],
- &inputs[kFragment_GrShaderType]);
- if (this->primitiveProcessor().willUseGeoShader()) {
- success = success && this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
- *sksl[kGeometry_GrShaderType],
- &shaderModules[kGeometry_GrShaderType],
- &shaderStageInfo[2],
- settings,
- desc,
- &shaders[kGeometry_GrShaderType],
- &inputs[kGeometry_GrShaderType]);
- ++numShaderStages;
- }
- if (!success) {
- for (int i = 0; i < kGrShaderTypeCount; ++i) {
- if (shaderModules[i]) {
- GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(),
- shaderModules[i], nullptr));
- }
- }
- GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
- nullptr));
- return nullptr;
- }
- if (persistentCache && !cached) {
- bool isSkSL = false;
- #if GR_TEST_UTILS
- if (fGpu->getContext()->priv().options().fCacheSKSL) {
- for (int i = 0; i < kGrShaderTypeCount; ++i) {
- shaders[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
- }
- isSkSL = true;
- }
- #endif
- this->storeShadersInCache(shaders, inputs, isSkSL);
- }
- }
- GrVkPipeline* pipeline = resourceProvider.createPipeline(
- this->renderTarget()->numSamples(), fPrimProc, fPipeline, stencil, this->origin(),
- shaderStageInfo, numShaderStages, primitiveType, compatibleRenderPass, pipelineLayout);
- for (int i = 0; i < kGrShaderTypeCount; ++i) {
- // This if check should not be needed since calling destroy on a VK_NULL_HANDLE is allowed.
- // However this is causing a crash in certain drivers (e.g. NVidia).
- if (shaderModules[i]) {
- GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), shaderModules[i],
- nullptr));
- }
- }
- if (!pipeline) {
- GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
- nullptr));
- return nullptr;
- }
- return new GrVkPipelineState(fGpu,
- pipeline,
- pipelineLayout,
- samplerDSHandle,
- fUniformHandles,
- fUniformHandler.fUniforms,
- fUniformHandler.fCurrentGeometryUBOOffset,
- fUniformHandler.fCurrentFragmentUBOOffset,
- fUniformHandler.fSamplers,
- std::move(fGeometryProcessor),
- std::move(fXferProcessor),
- std::move(fFragmentProcessors),
- fFragmentProcessorCnt);
- }
- //////////////////////////////////////////////////////////////////////////////
- bool GrVkPipelineStateBuilder::Desc::Build(Desc* desc,
- GrRenderTarget* renderTarget,
- const GrPrimitiveProcessor& primProc,
- const GrPipeline& pipeline,
- const GrStencilSettings& stencil,
- GrPrimitiveType primitiveType,
- GrVkGpu* gpu) {
- if (!INHERITED::Build(desc, renderTarget, primProc,
- primitiveType == GrPrimitiveType::kPoints, pipeline, gpu)) {
- return false;
- }
- GrProcessorKeyBuilder b(&desc->key());
- b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
- int keyLength = desc->key().count();
- SkASSERT(0 == (keyLength % 4));
- desc->fShaderKeyLength = SkToU32(keyLength);
- GrVkRenderTarget* vkRT = (GrVkRenderTarget*)renderTarget;
- vkRT->simpleRenderPass()->genKey(&b);
- stencil.genKey(&b);
- b.add32(pipeline.getBlendInfoKey());
- b.add32((uint32_t)primitiveType);
- return true;
- }
|