示例#1
0
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))
	));
}
示例#2
0
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);
    }
}