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"); } }
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); }