void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage,const GlExtensions *extensions) { bstring glsl; uint32_t i; Shader* psShader = psContext->psShader; GLLang language = *planguage; const uint32_t ui32InstCount = psShader->ui32InstCount; const uint32_t ui32DeclCount = psShader->ui32DeclCount; psContext->indent = 0; if(language == LANG_DEFAULT) { language = ChooseLanguage(psShader); *planguage = language; } glsl = bfromcstralloc (1024, GetVersionString(language)); psContext->glsl = glsl; psContext->earlyMain = bfromcstralloc (1024, ""); for(i=0; i<NUM_PHASES;++i) { psContext->postShaderCode[i] = bfromcstralloc (1024, ""); } psContext->currentGLSLString = &glsl; psShader->eTargetLanguage = language; psShader->extensions = (const struct GlExtensions*)extensions; psContext->currentPhase = MAIN_PHASE; if(extensions) { if(extensions->ARB_explicit_attrib_location) bcatcstr(glsl,"#extension GL_ARB_explicit_attrib_location : require\n"); if(extensions->ARB_explicit_uniform_location) bcatcstr(glsl,"#extension GL_ARB_explicit_uniform_location : require\n"); if(extensions->ARB_shading_language_420pack) bcatcstr(glsl,"#extension GL_ARB_shading_language_420pack : require\n"); } ClearDependencyData(psShader->eShaderType, psContext->psDependencies); AddVersionDependentCode(psContext); if(psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) { bcatcstr(glsl, "layout(std140) uniform;\n"); } //Special case. Can have multiple phases. if(psShader->eShaderType == HULL_SHADER) { int haveInstancedForkPhase = 0; uint32_t forkIndex = 0; ConsolidateHullTempVars(psShader); for(i=0; i < psShader->ui32HSDeclCount; ++i) { TranslateDeclaration(psContext, psShader->psHSDecl+i); } //control psContext->currentPhase = HS_CTRL_POINT_PHASE; if(psShader->ui32HSControlPointDeclCount) { bcatcstr(glsl, "//Control point phase declarations\n"); for(i=0; i < psShader->ui32HSControlPointDeclCount; ++i) { TranslateDeclaration(psContext, psShader->psHSControlPointPhaseDecl+i); } } if(psShader->ui32HSControlPointInstrCount) { SetDataTypes(psContext, psShader->psHSControlPointPhaseInstr, psShader->ui32HSControlPointInstrCount); bcatcstr(glsl, "void control_point_phase()\n{\n"); psContext->indent++; for(i=0; i < psShader->ui32HSControlPointInstrCount; ++i) { TranslateInstruction(psContext, psShader->psHSControlPointPhaseInstr+i); } psContext->indent--; bcatcstr(glsl, "}\n"); } //fork psContext->currentPhase = HS_FORK_PHASE; for(forkIndex = 0; forkIndex < psShader->ui32ForkPhaseCount; ++forkIndex) { bcatcstr(glsl, "//Fork phase declarations\n"); for(i=0; i < psShader->aui32HSForkDeclCount[forkIndex]; ++i) { TranslateDeclaration(psContext, psShader->apsHSForkPhaseDecl[forkIndex]+i); if(psShader->apsHSForkPhaseDecl[forkIndex][i].eOpcode == OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT) { haveInstancedForkPhase = 1; } } bformata(glsl, "void fork_phase%d()\n{\n", forkIndex); psContext->indent++; SetDataTypes(psContext, psShader->apsHSForkPhaseInstr[forkIndex], psShader->aui32HSForkInstrCount[forkIndex]-1); if(haveInstancedForkPhase) { AddIndentation(psContext); bformata(glsl, "for(int forkInstanceID = 0; forkInstanceID < HullPhase%dInstanceCount; ++forkInstanceID) {\n", forkIndex); psContext->indent++; } //The minus one here is remove the return statement at end of phases. //This is needed otherwise the for loop will only run once. ASSERT(psShader->apsHSForkPhaseInstr[forkIndex][psShader->aui32HSForkInstrCount[forkIndex]-1].eOpcode == OPCODE_RET); for(i=0; i < psShader->aui32HSForkInstrCount[forkIndex]-1; ++i) { TranslateInstruction(psContext, psShader->apsHSForkPhaseInstr[forkIndex]+i); } if(haveInstancedForkPhase) { psContext->indent--; AddIndentation(psContext); bcatcstr(glsl, "}\n"); if(psContext->havePostShaderCode[psContext->currentPhase]) { #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- Post shader code ---\n"); #endif bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- End post shader code ---\n"); #endif } } psContext->indent--; bcatcstr(glsl, "}\n"); } //join psContext->currentPhase = HS_JOIN_PHASE; if(psShader->ui32HSJoinDeclCount) { bcatcstr(glsl, "//Join phase declarations\n"); for(i=0; i < psShader->ui32HSJoinDeclCount; ++i) { TranslateDeclaration(psContext, psShader->psHSJoinPhaseDecl+i); } } if(psShader->ui32HSJoinInstrCount) { SetDataTypes(psContext, psShader->psHSJoinPhaseInstr, psShader->ui32HSJoinInstrCount); bcatcstr(glsl, "void join_phase()\n{\n"); psContext->indent++; for(i=0; i < psShader->ui32HSJoinInstrCount; ++i) { TranslateInstruction(psContext, psShader->psHSJoinPhaseInstr+i); } psContext->indent--; bcatcstr(glsl, "}\n"); } bcatcstr(glsl, "void main()\n{\n"); psContext->indent++; #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- Start Early Main ---\n"); #endif bconcat(glsl, psContext->earlyMain); #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- End Early Main ---\n"); #endif if(psShader->ui32HSControlPointInstrCount) { AddIndentation(psContext); bcatcstr(glsl, "control_point_phase();\n"); if(psShader->ui32ForkPhaseCount || psShader->ui32HSJoinInstrCount) { AddIndentation(psContext); bcatcstr(glsl, "barrier();\n"); } } for(forkIndex = 0; forkIndex < psShader->ui32ForkPhaseCount; ++forkIndex) { AddIndentation(psContext); bformata(glsl, "fork_phase%d();\n", forkIndex); if(psShader->ui32HSJoinInstrCount || (forkIndex+1 < psShader->ui32ForkPhaseCount)) { AddIndentation(psContext); bcatcstr(glsl, "barrier();\n"); } } if(psShader->ui32HSJoinInstrCount) { AddIndentation(psContext); bcatcstr(glsl, "join_phase();\n"); } psContext->indent--; bcatcstr(glsl, "}\n"); if(psContext->psDependencies) { //Save partitioning and primitive type for use by domain shader. psContext->psDependencies->eTessOutPrim = psShader->sInfo.eTessOutPrim; psContext->psDependencies->eTessPartitioning = psShader->sInfo.eTessPartitioning; } return; } if(psShader->eShaderType == DOMAIN_SHADER && psContext->psDependencies) { //Load partitioning and primitive type from hull shader. switch(psContext->psDependencies->eTessOutPrim) { case TESSELLATOR_OUTPUT_TRIANGLE_CW: { bcatcstr(glsl, "layout(cw) in;\n"); break; } case TESSELLATOR_OUTPUT_POINT: { bcatcstr(glsl, "layout(point_mode) in;\n"); break; } default: { break; } } switch(psContext->psDependencies->eTessPartitioning) { case TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: { bcatcstr(glsl, "layout(fractional_odd_spacing) in;\n"); break; } case TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: { bcatcstr(glsl, "layout(fractional_even_spacing) in;\n"); break; } default: { break; } } } for(i=0; i < ui32DeclCount; ++i) { TranslateDeclaration(psContext, psShader->psDecl+i); } bcatcstr(glsl, "void main()\n{\n"); psContext->indent++; #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- Start Early Main ---\n"); #endif bconcat(glsl, psContext->earlyMain); #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- End Early Main ---\n"); #endif MarkIntegerImmediates(psContext); SetDataTypes(psContext, psShader->psInst, ui32InstCount); for(i=0; i < ui32InstCount; ++i) { TranslateInstruction(psContext, psShader->psInst+i); } psContext->indent--; bcatcstr(glsl, "}\n"); }
void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage,const GlExtensions *extensions) { bstring glsl; uint32_t i; Shader* psShader = psContext->psShader; GLLang language = *planguage; uint32_t ui32InstCount = 0; uint32_t ui32DeclCount = 0; psContext->indent = 0; /*psShader->sPhase[MAIN_PHASE].ui32InstanceCount = 1; psShader->sPhase[MAIN_PHASE].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); psShader->sPhase[MAIN_PHASE].ppsInst = hlslcc_malloc(sizeof(Instruction*)); psShader->sPhase[MAIN_PHASE].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); psShader->sPhase[MAIN_PHASE].pui32InstCount = hlslcc_malloc(sizeof(uint32_t));*/ if(language == LANG_DEFAULT) { language = ChooseLanguage(psShader); *planguage = language; } glsl = bfromcstralloc (1024, GetVersionString(language)); psContext->glsl = glsl; psContext->earlyMain = bfromcstralloc (1024, ""); for(i=0; i<NUM_PHASES;++i) { psContext->postShaderCode[i] = bfromcstralloc (1024, ""); } psContext->currentGLSLString = &glsl; psShader->eTargetLanguage = language; psShader->extensions = (const struct GlExtensions*)extensions; psContext->currentPhase = MAIN_PHASE; if(extensions) { if(extensions->ARB_explicit_attrib_location) bcatcstr(glsl,"#extension GL_ARB_explicit_attrib_location : require\n"); if(extensions->ARB_explicit_uniform_location) bcatcstr(glsl,"#extension GL_ARB_explicit_uniform_location : require\n"); if(extensions->ARB_shading_language_420pack) bcatcstr(glsl,"#extension GL_ARB_shading_language_420pack : require\n"); } ClearDependencyData(psShader->eShaderType, psContext->psDependencies); AddVersionDependentCode(psContext); if(psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) { bcatcstr(glsl, "layout(std140) uniform;\n"); } //Special case. Can have multiple phases. if(psShader->eShaderType == HULL_SHADER) { int haveInstancedForkPhase = 0; // Do we have an instanced fork phase? int isCurrentForkPhasedInstanced = 0; // Is the current fork phase instanced? const char* asPhaseFuncNames[NUM_PHASES]; uint32_t ui32PhaseFuncCallOrder[3]; uint32_t ui32PhaseCallIndex; uint32_t ui32Phase; uint32_t ui32Instance; asPhaseFuncNames[MAIN_PHASE] = ""; asPhaseFuncNames[HS_GLOBAL_DECL] = ""; asPhaseFuncNames[HS_FORK_PHASE] = "fork_phase"; asPhaseFuncNames[HS_CTRL_POINT_PHASE] = "control_point_phase"; asPhaseFuncNames[HS_JOIN_PHASE] = "join_phase"; ConsolidateHullTempVars(psShader); for(i=0; i < psShader->asPhase[HS_GLOBAL_DECL].pui32DeclCount[0]; ++i) { TranslateDeclaration(psContext, psShader->asPhase[HS_GLOBAL_DECL].ppsDecl[0]+i); } for(ui32Phase=HS_CTRL_POINT_PHASE; ui32Phase<NUM_PHASES; ui32Phase++) { psContext->currentPhase = ui32Phase; for(ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) { isCurrentForkPhasedInstanced = 0; //reset for each fork phase for cases we don't have a fork phase instance count opcode. bformata(glsl, "//%s declarations\n", asPhaseFuncNames[ui32Phase]); for(i=0; i < psShader->asPhase[ui32Phase].pui32DeclCount[ui32Instance]; ++i) { TranslateDeclaration(psContext, psShader->asPhase[ui32Phase].ppsDecl[ui32Instance]+i); if(psShader->asPhase[ui32Phase].ppsDecl[ui32Instance][i].eOpcode == OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT) { haveInstancedForkPhase = 1; isCurrentForkPhasedInstanced = 1; } } bformata(glsl, "void %s%d()\n{\n", asPhaseFuncNames[ui32Phase], ui32Instance); psContext->indent++; SetDataTypes(psContext, psShader->asPhase[ui32Phase].ppsInst[ui32Instance], psShader->asPhase[ui32Phase].pui32InstCount[ui32Instance]-1); if(isCurrentForkPhasedInstanced) { AddIndentation(psContext); bformata(glsl, "for(int forkInstanceID = 0; forkInstanceID < HullPhase%dInstanceCount; ++forkInstanceID) {\n", ui32Instance); psContext->indent++; } //The minus one here is remove the return statement at end of phases. //This is needed otherwise the for loop will only run once. ASSERT(psShader->asPhase[ui32Phase].ppsInst[ui32Instance] [psShader->asPhase[ui32Phase].pui32InstCount[ui32Instance]-1].eOpcode == OPCODE_RET); for(i=0; i < psShader->asPhase[ui32Phase].pui32InstCount[ui32Instance]-1; ++i) { TranslateInstruction(psContext, psShader->asPhase[ui32Phase].ppsInst[ui32Instance]+i, NULL); } if(haveInstancedForkPhase) { psContext->indent--; AddIndentation(psContext); if(isCurrentForkPhasedInstanced) { bcatcstr(glsl, "}\n"); } if(psContext->havePostShaderCode[psContext->currentPhase]) { #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- Post shader code ---\n"); #endif bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- End post shader code ---\n"); #endif } } psContext->indent--; bcatcstr(glsl, "}\n"); } } bcatcstr(glsl, "void main()\n{\n"); psContext->indent++; #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- Start Early Main ---\n"); #endif bconcat(glsl, psContext->earlyMain); #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- End Early Main ---\n"); #endif ui32PhaseFuncCallOrder[0] = HS_CTRL_POINT_PHASE; ui32PhaseFuncCallOrder[1] = HS_FORK_PHASE; ui32PhaseFuncCallOrder[2] = HS_JOIN_PHASE; for(ui32PhaseCallIndex=0; ui32PhaseCallIndex<3; ui32PhaseCallIndex++) { ui32Phase = ui32PhaseFuncCallOrder[ui32PhaseCallIndex]; for(ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) { AddIndentation(psContext); bformata(glsl, "%s%d();\n", asPhaseFuncNames[ui32Phase], ui32Instance); if(ui32Phase == HS_FORK_PHASE) { if(psShader->asPhase[HS_JOIN_PHASE].ui32InstanceCount || (ui32Instance+1 < psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount)) { AddIndentation(psContext); bcatcstr(glsl, "barrier();\n"); } } } } psContext->indent--; bcatcstr(glsl, "}\n"); if(psContext->psDependencies) { //Save partitioning and primitive type for use by domain shader. psContext->psDependencies->eTessOutPrim = psShader->sInfo.eTessOutPrim; psContext->psDependencies->eTessPartitioning = psShader->sInfo.eTessPartitioning; } return; } if(psShader->eShaderType == DOMAIN_SHADER && psContext->psDependencies) { //Load partitioning and primitive type from hull shader. switch(psContext->psDependencies->eTessOutPrim) { case TESSELLATOR_OUTPUT_TRIANGLE_CW: { bcatcstr(glsl, "layout(cw) in;\n"); break; } case TESSELLATOR_OUTPUT_POINT: { bcatcstr(glsl, "layout(point_mode) in;\n"); break; } default: { break; } } switch(psContext->psDependencies->eTessPartitioning) { case TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: { bcatcstr(glsl, "layout(fractional_odd_spacing) in;\n"); break; } case TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: { bcatcstr(glsl, "layout(fractional_even_spacing) in;\n"); break; } default: { break; } } } ui32InstCount = psShader->asPhase[MAIN_PHASE].pui32InstCount[0]; ui32DeclCount = psShader->asPhase[MAIN_PHASE].pui32DeclCount[0]; for(i=0; i < ui32DeclCount; ++i) { TranslateDeclaration(psContext, psShader->asPhase[MAIN_PHASE].ppsDecl[0]+i); } if(psContext->psShader->ui32NumDx9ImmConst) { bformata(psContext->glsl, "vec4 ImmConstArray [%d];\n", psContext->psShader->ui32NumDx9ImmConst); } bcatcstr(glsl, "void main()\n{\n"); psContext->indent++; #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- Start Early Main ---\n"); #endif bconcat(glsl, psContext->earlyMain); #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//--- End Early Main ---\n"); #endif MarkIntegerImmediates(psContext); SetDataTypes(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0], ui32InstCount); for(i=0; i < ui32InstCount; ++i) { TranslateInstruction(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0]+i, i+1 < ui32InstCount ? psShader->asPhase[MAIN_PHASE].ppsInst[0]+i+1 : 0); } psContext->indent--; bcatcstr(glsl, "}\n"); }