Beispiel #1
0
void Hlsl11GeneratorInstance::PrintNodeInit(size_t nodeIndex)
{
	Node* node = nodeInits[nodeIndex];

	switch(node->GetType())
	{
	case Node::typeFloatConst:
		PrintNodeInitBegin(nodeIndex);
		text << std::fixed << std::setprecision(10) << fast_cast<FloatConstNode*>(node)->GetValue() << 'f';
		PrintNodeInitEnd();
		break;
	case Node::typeIntConst:
		PrintNodeInitBegin(nodeIndex);
		text << fast_cast<IntConstNode*>(node)->GetValue();
		PrintNodeInitEnd();
		break;
	case Node::typeAttribute:
		PrintNodeInitBegin(nodeIndex);
		text << "a.a" << fast_cast<AttributeNode*>(node)->GetElementIndex();
		PrintNodeInitEnd();
		break;
	case Node::typeUniform:
		// uniform doesn't have initialization
		break;
	case Node::typeSampler:
		// sampler doesn't have initialization
		break;
	case Node::typeReadUniform:
		{
			PrintNodeInitBegin(nodeIndex);
			ReadUniformNode* readUniformNode = fast_cast<ReadUniformNode*>(node);
			PrintUniform(readUniformNode->GetUniformNode());
			PrintNodeInitEnd();
		}
		break;
	case Node::typeIndexUniformArray:
		{
			PrintNodeInitBegin(nodeIndex);
			IndexUniformArrayNode* indexUniformArrayNode = fast_cast<IndexUniformArrayNode*>(node);
			PrintUniform(indexUniformArrayNode->GetUniformNode());
			text << '[';
			PrintNode(indexUniformArrayNode->GetIndexNode());
			text << ']';
			PrintNodeInitEnd();
		}
		break;
	case Node::typeTransformed:
		PrintNodeInitBegin(nodeIndex);
		text << "v.v" << fast_cast<TransformedNode*>(node)->GetSemantic();
		PrintNodeInitEnd();
		break;
	case Node::typeInterpolate:
		{
			InterpolateNode* interpolateNode = fast_cast<InterpolateNode*>(node);
			text << "\tv.v" << interpolateNode->GetSemantic() << " = ";
			PrintNode(interpolateNode->GetNode());
			PrintNodeInitEnd();
		}
		break;
	case Node::typeSequence:
		// sequence node doesn't have initialization
		break;
	case Node::typeSwizzle:
		{
			PrintNodeInitBegin(nodeIndex);
			SwizzleNode* swizzleNode = fast_cast<SwizzleNode*>(node);
			PrintNode(swizzleNode->GetA());
			text << '.' << swizzleNode->GetMap();
			PrintNodeInitEnd();
		}
		break;
	case Node::typeOperation:
		PrintNodeInitBegin(nodeIndex);
		PrintOperationNodeInit(fast_cast<OperationNode*>(node));
		PrintNodeInitEnd();
		break;
	case Node::typeAction:
		PrintActionNodeInit(fast_cast<ActionNode*>(node));
		break;
	case Node::typeSample:
		{
			PrintNodeInitBegin(nodeIndex);

			SampleNode* sampleNode = fast_cast<SampleNode*>(node);

			int slot = sampleNode->GetSamplerNode()->GetSlot();
			text << 't' << slot;

			ValueNode* coordsNode = sampleNode->GetCoordsNode();
			ValueNode* offsetNode = sampleNode->GetOffsetNode();
			ValueNode* lodNode = sampleNode->GetLodNode();
			ValueNode* biasNode = sampleNode->GetBiasNode();
			ValueNode* gradXNode = sampleNode->GetGradXNode();
			ValueNode* gradYNode = sampleNode->GetGradYNode();

			if(lodNode)
			{
				text << ".SampleLevel(s" << slot << ", ";
				PrintNode(coordsNode);
				text << ", ";
				PrintNode(lodNode);
			}
			else if(biasNode)
			{
				text << ".SampleBias(s" << slot << ", ";
				PrintNode(coordsNode);
				text << ", ";
				PrintNode(biasNode);
			}
			else if(gradXNode && gradYNode)
			{
				text << ".SampleGrad(s" << slot << ", ";
				PrintNode(coordsNode);
				text << ", ";
				PrintNode(gradXNode);
				text << ", ";
				PrintNode(gradYNode);
			}
			else
			{
				text << ".Sample(s" << slot << ", ";
				PrintNode(coordsNode);
			}

			// add offset if needed
			if(offsetNode)
			{
				text << ", ";
				PrintNode(offsetNode);
			}

			text << ')';

			PrintNodeInitEnd();
		}
		break;
	case Node::typeFragment:
		{
			FragmentNode* fragmentNode = fast_cast<FragmentNode*>(node);
			text << "\tr.r" << fragmentNode->GetTarget() << " = ";
			PrintNode(fragmentNode->GetNode());
			PrintNodeInitEnd();
		}
		break;
	case Node::typeCast:
		{
			PrintNodeInitBegin(nodeIndex);
			CastNode* castNode = fast_cast<CastNode*>(node);
			text << '(';
			PrintDataType(castNode->GetValueType());
			text << ")";
			PrintNode(castNode->GetA());
			PrintNodeInitEnd();
		}
		break;
	default:
		THROW("Unknown node type");
	}
}
void GlslGeneratorInstance::PrintNodeInit(size_t nodeIndex)
{
	Node* node = nodeInits[nodeIndex];

	switch(node->GetType())
	{
	case Node::typeFloatConst:
		PrintNodeInitBegin(nodeIndex);
		text << std::fixed << std::setprecision(10) << fast_cast<FloatConstNode*>(node)->GetValue();// << 'f';
		PrintNodeInitEnd();
		break;
	case Node::typeIntConst:
		PrintNodeInitBegin(nodeIndex);
		text << fast_cast<IntConstNode*>(node)->GetValue();
		PrintNodeInitEnd();
		break;
	case Node::typeAttribute:
		{
			AttributeNode* attributeNode = fast_cast<AttributeNode*>(node);
			PrintNodeInitBegin(nodeIndex);
			// WebGL hack for integer attributes
			// (only for case of using another hack - changing integer attributes to float)
			bool intConversion = false;
			if(glslVersion == GlslVersions::webgl)
				intConversion = PrintWebGLConversionToIntegerBegin(attributeNode->GetValueType());

			text << "a" << attributeNode->GetElementIndex();

			if(intConversion)
				PrintWebGLConversionToIntegerEnd();
			PrintNodeInitEnd();
		}
		break;
	case Node::typeUniform:
		// uniform doesn't have initialization
		break;
	case Node::typeSampler:
		// sampler doesn't have initialization
		break;
	case Node::typeReadUniform:
		{
			PrintNodeInitBegin(nodeIndex);
			ReadUniformNode* readUniformNode = fast_cast<ReadUniformNode*>(node);
			PrintUniform(readUniformNode->GetUniformNode());
			PrintNodeInitEnd();
		}
		break;
	case Node::typeIndexUniformArray:
		{
			PrintNodeInitBegin(nodeIndex);
			IndexUniformArrayNode* indexUniformArrayNode = fast_cast<IndexUniformArrayNode*>(node);
			PrintUniform(indexUniformArrayNode->GetUniformNode());
			text << '[';
			PrintNode(indexUniformArrayNode->GetIndexNode());
			text << ']';
			PrintNodeInitEnd();
		}
		break;
	case Node::typeTransformed:
		PrintNodeInitBegin(nodeIndex);
		text << "v" << fast_cast<TransformedNode*>(node)->GetSemantic();
		PrintNodeInitEnd();
		break;
	case Node::typeInterpolate:
		{
			InterpolateNode* interpolateNode = fast_cast<InterpolateNode*>(node);
			text << "\tv" << interpolateNode->GetSemantic() << " = ";
			PrintNode(interpolateNode->GetNode());
			PrintNodeInitEnd();
		}
		break;
	case Node::typeSequence:
		// sequence node doesn't have initialization
		break;
	case Node::typeSwizzle:
		{
			PrintNodeInitBegin(nodeIndex);
			SwizzleNode* swizzleNode = fast_cast<SwizzleNode*>(node);
			PrintNode(swizzleNode->GetA());
			text << '.' << swizzleNode->GetMap();
			PrintNodeInitEnd();
		}
		break;
	case Node::typeOperation:
		PrintNodeInitBegin(nodeIndex);
		PrintOperationNodeInit(fast_cast<OperationNode*>(node));
		PrintNodeInitEnd();
		break;
	case Node::typeAction:
		PrintActionNodeInit(fast_cast<ActionNode*>(node));
		break;
	case Node::typeSample:
		{
			PrintNodeInitBegin(nodeIndex);

			SampleNode* sampleNode = fast_cast<SampleNode*>(node);

			int slot = sampleNode->GetSamplerNode()->GetSlot();

			ValueNode* coordsNode = sampleNode->GetCoordsNode();
			ValueNode* offsetNode = sampleNode->GetOffsetNode();
			ValueNode* lodNode = sampleNode->GetLodNode();
			ValueNode* biasNode = sampleNode->GetBiasNode();
			ValueNode* gradXNode = sampleNode->GetGradXNode();
			ValueNode* gradYNode = sampleNode->GetGradYNode();

			auto printOffsetNode = [&]()
			{
				// offset node is required to be constant expression,
				// but AMD driver requires it also to be compile-time expression
				// so HACK: print value inline, only for known node
				// PrintNode(offsetNode);
				if(offsetNode->GetType() != Node::typeOperation)
					THROW("wrong offset node");
				OperationNode* offsetOperationNode = fast_cast<OperationNode*>(offsetNode);
				if(
					offsetOperationNode->GetOperation() != OperationNode::operationInt11to2 ||
					offsetOperationNode->GetA()->GetType() != Node::typeIntConst ||
					offsetOperationNode->GetB()->GetType() != Node::typeIntConst
					)
					THROW("wrong offset node");
				text << "ivec2("
					<< offsetOperationNode->GetA().FastCast<IntConstNode>()->GetValue() << ", "
					<< offsetOperationNode->GetB().FastCast<IntConstNode>()->GetValue() << ")";
			};

			if(lodNode)
			{
				text << "textureLod";
				if(offsetNode)
					text << "Offset";
				text << '(' << samplerPrefix << slot << ", ";
				PrintNode(coordsNode);
				text << ", ";
				PrintNode(lodNode);
				if(offsetNode)
				{
					text << ", ";
					printOffsetNode();
				}
			}
			else if(biasNode)
			{
				text << "texture";
				if(offsetNode)
					text << "Offset";
				text << '(' << samplerPrefix << slot << ", ";
				PrintNode(coordsNode);
				if(offsetNode)
				{
					text << ", ";
					printOffsetNode();
				}
				text << ", ";
				PrintNode(biasNode);
			}
			else if(gradXNode && gradYNode)
			{
				text << "textureGrad";
				if(offsetNode)
					text << "Offset";
				text << '(' << samplerPrefix << slot << ", ";
				PrintNode(coordsNode);
				text << ", ";
				PrintNode(gradXNode);
				text << ", ";
				PrintNode(gradYNode);
				if(offsetNode)
				{
					text << ", ";
					printOffsetNode();
				}
			}
			else
			{
				text << (glslVersion == GlslVersions::webgl ? "texture2D" : "texture");
				if(offsetNode && glslVersion != GlslVersions::webgl)
					text << "Offset";
				text << '(' << samplerPrefix << slot << ", ";
				PrintNode(coordsNode);
				if(offsetNode && glslVersion != GlslVersions::webgl)
				{
					text << ", ";
					printOffsetNode();
				}
			}

			// close sample call
			text << ')';

			// sample always returns four-component vector, so make some swizzle if needed
			int valueSize = GetVectorDataTypeDimensions(sampleNode->GetValueType());
			if(valueSize < 4)
			{
				text << '.';
				for(int i = 0; i < valueSize; ++i)
					text << "xyzw"[i];
			}

			PrintNodeInitEnd();
		}
		break;
	case Node::typeFragment:
		{
			FragmentNode* fragmentNode = fast_cast<FragmentNode*>(node);
			switch(glslVersion)
			{
			case GlslVersions::opengl33: text << "\tr" << fragmentNode->GetTarget(); break;
			case GlslVersions::webgl:
				if(fragmentTargetsCount > 1)
					text << "gl_FragData[" << fragmentNode->GetTarget() << ']';
				else
					text << "gl_FragColor";
				break;
			}
			text << " = ";
			PrintNode(fragmentNode->GetNode());
			PrintNodeInitEnd();
		}
		break;
	case Node::typeDualFragment:
		{
			DualFragmentNode* dualFragmentNode = fast_cast<DualFragmentNode*>(node);
			switch(glslVersion)
			{
			case GlslVersions::opengl33:
				text << "\tr0 = ";
				PrintNode(dualFragmentNode->GetNode0());
				PrintNodeInitEnd();
				text << "\tr1 = ";
				PrintNode(dualFragmentNode->GetNode1());
				PrintNodeInitEnd();
				break;
			case GlslVersions::webgl:
				text << "\tgl_FragData[0] = ";
				PrintNode(dualFragmentNode->GetNode0());
				PrintNodeInitEnd();
				text << "\tgl_FragData[1] = ";
				PrintNode(dualFragmentNode->GetNode1());
				PrintNodeInitEnd();
				break;
			}
		}
		break;
	case Node::typeCast:
		{
			PrintNodeInitBegin(nodeIndex);
			CastNode* castNode = fast_cast<CastNode*>(node);
			PrintDataType(castNode->GetValueType());
			text << '(';
			PrintNode(castNode->GetA());
			text << ')';
			PrintNodeInitEnd();
		}
		break;
	default:
		THROW("Unknown node type");
	}
}
Beispiel #3
0
void SlGeneratorInstance::RegisterNode(Node* node)
{
	// if registration of node already began
	if(registeredNodes.find(node) != registeredNodes.end())
	{
		// if node is not registered yet
		if(nodeInitIndices.find(node) == nodeInitIndices.end())
			// than it's a loop
			THROW("Node cyclic dependency");
		// else it's ok, it's just another use of node
		return;
	}
	// register node
	registeredNodes.insert(node);

	switch(node->GetType())
	{
	case Node::typeFloatConst:
	case Node::typeIntConst:
		break;
	case Node::typeAttribute:
		{
			if(shaderType != ShaderTypes::vertex)
				THROW("Only vertex shader can have attribute nodes");

			attributes.push_back(fast_cast<AttributeNode*>(node));
		}
		break;
	case Node::typeUniform:
		{
			UniformNode* uniformNode = fast_cast<UniformNode*>(node);
			uniforms.push_back(std::make_pair(uniformNode->GetGroup(), uniformNode));
		}
		break;
	case Node::typeSampler:
		samplers.push_back(fast_cast<SamplerNode*>(node));
		break;
	case Node::typeReadUniform:
		RegisterNode(fast_cast<ReadUniformNode*>(node)->GetUniformNode());
		break;
	case Node::typeIndexUniformArray:
		{
			IndexUniformArrayNode* indexUniformArrayNode = fast_cast<IndexUniformArrayNode*>(node);
			RegisterNode(indexUniformArrayNode->GetUniformNode());
			RegisterNode(indexUniformArrayNode->GetIndexNode());
		}
		break;
	case Node::typeTransformed:
		transformedNodes.push_back(fast_cast<TransformedNode*>(node));
		break;
	case Node::typeInterpolate:
		{
			InterpolateNode* interpolateNode = fast_cast<InterpolateNode*>(node);
			interpolateNodes.push_back(interpolateNode);
			RegisterNode(interpolateNode->GetNode());
		}
		break;
	case Node::typeSequence:
		{
			SequenceNode* sequenceNode = fast_cast<SequenceNode*>(node);
			RegisterNode(sequenceNode->GetA());
			RegisterNode(sequenceNode->GetB());
		}
		break;
	case Node::typeSwizzle:
		RegisterNode(fast_cast<SwizzleNode*>(node)->GetA());
		break;
	case Node::typeOperation:
		{
			OperationNode* operationNode = fast_cast<OperationNode*>(node);
			int argumentsCount = operationNode->GetArgumentsCount();
			for(int i = 0; i < argumentsCount; ++i)
				RegisterNode(operationNode->GetArgument(i));
		}
		break;
	case Node::typeAction:
		{
			ActionNode* actionNode = fast_cast<ActionNode*>(node);
			int argumentsCount = actionNode->GetArgumentsCount();
			for(int i = 0; i < argumentsCount; ++i)
				RegisterNode(actionNode->GetArgument(i));
		}
		break;
	case Node::typeSample:
		{
			SampleNode* sampleNode = fast_cast<SampleNode*>(node);

			RegisterNode(sampleNode->GetSamplerNode());
			RegisterNode(sampleNode->GetCoordsNode());

			ValueNode* lodNode = sampleNode->GetLodNode();
			if(lodNode)
				RegisterNode(lodNode);

			ValueNode* biasNode = sampleNode->GetBiasNode();
			if(biasNode)
				RegisterNode(biasNode);

			ValueNode* gradXNode = sampleNode->GetGradXNode();
			if(gradXNode)
				RegisterNode(gradXNode);
			ValueNode* gradYNode = sampleNode->GetGradYNode();
			if(gradYNode)
				RegisterNode(gradYNode);

			ValueNode* offsetNode = sampleNode->GetOffsetNode();
			if(offsetNode)
				RegisterNode(offsetNode);
		}
		break;
	case Node::typeFragment:
		{
			if(shaderType != ShaderTypes::pixel)
				THROW("Only pixel shader can do fragment output");
			FragmentNode* fragmentNode = fast_cast<FragmentNode*>(node);

			// register maximum number of fragment outputs
			fragmentTargetsCount = std::max(fragmentTargetsCount, fragmentNode->GetTarget() + 1);
			RegisterNode(fragmentNode->GetNode());
		}
		break;
	case Node::typeDualFragment:
		{
			if(shaderType != ShaderTypes::pixel)
				THROW("Only pixel shader can do dual fragment output");
			DualFragmentNode* dualFragmentNode = fast_cast<DualFragmentNode*>(node);

			dualFragmentTarget = true;

			// register maximum number of fragment outputs
			fragmentTargetsCount = std::max(fragmentTargetsCount, 2);
			RegisterNode(dualFragmentNode->GetNode0());
			RegisterNode(dualFragmentNode->GetNode1());
		}
		break;
	case Node::typeCast:
		RegisterNode(fast_cast<CastNode*>(node)->GetA());
		break;
	default:
		THROW("Unknown node type");
	}

	// add initialization of node
	THROW_ASSERT(nodeInitIndices.find(node) == nodeInitIndices.end());
	nodeInitIndices[node] = (int)nodeInits.size();
	nodeInits.push_back(node);
}