ptr<ShaderSource> GlslGeneratorInstance::Generate() { // first stage: register all nodes RegisterNode(rootNode); // заголовок файла switch(glslVersion) { case GlslVersions::opengl33: text << "#version 330\n"; break; case GlslVersions::webgl: // version numbers in WebGL are not supported text << "#extension GL_OES_standard_derivatives : enable\n" "#extension GL_EXT_draw_buffers : enable\n" "#ifdef GL_ES\n" "precision highp float;\n" "#endif\n"; break; default: THROW("Unknown GLSL version"); } // вывести атрибуты в качестве входных переменных, если это вершинный шейдер if(shaderType == ShaderTypes::vertex) { const char* prefixStr; switch(glslVersion) { case GlslVersions::opengl33: prefixStr = "in "; break; case GlslVersions::webgl: prefixStr = "attribute "; break; default: THROW("Unknown GLSL version"); } std::sort(attributes.begin(), attributes.end()); for(size_t i = 0; i < attributes.size(); ++i) { AttributeNode* node = attributes[i]; text << prefixStr; DataType valueType = node->GetValueType(); // hack for lack of supporting integer attributes in WebGL // change them to float if(glslVersion == GlslVersions::webgl) valueType = EnforceFloatDataType(valueType); PrintDataType(valueType); text << " a" << node->GetElementIndex() << ";\n"; } } // print transformed nodes if(!transformedNodes.empty()) { if(shaderType != ShaderTypes::pixel) THROW("Only pixel shader may have transformed nodes"); const char* prefixStr; switch(glslVersion) { case GlslVersions::opengl33: prefixStr = "in "; break; case GlslVersions::webgl: prefixStr = "varying "; break; default: THROW("Unknown GLSL version"); } for(size_t i = 0; i < transformedNodes.size(); ++i) { TransformedNode* node = transformedNodes[i]; text << prefixStr; PrintDataType(node->GetValueType()); text << " v" << node->GetSemantic() << ";\n"; } } // print interpolate nodes if(!interpolateNodes.empty()) { if(shaderType != ShaderTypes::vertex) THROW("Only vertex shader may have interpolate nodes"); const char* prefixStr; switch(glslVersion) { case GlslVersions::opengl33: prefixStr = "out "; break; case GlslVersions::webgl: prefixStr = "varying "; break; default: THROW("Unknown GLSL version"); } for(size_t i = 0; i < interpolateNodes.size(); ++i) { InterpolateNode* node = interpolateNodes[i]; text << prefixStr; PrintDataType(node->GetValueType()); text << " v" << node->GetSemantic() << ";\n"; } } // вывести пиксельные переменные, если это пиксельный шейдер, и это нужно if(shaderType == ShaderTypes::pixel && glslVersion == GlslVersions::opengl33) { for(int i = 0; i < fragmentTargetsCount; ++i) { text << "out "; PrintDataType(DataTypes::_vec4); text << " r" << i << ";\n"; } } // print uniforms PrintUniforms(); // samplers for(size_t i = 0; i < samplers.size(); ++i) { SamplerNode* samplerNode = samplers[i]; // строка, описывающая основной тип семпла const char* valueTypeStr; switch(samplerNode->GetValueType()) { case DataTypes::_float: case DataTypes::_vec2: case DataTypes::_vec3: case DataTypes::_vec4: valueTypeStr = ""; break; case DataTypes::_uint: case DataTypes::_uvec2: case DataTypes::_uvec3: case DataTypes::_uvec4: valueTypeStr = glslVersion == GlslVersions::webgl ? "i" : "u"; break; case DataTypes::_int: case DataTypes::_ivec2: case DataTypes::_ivec3: case DataTypes::_ivec4: valueTypeStr = "i"; break; default: THROW("Invalid sampler value type"); } // строка, описывающая размерность const char* dimensionStr; switch(samplerNode->GetCoordType()) { case SamplerNode::_1D: dimensionStr = "1D"; break; case SamplerNode::_2D: dimensionStr = "2D"; break; case SamplerNode::_3D: dimensionStr = "3D"; break; case SamplerNode::_Cube: dimensionStr = "Cube"; break; default: THROW("Invalid sampler coord type"); } // вывести семплер int slot = samplerNode->GetSlot(); text << "uniform " << valueTypeStr << "sampler" << dimensionStr << ' ' << samplerPrefix << slot << ";\n"; } //** заголовок функции шейдера text << "void main()\n{\n"; // shader code for(size_t i = 0; i < nodeInits.size(); ++i) PrintNodeInit(i); // завершение шейдера text << "}\n"; // make list of uniform variable bindings GlShaderBindings::UniformBindings uniformBindings; if(!supportUniformBuffers) { uniformBindings.resize(uniforms.size()); for(size_t i = 0; i < uniforms.size(); ++i) { UniformNode* node = uniforms[i].second; GlShaderBindings::UniformBinding& uniformBinding = uniformBindings[i]; uniformBinding.dataType = node->GetValueType(); uniformBinding.count = node->GetCount(); uniformBinding.slot = uniforms[i].first->GetSlot(); uniformBinding.offset = node->GetOffset(); std::ostringstream ss; ss << uniformPrefix << uniformBinding.slot << '_' << uniformBinding.offset; uniformBinding.name = ss.str(); } } // make list of uniform block bindings GlShaderBindings::Bindings uniformBlockBindings; if(supportUniformBuffers) { uniformBlockBindings.resize(uniforms.size()); for(size_t i = 0; i < uniforms.size(); ++i) { int slot = uniforms[i].first->GetSlot(); char name[16]; sprintf(name, "%s%d", uniformBufferPrefix, slot); uniformBlockBindings[i].first = name; uniformBlockBindings[i].second = slot; } // remove duplicates std::sort(uniformBlockBindings.begin(), uniformBlockBindings.end()); uniformBlockBindings.resize(std::unique(uniformBlockBindings.begin(), uniformBlockBindings.end()) - uniformBlockBindings.begin()); } // сформировать список привязок семплеров GlShaderBindings::Bindings samplerBindings(samplers.size()); for(size_t i = 0; i < samplers.size(); ++i) { int slot = samplers[i]->GetSlot(); char name[16]; sprintf(name, "%s%d", samplerPrefix, slot); samplerBindings[i].first = name; samplerBindings[i].second = slot; } // сформировать список привязок атрибутов GlShaderBindings::Bindings attributeBindings(attributes.size()); for(size_t i = 0; i < attributes.size(); ++i) { int index = attributes[i]->GetElementIndex(); char name[16]; sprintf(name, "a%d", index); attributeBindings[i].first = name; attributeBindings[i].second = index; } // make a target variables list GlShaderBindings::Bindings targetBindings; switch(glslVersion) { case GlslVersions::opengl33: targetBindings.resize(fragmentTargetsCount); for(int i = 0; i < fragmentTargetsCount; ++i) { char name[16]; sprintf(name, "r%d", i); targetBindings[i].first = name; targetBindings[i].second = i; } break; case GlslVersions::webgl: // no bindings needed, because of use of gl_FragColor/gl_FragData break; } return NEW(GlslSource( Strings::String2File(text.str()), NEW(GlShaderBindings(uniformBindings, uniformBlockBindings, samplerBindings, attributeBindings, targetBindings, dualFragmentTarget)) )); }
void GrVkPipelineState::setAndBindTextures(GrVkGpu* gpu, const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, const GrTextureProxy* const primProcTextures[], GrVkCommandBuffer* commandBuffer) { SkASSERT(primProcTextures || !primProc.numTextureSamplers()); struct SamplerBindings { GrSamplerState fState; GrVkTexture* fTexture; }; SkAutoSTMalloc<8, SamplerBindings> samplerBindings(fNumSamplers); int currTextureBinding = 0; fGeometryProcessor->setData(fDataManager, primProc, GrFragmentProcessor::CoordTransformIter(pipeline)); for (int i = 0; i < primProc.numTextureSamplers(); ++i) { const auto& sampler = primProc.textureSampler(i); auto texture = static_cast<GrVkTexture*>(primProcTextures[i]->peekTexture()); samplerBindings[currTextureBinding++] = {sampler.samplerState(), texture}; } GrFragmentProcessor::Iter iter(pipeline); GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt); const GrFragmentProcessor* fp = iter.next(); GrGLSLFragmentProcessor* glslFP = glslIter.next(); while (fp && glslFP) { for (int i = 0; i < fp->numTextureSamplers(); ++i) { const auto& sampler = fp->textureSampler(i); samplerBindings[currTextureBinding++] = {sampler.samplerState(), static_cast<GrVkTexture*>(sampler.peekTexture())}; } fp = iter.next(); glslFP = glslIter.next(); } SkASSERT(!fp && !glslFP); if (GrTextureProxy* dstTextureProxy = pipeline.dstTextureProxy()) { samplerBindings[currTextureBinding++] = { GrSamplerState::ClampNearest(), static_cast<GrVkTexture*>(dstTextureProxy->peekTexture())}; } // Get new descriptor set SkASSERT(fNumSamplers == currTextureBinding); if (fNumSamplers) { if (fSamplerDescriptorSet) { fSamplerDescriptorSet->recycle(gpu); } fSamplerDescriptorSet = gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle); int samplerDSIdx = GrVkUniformHandler::kSamplerDescSet; fDescriptorSets[samplerDSIdx] = fSamplerDescriptorSet->descriptorSet(); for (int i = 0; i < fNumSamplers; ++i) { const GrSamplerState& state = samplerBindings[i].fState; GrVkTexture* texture = samplerBindings[i].fTexture; const GrVkImageView* textureView = texture->textureView(); const GrVkSampler* sampler = nullptr; if (fImmutableSamplers[i]) { sampler = fImmutableSamplers[i]; } else { sampler = gpu->resourceProvider().findOrCreateCompatibleSampler( state, texture->ycbcrConversionInfo()); } SkASSERT(sampler); VkDescriptorImageInfo imageInfo; memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo)); imageInfo.sampler = sampler->sampler(); imageInfo.imageView = textureView->imageView(); imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkWriteDescriptorSet writeInfo; memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet)); writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeInfo.pNext = nullptr; writeInfo.dstSet = fDescriptorSets[GrVkUniformHandler::kSamplerDescSet]; writeInfo.dstBinding = i; writeInfo.dstArrayElement = 0; writeInfo.descriptorCount = 1; writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; writeInfo.pImageInfo = &imageInfo; writeInfo.pBufferInfo = nullptr; writeInfo.pTexelBufferView = nullptr; GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr)); commandBuffer->addResource(sampler); if (!fImmutableSamplers[i]) { sampler->unref(gpu); } commandBuffer->addResource(samplerBindings[i].fTexture->textureView()); commandBuffer->addResource(samplerBindings[i].fTexture->resource()); } commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, samplerDSIdx, 1, &fDescriptorSets[samplerDSIdx], 0, nullptr); commandBuffer->addRecycledResource(fSamplerDescriptorSet); } }