static void TranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle) { int integerConstructor = 0; bstring glsl = *psContext->currentGLSLString; *pui32IgnoreSwizzle = 0; if(psOperand->eType != OPERAND_TYPE_IMMEDIATE32 && psOperand->eType != OPERAND_TYPE_IMMEDIATE64 && psOperand->eType != OPERAND_TYPE_CONSTANT_BUFFER) { const uint32_t swizCount = psOperand->iNumComponents; SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand); if( (ui32TOFlag & (TO_FLAG_INTEGER|TO_FLAG_UNSIGNED_INTEGER)) == (TO_FLAG_INTEGER|TO_FLAG_UNSIGNED_INTEGER)) { //Can be either int or uint if(eType != SVT_INT && eType != SVT_UINT) { if(swizCount == 1) bformata(glsl, "int("); else bformata(glsl, "ivec%d(", swizCount); integerConstructor = 1; } } else { if((ui32TOFlag & (TO_FLAG_INTEGER|TO_FLAG_DESTINATION))==TO_FLAG_INTEGER && eType != SVT_INT) { //Convert to int if(swizCount == 1) bformata(glsl, "int("); else bformata(glsl, "ivec%d(", swizCount); integerConstructor = 1; } if((ui32TOFlag & (TO_FLAG_UNSIGNED_INTEGER|TO_FLAG_DESTINATION))==TO_FLAG_UNSIGNED_INTEGER && eType != SVT_UINT) { //Convert to uint if(swizCount == 1) bformata(glsl, "uint("); else bformata(glsl, "uvec%d(", swizCount); integerConstructor = 1; } } } switch(psOperand->eType) { case OPERAND_TYPE_IMMEDIATE32: { if(psOperand->iNumComponents == 1) { if(ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) { bformata(glsl, "%uu", *((unsigned int*)(&psOperand->afImmediates[0]))); } else if((ui32TOFlag & TO_FLAG_INTEGER) || psOperand->iIntegerImmediate || fpcheck(psOperand->afImmediates[0])) { bformata(glsl, "%d", *((int*)(&psOperand->afImmediates[0]))); } else { bformata(glsl, "%f", psOperand->afImmediates[0]); } } else { if(ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) { bformata(glsl, "uvec4(%uu, %uu, %uu, %uu)", *(unsigned int*)&psOperand->afImmediates[0], *(unsigned int*)&psOperand->afImmediates[1], *(unsigned int*)&psOperand->afImmediates[2], *(unsigned int*)&psOperand->afImmediates[3]); } else if((ui32TOFlag & TO_FLAG_INTEGER) || psOperand->iIntegerImmediate || fpcheck(psOperand->afImmediates[0]) || fpcheck(psOperand->afImmediates[1]) || fpcheck(psOperand->afImmediates[2]) || fpcheck(psOperand->afImmediates[3])) { bformata(glsl, "ivec4(%d, %d, %d, %d)", *(int*)&psOperand->afImmediates[0], *(int*)&psOperand->afImmediates[1], *(int*)&psOperand->afImmediates[2], *(int*)&psOperand->afImmediates[3]); } else { bformata(glsl, "vec4(%f, %f, %f, %f)", psOperand->afImmediates[0], psOperand->afImmediates[1], psOperand->afImmediates[2], psOperand->afImmediates[3]); } if(psOperand->iNumComponents != 4) { AddSwizzleUsingElementCount(psContext, psOperand->iNumComponents); } } break; } case OPERAND_TYPE_IMMEDIATE64: { if(psOperand->iNumComponents == 1) { bformata(glsl, "%f", psOperand->adImmediates[0]); } else { bformata(glsl, "dvec4(%f, %f, %f, %f)", psOperand->adImmediates[0], psOperand->adImmediates[1], psOperand->adImmediates[2], psOperand->adImmediates[3]); if(psOperand->iNumComponents != 4) { AddSwizzleUsingElementCount(psContext, psOperand->iNumComponents); } } break; } case OPERAND_TYPE_INPUT: { switch(psOperand->iIndexDims) { case INDEX_2D: { if(psOperand->aui32ArraySizes[1] == 0)//Input index zero - position. { bcatcstr(glsl, "gl_in"); TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE);//Vertex index bcatcstr(glsl, ".gl_Position"); } else { const char* name = "Input"; if(ui32TOFlag & TO_FLAG_DECLARATION_NAME) { name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); } bformata(glsl, "%s%d", name, psOperand->aui32ArraySizes[1]); TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE);//Vertex index } break; } default: { if(psOperand->eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE) { bformata(glsl, "Input%d[int(", psOperand->ui32RegisterNumber); TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE); bcatcstr(glsl, ")]"); } else { if(psContext->psShader->aIndexedInput[psOperand->ui32RegisterNumber] != 0) { const uint32_t parentIndex = psContext->psShader->aIndexedInputParents[psOperand->ui32RegisterNumber]; bformata(glsl, "Input%d[%d]", parentIndex, psOperand->ui32RegisterNumber - parentIndex); } else { if(ui32TOFlag & TO_FLAG_DECLARATION_NAME) { const char* name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); bcatcstr(glsl, name); } else { bformata(glsl, "Input%d", psOperand->ui32RegisterNumber); } } } break; } } break; } case OPERAND_TYPE_OUTPUT: { bformata(glsl, "Output%d", psOperand->ui32RegisterNumber); if(psOperand->psSubOperand[0]) { bcatcstr(glsl, "[int("); //Indexes must be integral. TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE); bcatcstr(glsl, ")]"); } break; } case OPERAND_TYPE_OUTPUT_DEPTH: case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: { bcatcstr(glsl, "gl_FragDepth"); break; } case OPERAND_TYPE_TEMP: { SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand); bcatcstr(glsl, "Temp"); if(eType == SVT_INT) { bcatcstr(glsl, "_int"); } else if(eType == SVT_UINT) { bcatcstr(glsl, "_uint"); } else if(eType == SVT_DOUBLE) { bcatcstr(glsl, "_double"); } else if(eType == SVT_VOID || (ui32TOFlag & TO_FLAG_DESTINATION)) { if(ui32TOFlag & TO_FLAG_INTEGER) { bcatcstr(glsl, "_int"); } else if(ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) { bcatcstr(glsl, "_uint"); } } bformata(glsl, "[%d]", psOperand->ui32RegisterNumber); break; } case OPERAND_TYPE_SPECIAL_IMMCONSTINT: { bformata(glsl, "IntImmConst%d", psOperand->ui32RegisterNumber); break; } case OPERAND_TYPE_SPECIAL_IMMCONST: { bformata(glsl, "ImmConst%d", psOperand->ui32RegisterNumber); break; } case OPERAND_TYPE_SPECIAL_OUTBASECOLOUR: { bcatcstr(glsl, "BaseColour"); break; } case OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR: { bcatcstr(glsl, "OffsetColour"); break; } case OPERAND_TYPE_SPECIAL_POSITION: { bcatcstr(glsl, "gl_Position"); break; } case OPERAND_TYPE_SPECIAL_FOG: { bcatcstr(glsl, "Fog"); break; } case OPERAND_TYPE_SPECIAL_POINTSIZE: { bcatcstr(glsl, "gl_PointSize"); break; } case OPERAND_TYPE_SPECIAL_ADDRESS: { bcatcstr(glsl, "Address"); break; } case OPERAND_TYPE_SPECIAL_TEXCOORD: { bformata(glsl, "TexCoord%d", psOperand->ui32RegisterNumber); break; } case OPERAND_TYPE_CONSTANT_BUFFER: { const char* StageName = "VS"; ConstantBuffer* psCBuf = NULL; ShaderVarType* psVarType = NULL; int32_t index = -1; GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); switch(psContext->psShader->eShaderType) { case PIXEL_SHADER: { StageName = "PS"; break; } case HULL_SHADER: { StageName = "HS"; break; } case DOMAIN_SHADER: { StageName = "DS"; break; } case GEOMETRY_SHADER: { StageName = "GS"; break; } case COMPUTE_SHADER: { StageName = "CS"; break; } default: { break; } } if(ui32TOFlag & TO_FLAG_DECLARATION_NAME) { pui32IgnoreSwizzle[0] = 1; } if((psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT)!=HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) { if(psCBuf) { //$Globals. if(psCBuf->Name[0] == '$') { bformata(glsl, "Globals%s", StageName); } else { bformata(glsl, "%s%s", psCBuf->Name, StageName); } if((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) { bcatcstr(glsl, "."); } } else { //bformata(glsl, "cb%d", psOperand->aui32ArraySizes[0]); } } if((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) { //Work out the variable name. Don't apply swizzle to that variable yet. int32_t rebase = 0; if(psCBuf) { GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); bformata(glsl, "%s", psVarType->FullName); } else // We don't have a semantic for this variable, so try the raw dump appoach. { bformata(glsl, "cb%d.data", psOperand->aui32ArraySizes[0]);// index = psOperand->aui32ArraySizes[1]; } //Dx9 only? if(psOperand->psSubOperand[0] != NULL) { SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[0]); if(eType != SVT_INT && eType != SVT_UINT) { bcatcstr(glsl, "[int("); //Indexes must be integral. TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE); bcatcstr(glsl, ")]"); } else { bcatcstr(glsl, "["); //Indexes must be integral. TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE); bcatcstr(glsl, "]"); } ASSERT(index == 0 || index == -1); } else if(index != -1 && psOperand->psSubOperand[1] != NULL) { //Array of matrices is treated as array of vec4s if(index != -1) { SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[1]); if(eType != SVT_INT && eType != SVT_UINT) { bcatcstr(glsl, "[int("); TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_NONE); bformata(glsl, ") + %d]", index); } else { bcatcstr(glsl, "["); TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_NONE); bformata(glsl, " + %d]", index); } } } else if(index != -1) { bformata(glsl, "[%d]", index); } else if(psOperand->psSubOperand[1] != NULL) { SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[1]); if(eType != SVT_INT && eType != SVT_UINT) { bcatcstr(glsl, "["); TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_NONE); bcatcstr(glsl, "]"); } else { bcatcstr(glsl, "[int("); TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_NONE); bcatcstr(glsl, ")]"); } } if(psVarType && psVarType->Class == SVC_VECTOR) { switch(rebase) { case 4: { if(psVarType->Columns == 2) { //.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) bcatcstr(glsl, ".xxyx"); } else if(psVarType->Columns == 3) { //.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) .z(GLSL) is .w(HLSL) bcatcstr(glsl, ".xxyz"); } break; } case 8: { if(psVarType->Columns == 2) { //.x(GLSL) is .z(HLSL). .y(GLSL) is .w(HLSL) bcatcstr(glsl, ".xxxy"); } break; } case 0: default: { //No rebase, but extend to vec4. if(psVarType->Columns == 2) { bcatcstr(glsl, ".xyxx"); } else if(psVarType->Columns == 3) { bcatcstr(glsl, ".xyzx"); } break; } } } if(psVarType && psVarType->Class == SVC_SCALAR) { *pui32IgnoreSwizzle = 1; } } break; } case OPERAND_TYPE_RESOURCE: { TextureName(psContext, psOperand->ui32RegisterNumber, 0); *pui32IgnoreSwizzle = 1; break; } case OPERAND_TYPE_SAMPLER: { bformata(glsl, "Sampler%d", psOperand->ui32RegisterNumber); *pui32IgnoreSwizzle = 1; break; } case OPERAND_TYPE_FUNCTION_BODY: { const uint32_t ui32FuncBody = psOperand->ui32RegisterNumber; const uint32_t ui32FuncTable = psContext->psShader->aui32FuncBodyToFuncTable[ui32FuncBody]; //const uint32_t ui32FuncPointer = psContext->psShader->aui32FuncTableToFuncPointer[ui32FuncTable]; const uint32_t ui32ClassType = psContext->psShader->sInfo.aui32TableIDToTypeID[ui32FuncTable]; const char* ClassTypeName = &psContext->psShader->sInfo.psClassTypes[ui32ClassType].Name[0]; const uint32_t ui32UniqueClassFuncIndex = psContext->psShader->ui32NextClassFuncName[ui32ClassType]++; bformata(glsl, "%s_Func%d", ClassTypeName, ui32UniqueClassFuncIndex); break; } case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID: { bcatcstr(glsl, "forkInstanceID"); *pui32IgnoreSwizzle = 1; return; } case OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: { bcatcstr(glsl, "immediateConstBufferF"); if(psOperand->psSubOperand[0]) { bcatcstr(glsl, "(int("); //Indexes must be integral. TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE); bcatcstr(glsl, "))"); } break; } case OPERAND_TYPE_INPUT_DOMAIN_POINT: { bcatcstr(glsl, "gl_TessCoord"); break; } case OPERAND_TYPE_INPUT_CONTROL_POINT: { if(psOperand->aui32ArraySizes[1] == 0)//Input index zero - position. { bformata(glsl, "gl_in[%d].gl_Position", psOperand->aui32ArraySizes[0]); } else { bformata(glsl, "Input%d[%d]", psOperand->aui32ArraySizes[1], psOperand->aui32ArraySizes[0]); } break; } case OPERAND_TYPE_NULL: { // Null register, used to discard results of operations bcatcstr(glsl, "//null"); break; } case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: { bcatcstr(glsl, "gl_InvocationID"); *pui32IgnoreSwizzle = 1; break; } case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: { bcatcstr(glsl, "gl_SampleMask[0]"); *pui32IgnoreSwizzle = 1; break; } case OPERAND_TYPE_INPUT_COVERAGE_MASK: { bcatcstr(glsl, "gl_SampleMaskIn[0]"); //Skip swizzle on scalar types. *pui32IgnoreSwizzle = 1; break; } case OPERAND_TYPE_INPUT_THREAD_ID://SV_DispatchThreadID { bcatcstr(glsl, "gl_GlobalInvocationID"); break; } case OPERAND_TYPE_INPUT_THREAD_GROUP_ID://SV_GroupThreadID { bcatcstr(glsl, "gl_LocalInvocationID"); break; } case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP://SV_GroupID { bcatcstr(glsl, "gl_WorkGroupID"); break; } case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED://SV_GroupIndex { bcatcstr(glsl, "gl_LocalInvocationIndex"); break; } case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: { bformata(glsl, "UAV%d", psOperand->ui32RegisterNumber); break; } case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: { bformata(glsl, "TGSM%d", psOperand->ui32RegisterNumber); break; } case OPERAND_TYPE_INPUT_PRIMITIVEID: { bcatcstr(glsl, "gl_PrimitiveID"); break; } case OPERAND_TYPE_INDEXABLE_TEMP: { bformata(glsl, "TempArray%d", psOperand->aui32ArraySizes[0]); bformata(glsl, "[%d", psOperand->aui32ArraySizes[1]); if(psOperand->psSubOperand[1]) { bcatcstr(glsl, "+"); TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_NONE); } bcatcstr(glsl, "]"); break; } case OPERAND_TYPE_STREAM: { bformata(glsl, "%d", psOperand->ui32RegisterNumber); break; } case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: { bcatcstr(glsl, "gl_InvocationID"); break; } case OPERAND_TYPE_THIS_POINTER: { /* The "this" register is a register that provides up to 4 pieces of information: X: Which CB holds the instance data Y: Base element offset of the instance data within the instance CB Z: Base sampler index W: Base Texture index Can be different for each function call */ break; } default: { ASSERT(0); break; } } if(integerConstructor) { bcatcstr(glsl, ")"); } }
SHADER_VARIABLE_TYPE GetOperandDataType(HLSLCrossCompilerContext* psContext, const Operand* psOperand) { switch(psOperand->eType) { case OPERAND_TYPE_TEMP: { SHADER_VARIABLE_TYPE eCurrentType; int i = 0; if(psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) { return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; } if(psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) { if(psOperand->ui32Swizzle == (NO_SWIZZLE)) { return psOperand->aeDataType[0]; } return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; } if(psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) { uint32_t ui32CompMask = psOperand->ui32CompMask; if(!psOperand->ui32CompMask) { ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; } for(;i<4;++i) { if(ui32CompMask & (1<<i)) { eCurrentType = psOperand->aeDataType[i]; break; } } #ifdef _DEBUG //Check if all elements have the same basic type. for(;i<4;++i) { if(psOperand->ui32CompMask & (1<<i)) { if(eCurrentType != psOperand->aeDataType[i]) { ASSERT(0); } } } #endif return eCurrentType; } ASSERT(0); break; } case OPERAND_TYPE_OUTPUT: { const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims-1]; InOutSignature* psOut; if(GetOutputSignatureFromRegister(ui32Register, psOperand->ui32CompMask, 0, &psContext->psShader->sInfo, &psOut)) { if( psOut->eComponentType == INOUT_COMPONENT_UINT32) { return SVT_UINT; } else if( psOut->eComponentType == INOUT_COMPONENT_SINT32) { return SVT_INT; } } break; } case OPERAND_TYPE_INPUT: { const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims-1]; InOutSignature* psIn; //UINT in DX, INT in GL. if(psOperand->eSpecialName == NAME_PRIMITIVE_ID) { return SVT_INT; } if(GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn)) { if( psIn->eComponentType == INOUT_COMPONENT_UINT32) { return SVT_UINT; } else if( psIn->eComponentType == INOUT_COMPONENT_SINT32) { return SVT_INT; } } break; } case OPERAND_TYPE_CONSTANT_BUFFER: { ConstantBuffer* psCBuf = NULL; ShaderVarType* psVarType = NULL; int32_t index = -1; int32_t rebase = -1; int foundVar; GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); if(psCBuf) { foundVar = GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); if(foundVar && index == -1 && psOperand->psSubOperand[1] == NULL) { return psVarType->Type; } } else { // Todo: this isn't correct yet. return SVT_FLOAT; } break; } case OPERAND_TYPE_IMMEDIATE32: { return psOperand->iIntegerImmediate ? SVT_INT : SVT_FLOAT; } case OPERAND_TYPE_INPUT_THREAD_ID: case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: { return SVT_UINT; } case OPERAND_TYPE_SPECIAL_ADDRESS: { return SVT_INT; } default: { return SVT_FLOAT; } } return SVT_FLOAT; }
static void TranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle) { bstring glsl = *psContext->currentGLSLString; *pui32IgnoreSwizzle = 0; switch(psOperand->eType) { case OPERAND_TYPE_IMMEDIATE32: { if(psOperand->iNumComponents == 1) { if((ui32TOFlag & TO_FLAG_INTEGER) || psOperand->iIntegerImmediate || fpcheck(psOperand->afImmediates[0])) { bformata(glsl, "%d", *((int*)(&psOperand->afImmediates[0]))); } else { bformata(glsl, "%f", psOperand->afImmediates[0]); } } else if(psOperand->iNumComponents == 4) { if((ui32TOFlag & TO_FLAG_INTEGER) || psOperand->iIntegerImmediate || fpcheck(psOperand->afImmediates[0]) || fpcheck(psOperand->afImmediates[1]) || fpcheck(psOperand->afImmediates[2]) || fpcheck(psOperand->afImmediates[3])) { bformata(glsl, "vec4(%d, %d, %d, %d)", *(int*)&psOperand->afImmediates[0], *(int*)&psOperand->afImmediates[1], *(int*)&psOperand->afImmediates[2], *(int*)&psOperand->afImmediates[3]); } else { bformata(glsl, "vec4(%f, %f, %f, %f)", psOperand->afImmediates[0], psOperand->afImmediates[1], psOperand->afImmediates[2], psOperand->afImmediates[3]); } } break; } case OPERAND_TYPE_INPUT: { switch(psOperand->iIndexDims) { case INDEX_2D: { if(psOperand->aui32ArraySizes[1] == 0)//Input index zero - position. { bcatcstr(glsl, "gl_in"); TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE);//Vertex index bcatcstr(glsl, ".gl_Position"); } else { const char* name = "Input"; if(ui32TOFlag & TO_FLAG_DECLARATION_NAME) { name = GetDeclaredName(psContext->psShader->eShaderType, psContext->flags); } bformata(glsl, "%s%d", name, psOperand->aui32ArraySizes[1]); TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE);//Vertex index } break; } default: { if(psOperand->eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE) { bformata(glsl, "Input%d[int(", psOperand->ui32RegisterNumber); TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE); bcatcstr(glsl, ")]"); } else { if(psContext->psShader->aIndexedInput[psOperand->ui32RegisterNumber] != 0) { const uint32_t parentIndex = psContext->psShader->aIndexedInputParents[psOperand->ui32RegisterNumber]; bformata(glsl, "Input%d[%d]", parentIndex, psOperand->ui32RegisterNumber - parentIndex); } else { const char* name = "Input"; if(ui32TOFlag & TO_FLAG_DECLARATION_NAME) { name = GetDeclaredName(psContext->psShader->eShaderType, psContext->flags); } bformata(glsl, "%s%d", name, psOperand->ui32RegisterNumber); } } break; } } break; } case OPERAND_TYPE_OUTPUT: { bformata(glsl, "Output%d", psOperand->ui32RegisterNumber); if(psOperand->psSubOperand[0]) { bcatcstr(glsl, "[int("); //Indexes must be integral. TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE); bcatcstr(glsl, ")]"); } break; } case OPERAND_TYPE_OUTPUT_DEPTH: case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: { bcatcstr(glsl, "gl_FragDepth"); break; } case OPERAND_TYPE_TEMP: { bformata(glsl, "Temp%d", psOperand->ui32RegisterNumber); break; } case OPERAND_TYPE_CONSTANT_BUFFER: { const char* StageName = "VS"; ConstantBuffer* psCBuf = NULL; GetConstantBufferFromBindingPoint(psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); switch(psContext->psShader->eShaderType) { case PIXEL_SHADER: { StageName = "PS"; break; } case HULL_SHADER: { StageName = "HS"; break; } case DOMAIN_SHADER: { StageName = "DS"; break; } case GEOMETRY_SHADER: { StageName = "GS"; break; } default: { break; } } #if CBUFFER_USE_STRUCT_AND_NAMES { char* pszContBuffName; pszContBuffName = psCBuf->Name; if(psCBuf->Name[0] == '$')//$Global or $Param pszContBuffName++; ASSERT(psOperand->aui32ArraySizes[1] < psCBuf->ui32NumVars); bformata(glsl, "%s%s.%s", pszContBuffName, StageName, psCBuf->asVars[psOperand->aui32ArraySizes[1]].Name); } #else if(psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) { if((psCBuf->Name[0] == '$') && (psContext->flags & HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO)) { bformata(glsl, "Globals%s[%d]", StageName, psOperand->aui32ArraySizes[1]); } else { //Each uniform block is given the HLSL consant buffer name. //Within each uniform block is a constant array named ConstN bformata(glsl, "Const%d[%d]", psOperand->aui32ArraySizes[0], psOperand->aui32ArraySizes[1]); } } else { //$Globals. if(psCBuf->Name[0] == '$') { bformata(glsl, "Globals%s[%d]", StageName, psOperand->aui32ArraySizes[1]); } else { bformata(glsl, "%s%s[%d]", psCBuf->Name, StageName, psOperand->aui32ArraySizes[1]); } } #endif break; } case OPERAND_TYPE_RESOURCE: { TextureName(psContext, psOperand->ui32RegisterNumber, 0); break; } case OPERAND_TYPE_SAMPLER: { bformata(glsl, "Sampler%d", psOperand->ui32RegisterNumber); break; } case OPERAND_TYPE_FUNCTION_BODY: { const uint32_t ui32FuncBody = psOperand->ui32RegisterNumber; const uint32_t ui32FuncTable = psContext->psShader->aui32FuncBodyToFuncTable[ui32FuncBody]; //const uint32_t ui32FuncPointer = psContext->psShader->aui32FuncTableToFuncPointer[ui32FuncTable]; const uint32_t ui32ClassType = psContext->psShader->sInfo.aui32TableIDToTypeID[ui32FuncTable]; const char* ClassTypeName = &psContext->psShader->sInfo.psClassTypes[ui32ClassType].Name[0]; const uint32_t ui32UniqueClassFuncIndex = psContext->psShader->ui32NextClassFuncName[ui32ClassType]++; bformata(glsl, "%s_Func%d", ClassTypeName, ui32UniqueClassFuncIndex); break; } case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID: { bcatcstr(glsl, "forkInstanceID"); *pui32IgnoreSwizzle = 1; return; } case OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: { bcatcstr(glsl, "immediateConstBufferF"); if(psOperand->psSubOperand[0]) { bcatcstr(glsl, "(int("); //Indexes must be integral. TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE); bcatcstr(glsl, "))"); } break; } case OPERAND_TYPE_INPUT_DOMAIN_POINT: { bcatcstr(glsl, "gl_TessCoord"); break; } case OPERAND_TYPE_INPUT_CONTROL_POINT: { if(psOperand->aui32ArraySizes[1] == 0)//Input index zero - position. { bformata(glsl, "gl_in[%d].gl_Position", psOperand->aui32ArraySizes[0]); } else { bformata(glsl, "Input%d[%d]", psOperand->aui32ArraySizes[1], psOperand->aui32ArraySizes[0]); } break; } case OPERAND_TYPE_NULL: { // Null register, used to discard results of operations bcatcstr(glsl, "//null"); break; } case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: { bcatcstr(glsl, "gl_InvocationID"); *pui32IgnoreSwizzle = 1; break; } case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: { bcatcstr(glsl, "gl_SampleMask[0]"); *pui32IgnoreSwizzle = 1; break; } case OPERAND_TYPE_INPUT_COVERAGE_MASK: { bcatcstr(glsl, "gl_SampleMaskIn[0]"); //Skip swizzle on scalar types. *pui32IgnoreSwizzle = 1; break; } default: { ASSERT(0); break; } } }
const uint32_t* DecodeDeclaration(Shader* psShader, const uint32_t* pui32Token, Declaration* psDecl) { uint32_t ui32TokenLength = DecodeInstructionLength(*pui32Token); const uint32_t bExtended = DecodeIsOpcodeExtended(*pui32Token); const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32Token); uint32_t ui32OperandOffset = 1; psDecl->eOpcode = eOpcode; psDecl->ui32IsShadowTex = 0; if(bExtended) { ui32OperandOffset = 2; } switch (eOpcode) { case OPCODE_DCL_RESOURCE: // DCL* opcodes have { psDecl->value.eResourceDimension = DecodeResourceDimension(*pui32Token); psDecl->ui32NumOperands = 1; DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); break; } case OPCODE_DCL_CONSTANT_BUFFER: // custom operand formats. { psDecl->ui32NumOperands = 1; DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); break; } case OPCODE_DCL_SAMPLER: { break; } case OPCODE_DCL_INDEX_RANGE: { psDecl->ui32NumOperands = 1; ui32OperandOffset += DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); psDecl->value.ui32IndexRange = pui32Token[ui32OperandOffset]; if(psDecl->asOperands[0].eType == OPERAND_TYPE_INPUT) { uint32_t i; const uint32_t indexRange = psDecl->value.ui32IndexRange; const uint32_t reg = psDecl->asOperands[0].ui32RegisterNumber; psShader->aIndexedInput[reg] = indexRange; psShader->aIndexedInputParents[reg] = reg; //-1 means don't declare this input because it falls in //the range of an already declared array. for(i=reg+1; i<reg+indexRange; ++i) { psShader->aIndexedInput[i] = -1; psShader->aIndexedInputParents[i] = reg; } } if(psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT) { psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.ui32IndexRange; } break; } case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: { psDecl->value.eOutputPrimitiveTopology = DecodeGSOutputPrimitiveTopology(*pui32Token); break; } case OPCODE_DCL_GS_INPUT_PRIMITIVE: { psDecl->value.eInputPrimitive = DecodeGSInputPrimitive(*pui32Token); break; } case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: { psDecl->value.ui32MaxOutputVertexCount = pui32Token[1]; break; } case OPCODE_DCL_TESS_PARTITIONING: { psDecl->value.eTessPartitioning = DecodeTessPartitioning(*pui32Token); break; } case OPCODE_DCL_TESS_DOMAIN: { psDecl->value.eTessDomain = DecodeTessDomain(*pui32Token); break; } case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: { psDecl->value.eTessOutPrim = DecodeTessOutPrim(*pui32Token); break; } case OPCODE_DCL_THREAD_GROUP: { psDecl->value.aui32WorkGroupSize[0] = pui32Token[1]; psDecl->value.aui32WorkGroupSize[1] = pui32Token[2]; psDecl->value.aui32WorkGroupSize[2] = pui32Token[3]; break; } case OPCODE_DCL_INPUT: { psDecl->ui32NumOperands = 1; DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); break; } case OPCODE_DCL_INPUT_SIV: { psDecl->ui32NumOperands = 1; DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); if(psShader->eShaderType == PIXEL_SHADER) { psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); } break; } case OPCODE_DCL_INPUT_PS: { psDecl->ui32NumOperands = 1; psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); break; } case OPCODE_DCL_INPUT_SGV: case OPCODE_DCL_INPUT_PS_SGV: { psDecl->ui32NumOperands = 1; DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); break; } case OPCODE_DCL_INPUT_PS_SIV: { psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); break; } case OPCODE_DCL_OUTPUT: { psDecl->ui32NumOperands = 1; DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); break; } case OPCODE_DCL_OUTPUT_SGV: { break; } case OPCODE_DCL_OUTPUT_SIV: { psDecl->ui32NumOperands = 1; DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); break; } case OPCODE_DCL_TEMPS: { psDecl->value.ui32NumTemps = *(pui32Token+ui32OperandOffset); break; } case OPCODE_DCL_INDEXABLE_TEMP: { break; } case OPCODE_DCL_GLOBAL_FLAGS: { psDecl->value.ui32GlobalFlags = DecodeGlobalFlags(*pui32Token); break; } case OPCODE_DCL_INTERFACE: { uint32_t func = 0, numClassesImplementingThisInterface, arrayLen, interfaceID; interfaceID = pui32Token[ui32OperandOffset]; ui32OperandOffset++; psDecl->ui32TableLength = pui32Token[ui32OperandOffset]; ui32OperandOffset++; numClassesImplementingThisInterface = DecodeInterfaceTableLength(*(pui32Token+ui32OperandOffset)); arrayLen = DecodeInterfaceArrayLength(*(pui32Token+ui32OperandOffset)); ui32OperandOffset++; psDecl->value.interface.ui32InterfaceID = interfaceID; psDecl->value.interface.ui32NumFuncTables = numClassesImplementingThisInterface; psDecl->value.interface.ui32ArraySize = arrayLen; psShader->funcPointer[interfaceID].ui32NumBodiesPerTable = psDecl->ui32TableLength; for(;func < numClassesImplementingThisInterface; ++func) { uint32_t ui32FuncTable = *(pui32Token+ui32OperandOffset); psShader->aui32FuncTableToFuncPointer[ui32FuncTable] = interfaceID; psShader->funcPointer[interfaceID].aui32FuncTables[func] = ui32FuncTable; ui32OperandOffset++; } break; } case OPCODE_DCL_FUNCTION_BODY: { psDecl->ui32NumOperands = 1; DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); break; } case OPCODE_DCL_FUNCTION_TABLE: { uint32_t ui32Func; const uint32_t ui32FuncTableID = pui32Token[ui32OperandOffset++]; const uint32_t ui32NumFuncsInTable = pui32Token[ui32OperandOffset++]; for(ui32Func=0; ui32Func<ui32NumFuncsInTable;++ui32Func) { const uint32_t ui32FuncBodyID = pui32Token[ui32OperandOffset++]; psShader->aui32FuncBodyToFuncTable[ui32FuncBodyID] = ui32FuncTableID; psShader->funcTable[ui32FuncTableID].aui32FuncBodies[ui32Func] = ui32FuncBodyID; } // OpcodeToken0 is followed by a DWORD that represents the function table // identifier and another DWORD (TableLength) that gives the number of // functions in the table. // // This is followed by TableLength DWORDs which are function body indices. // break; } case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: { break; } case OPCODE_HS_DECLS: { break; } case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: { psDecl->value.ui32MaxOutputVertexCount = DecodeOutputControlPointCount(*pui32Token); break; } case OPCODE_HS_JOIN_PHASE: case OPCODE_HS_FORK_PHASE: case OPCODE_HS_CONTROL_POINT_PHASE: { break; } case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: { ASSERT(psShader->ui32ForkPhaseCount != 0);//Check for wrapping when we decrement. psDecl->value.aui32HullPhaseInstanceInfo[0] = psShader->ui32ForkPhaseCount-1; psDecl->value.aui32HullPhaseInstanceInfo[1] = pui32Token[1]; break; } case OPCODE_CUSTOMDATA: { ui32TokenLength = pui32Token[1]; { int iTupleSrc = 0, iTupleDest = 0; //const uint32_t ui32ConstCount = pui32Token[1] - 2; //const uint32_t ui32TupleCount = (ui32ConstCount / 4); CUSTOMDATA_CLASS eClass = DecodeCustomDataClass(pui32Token[0]); const uint32_t ui32NumVec4 = (ui32TokenLength - 2) / 4; uint32_t uIdx = 0; ICBVec4 const *pVec4Array = (void*) (pui32Token + 2); //The buffer will contain at least one value, but not more than 4096 scalars/1024 vec4's. ASSERT(ui32NumVec4 < MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE); /* must be a multiple of 4 */ ASSERT(((ui32TokenLength - 2) % 4) == 0); for (uIdx = 0; uIdx < ui32NumVec4; uIdx++) { psDecl->asImmediateConstBuffer[uIdx] = pVec4Array[uIdx]; } psDecl->ui32NumOperands = ui32NumVec4; } break; } case OPCODE_DCL_HS_MAX_TESSFACTOR: { psDecl->value.fMaxTessFactor = *((float*)&pui32Token[1]); break; } case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: { psDecl->ui32NumOperands = 1; psDecl->value.eResourceDimension = DecodeResourceDimension(*pui32Token); psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); break; } case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: { ResourceBinding* psBinding = NULL; ConstantBuffer* psBuffer = NULL; psDecl->ui32NumOperands = 1; psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); if(GetResourceFromBindingPoint(RTYPE_UAV_RWBYTEADDRESS, psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psBinding)) { GetConstantBufferFromBindingPoint(psBinding->ui32BindPoint, &psShader->sInfo, &psBuffer); psDecl->sUAV.ui32BufferSize = psBuffer->ui32TotalSizeInBytes; } break; } case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: { ResourceBinding* psBinding = NULL; ConstantBuffer* psBuffer = NULL; psDecl->ui32NumOperands = 1; psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); if(GetResourceFromBindingPoint(RTYPE_UAV_RWSTRUCTURED, psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psBinding)) { GetUAVBufferFromBindingPoint(psBinding->ui32BindPoint, &psShader->sInfo, &psBuffer); psDecl->sUAV.ui32BufferSize = psBuffer->ui32TotalSizeInBytes; } break; } case OPCODE_DCL_RESOURCE_STRUCTURED: { psDecl->ui32NumOperands = 1; DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); break; } case OPCODE_DCL_RESOURCE_RAW: { psDecl->ui32NumOperands = 1; DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); break; } default: { //Reached end of declarations return 0; } } return pui32Token + ui32TokenLength; }
SHADER_VARIABLE_TYPE GetOperandDataType(HLSLCrossCompilerContext* psContext, const Operand* psOperand) { if(psOperand->eType == OPERAND_TYPE_TEMP) { SHADER_VARIABLE_TYPE eCurrentType; int i = 0; if(psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) { return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; } if(psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) { if(psOperand->ui32Swizzle == (NO_SWIZZLE)) { return psOperand->aeDataType[0]; } return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; } if(psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) { uint32_t ui32CompMask = psOperand->ui32CompMask; if(!psOperand->ui32CompMask) { ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; } for(;i<4;++i) { if(ui32CompMask & (1<<i)) { eCurrentType = psOperand->aeDataType[i]; break; } } #ifdef _DEBUG //Check if all elements have the same basic type. for(;i<4;++i) { if(psOperand->ui32CompMask & (1<<i)) { if(eCurrentType != psOperand->aeDataType[i]) { ASSERT(0); } } } #endif return eCurrentType; } ASSERT(0); } else if(psOperand->eType == OPERAND_TYPE_OUTPUT) { const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims-1]; InOutSignature* psOut; if(GetOutputSignatureFromRegister(ui32Register, psOperand->ui32CompMask, &psContext->psShader->sInfo, &psOut)) { if( psOut->eComponentType == INOUT_COMPONENT_UINT32) { return SVT_UINT; } else if( psOut->eComponentType == INOUT_COMPONENT_SINT32) { return SVT_INT; } } } else if(psOperand->eType == OPERAND_TYPE_INPUT) { const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims-1]; InOutSignature* psIn; if(GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn)) { if( psIn->eComponentType == INOUT_COMPONENT_UINT32) { return SVT_UINT; } else if( psIn->eComponentType == INOUT_COMPONENT_SINT32) { return SVT_INT; } } } else if(psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) { ConstantBuffer* psCBuf = NULL; ShaderVar* psVar = NULL; int32_t index = -1; int foundVar; GetConstantBufferFromBindingPoint(psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); foundVar = GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVar, &index); if(foundVar && index == -1 && psOperand->psSubOperand[1] == NULL) { return psVar->sType.Type; } } else if(psOperand->eType == OPERAND_TYPE_IMMEDIATE32) { return psOperand->iIntegerImmediate ? SVT_INT : SVT_FLOAT; } return SVT_FLOAT; }