// Modifications copyright Amazon.com, Inc. or its affiliates // Modifications copyright Crytek GmbH #include "internal_includes/reflect.h" #include "internal_includes/debug.h" #include "internal_includes/decode.h" #include "internal_includes/hlslcc_malloc.h" #include "bstrlib.h" #include #include static void FormatVariableName(char* Name) { int i; /* MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/bb944006(v=vs.85).aspx The uniform function parameters appear in the constant table prepended with a dollar sign ($), unlike the global variables. The dollar sign is required to avoid name collisions between local uniform inputs and global variables of the same name.*/ /* Leave $ThisPointer, $Element and $Globals as-is. Otherwise remove $ character ($ is not a valid character for GLSL variable names). */ if(Name[0] == '$') { if(strcmp(Name, "$Element") !=0 && strcmp(Name, "$Globals") != 0 && strcmp(Name, "$ThisPointer") != 0) { Name[0] = '_'; } } // remove "__" because it's reserved in OpenGL for (i = 0; Name[i] != '\0'; ++i) { if (Name[i] == '_' && Name[i + 1] == '_') { Name[i + 1] = 'x'; } } } static void ReadStringFromTokenStream(const uint32_t* tokens, char* str) { char* charTokens = (char*) tokens; char nextCharacter = *charTokens++; int length = 0; //Add each individual character until //a terminator is found. while(nextCharacter != 0) { str[length++] = nextCharacter; if(length > MAX_REFLECT_STRING_LENGTH) { str[length-1] = '\0'; return; } nextCharacter = *charTokens++; } str[length] = '\0'; } static void ReadInputSignatures(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo, const int extended) { uint32_t i; InOutSignature* psSignatures; const uint32_t* pui32FirstSignatureToken = pui32Tokens; const uint32_t ui32ElementCount = *pui32Tokens++; const uint32_t ui32Key = *pui32Tokens++; psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); psShaderInfo->psInputSignatures = psSignatures; psShaderInfo->ui32NumInputSignatures = ui32ElementCount; for(i=0; iui32Stream = 0; psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; if(extended) psCurrentSignature->ui32Stream = *pui32Tokens++; ui32SemanticNameOffset = *pui32Tokens++; psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; psCurrentSignature->eSystemValueType = (SPECIAL_NAME) *pui32Tokens++; psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; psCurrentSignature->ui32Register = *pui32Tokens++; ui32ComponentMasks = *pui32Tokens++; psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; //Shows which components are read psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; if(extended) psCurrentSignature->eMinPrec = *pui32Tokens++; ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken+ui32SemanticNameOffset), psCurrentSignature->SemanticName); } } static void ReadOutputSignatures(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo, const int minPrec, const int streams) { uint32_t i; InOutSignature* psSignatures; const uint32_t* pui32FirstSignatureToken = pui32Tokens; const uint32_t ui32ElementCount = *pui32Tokens++; const uint32_t ui32Key = *pui32Tokens++; psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); psShaderInfo->psOutputSignatures = psSignatures; psShaderInfo->ui32NumOutputSignatures = ui32ElementCount; for(i=0; iui32Stream = 0; psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; if(streams) psCurrentSignature->ui32Stream = *pui32Tokens++; ui32SemanticNameOffset = *pui32Tokens++; psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; psCurrentSignature->eSystemValueType = (SPECIAL_NAME)*pui32Tokens++; psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; psCurrentSignature->ui32Register = *pui32Tokens++; ui32ComponentMasks = *pui32Tokens++; psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; //Shows which components are NEVER written. psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; if(minPrec) psCurrentSignature->eMinPrec = *pui32Tokens++; ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken+ui32SemanticNameOffset), psCurrentSignature->SemanticName); } } static const uint32_t* ReadResourceBinding(const uint32_t* pui32FirstResourceToken, const uint32_t* pui32Tokens, ResourceBinding* psBinding) { uint32_t ui32NameOffset = *pui32Tokens++; ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstResourceToken+ui32NameOffset), psBinding->Name); FormatVariableName(psBinding->Name); psBinding->eType = *pui32Tokens++; psBinding->ui32ReturnType = *pui32Tokens++; psBinding->eDimension = (REFLECT_RESOURCE_DIMENSION)*pui32Tokens++; psBinding->ui32NumSamples = *pui32Tokens++; psBinding->ui32BindPoint = *pui32Tokens++; psBinding->ui32BindCount = *pui32Tokens++; psBinding->ui32Flags = *pui32Tokens++; return pui32Tokens; } //Read D3D11_SHADER_TYPE_DESC static void ReadShaderVariableType(const uint32_t ui32MajorVersion, const uint32_t* pui32FirstConstBufToken, const uint32_t* pui32tokens, ShaderVarType* varType) { const uint16_t* pui16Tokens = (const uint16_t*) pui32tokens; uint16_t ui32MemberCount; uint32_t ui32MemberOffset; const uint32_t* pui32MemberTokens; uint32_t i; varType->Class = (SHADER_VARIABLE_CLASS)pui16Tokens[0]; varType->Type = (SHADER_VARIABLE_TYPE)pui16Tokens[1]; varType->Rows = pui16Tokens[2]; varType->Columns = pui16Tokens[3]; varType->Elements = pui16Tokens[4]; varType->MemberCount = ui32MemberCount = pui16Tokens[5]; varType->Members = 0; if(ui32MemberCount) { varType->Members = (ShaderVarType*)hlslcc_malloc(sizeof(ShaderVarType)*ui32MemberCount); ui32MemberOffset = pui32tokens[3]; pui32MemberTokens = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32MemberOffset); for(i=0; i< ui32MemberCount; ++i) { uint32_t ui32NameOffset = *pui32MemberTokens++; uint32_t ui32MemberTypeOffset = *pui32MemberTokens++; varType->Members[i].Parent = varType; varType->Members[i].ParentCount = varType->ParentCount + 1; varType->Members[i].Offset = *pui32MemberTokens++; ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken+ui32NameOffset), varType->Members[i].Name); ReadShaderVariableType(ui32MajorVersion, pui32FirstConstBufToken, (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32MemberTypeOffset), &varType->Members[i]); } } } static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo, const uint32_t* pui32FirstConstBufToken, const uint32_t* pui32Tokens, ConstantBuffer* psBuffer) { uint32_t i; uint32_t ui32NameOffset = *pui32Tokens++; uint32_t ui32VarCount = *pui32Tokens++; uint32_t ui32VarOffset = *pui32Tokens++; const uint32_t* pui32VarToken = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32VarOffset); ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken+ui32NameOffset), psBuffer->Name); FormatVariableName(psBuffer->Name); psBuffer->ui32NumVars = ui32VarCount; for(i=0; iasVars[i]; uint32_t ui32TypeOffset; uint32_t ui32DefaultValueOffset; ui32NameOffset = *pui32VarToken++; ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken+ui32NameOffset), psVar->Name); FormatVariableName(psVar->Name); psVar->ui32StartOffset = *pui32VarToken++; psVar->ui32Size = *pui32VarToken++; psVar->ui32Flags = *pui32VarToken++; ui32TypeOffset = *pui32VarToken++; strcpy(psVar->sType.Name, psVar->Name); psVar->sType.Parent = 0; psVar->sType.ParentCount = 0; psVar->sType.Offset = 0; ReadShaderVariableType(psShaderInfo->ui32MajorVersion, pui32FirstConstBufToken, (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32TypeOffset), &psVar->sType); ui32DefaultValueOffset = *pui32VarToken++; if (psShaderInfo->ui32MajorVersion >= 5) { uint32_t StartTexture = *pui32VarToken++; uint32_t TextureSize = *pui32VarToken++; uint32_t StartSampler = *pui32VarToken++; uint32_t SamplerSize = *pui32VarToken++; } psVar->haveDefaultValue = 0; if(ui32DefaultValueOffset) { uint32_t i = 0; const uint32_t ui32NumDefaultValues = psVar->ui32Size / 4; const uint32_t* pui32DefaultValToken = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32DefaultValueOffset); //Always a sequence of 4-bytes at the moment. //bool const becomes 0 or 0xFFFFFFFF int, int & float are 4-bytes. ASSERT(psVar->ui32Size%4 == 0); psVar->haveDefaultValue = 1; psVar->pui32DefaultValues = hlslcc_malloc(psVar->ui32Size); for(i=0; ipui32DefaultValues[i] = pui32DefaultValToken[i]; } } } { uint32_t ui32Flags; uint32_t ui32BufferType; psBuffer->ui32TotalSizeInBytes = *pui32Tokens++; psBuffer->blob = 0; ui32Flags = *pui32Tokens++; ui32BufferType = *pui32Tokens++; } return pui32Tokens; } static void ReadResources(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo) { ResourceBinding* psResBindings; ConstantBuffer* psConstantBuffers; const uint32_t* pui32ConstantBuffers; const uint32_t* pui32ResourceBindings; const uint32_t* pui32FirstToken = pui32Tokens; uint32_t i; const uint32_t ui32NumConstantBuffers = *pui32Tokens++; const uint32_t ui32ConstantBufferOffset = *pui32Tokens++; uint32_t ui32NumResourceBindings = *pui32Tokens++; uint32_t ui32ResourceBindingOffset = *pui32Tokens++; uint32_t ui32ShaderModel = *pui32Tokens++; uint32_t ui32CompileFlags = *pui32Tokens++;//D3DCompile flags? http://msdn.microsoft.com/en-us/library/gg615083(v=vs.85).aspx //Resources pui32ResourceBindings = (const uint32_t*)((const char*)pui32FirstToken + ui32ResourceBindingOffset); psResBindings = hlslcc_malloc(sizeof(ResourceBinding)*ui32NumResourceBindings); psShaderInfo->ui32NumResourceBindings = ui32NumResourceBindings; psShaderInfo->psResourceBindings = psResBindings; for(i=0; i < ui32NumResourceBindings; ++i) { pui32ResourceBindings = ReadResourceBinding(pui32FirstToken, pui32ResourceBindings, psResBindings+i); ASSERT(psResBindings[i].ui32BindPoint < MAX_RESOURCE_BINDINGS); } //Constant buffers pui32ConstantBuffers = (const uint32_t*)((const char*)pui32FirstToken + ui32ConstantBufferOffset); psConstantBuffers = hlslcc_malloc(sizeof(ConstantBuffer) * ui32NumConstantBuffers); psShaderInfo->ui32NumConstantBuffers = ui32NumConstantBuffers; psShaderInfo->psConstantBuffers = psConstantBuffers; for(i=0; i < ui32NumConstantBuffers; ++i) { pui32ConstantBuffers = ReadConstantBuffer(psShaderInfo, pui32FirstToken, pui32ConstantBuffers, psConstantBuffers+i); } //Map resource bindings to constant buffers if(psShaderInfo->ui32NumConstantBuffers) { for(i=0; i < ui32NumResourceBindings; ++i) { ResourceGroup eRGroup; uint32_t cbufIndex = 0; eRGroup = ResourceTypeToResourceGroup(psResBindings[i].eType); //Find the constant buffer whose name matches the resource at the given resource binding point for(cbufIndex=0; cbufIndex < psShaderInfo->ui32NumConstantBuffers; cbufIndex++) { if(strcmp(psConstantBuffers[cbufIndex].Name, psResBindings[i].Name) == 0) { psShaderInfo->aui32ResourceMap[eRGroup][psResBindings[i].ui32BindPoint] = cbufIndex; } } } } } static const uint16_t* ReadClassType(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassType* psClassType) { const uint32_t* pui32Tokens = (const uint32_t*)pui16Tokens; uint32_t ui32NameOffset = *pui32Tokens; pui16Tokens+= 2; psClassType->ui16ID = *pui16Tokens++; psClassType->ui16ConstBufStride = *pui16Tokens++; psClassType->ui16Texture = *pui16Tokens++; psClassType->ui16Sampler = *pui16Tokens++; ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken+ui32NameOffset), psClassType->Name); return pui16Tokens; } static const uint16_t* ReadClassInstance(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassInstance* psClassInstance) { uint32_t ui32NameOffset = *pui16Tokens++ << 16; ui32NameOffset |= *pui16Tokens++; psClassInstance->ui16ID = *pui16Tokens++; psClassInstance->ui16ConstBuf = *pui16Tokens++; psClassInstance->ui16ConstBufOffset = *pui16Tokens++; psClassInstance->ui16Texture = *pui16Tokens++; psClassInstance->ui16Sampler = *pui16Tokens++; ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken+ui32NameOffset), psClassInstance->Name); return pui16Tokens; } static void ReadInterfaces(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo) { uint32_t i; uint32_t ui32StartSlot; const uint32_t* pui32FirstInterfaceToken = pui32Tokens; const uint32_t ui32ClassInstanceCount = *pui32Tokens++; const uint32_t ui32ClassTypeCount = *pui32Tokens++; const uint32_t ui32InterfaceSlotRecordCount = *pui32Tokens++; const uint32_t ui32InterfaceSlotCount = *pui32Tokens++; const uint32_t ui32ClassInstanceOffset = *pui32Tokens++; const uint32_t ui32ClassTypeOffset = *pui32Tokens++; const uint32_t ui32InterfaceSlotOffset = *pui32Tokens++; const uint16_t* pui16ClassTypes = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32ClassTypeOffset); const uint16_t* pui16ClassInstances = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32ClassInstanceOffset); const uint32_t* pui32InterfaceSlots = (const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32InterfaceSlotOffset); const uint32_t* pui32InterfaceSlotTokens = pui32InterfaceSlots; ClassType* psClassTypes; ClassInstance* psClassInstances; psClassTypes = hlslcc_malloc(sizeof(ClassType) * ui32ClassTypeCount); for(i=0; iaui32TableIDToTypeID[*pui32TableID++] = *pui16TypeID++; } ui32StartSlot += ui32SlotSpan; } psShaderInfo->ui32NumClassInstances = ui32ClassInstanceCount; psShaderInfo->psClassInstances = psClassInstances; psShaderInfo->ui32NumClassTypes = ui32ClassTypeCount; psShaderInfo->psClassTypes = psClassTypes; } void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ConstantBuffer** ppsConstBuf) { if(psShaderInfo->ui32MajorVersion > 3) { *ppsConstBuf = psShaderInfo->psConstantBuffers + psShaderInfo->aui32ResourceMap[eGroup][ui32BindPoint]; } else { ASSERT(psShaderInfo->ui32NumConstantBuffers == 1); *ppsConstBuf = psShaderInfo->psConstantBuffers; } } int GetResourceFromBindingPoint(const ResourceGroup eGroup, uint32_t const ui32BindPoint, const ShaderInfo* psShaderInfo, ResourceBinding** ppsOutBinding) { uint32_t i; const uint32_t ui32NumBindings = psShaderInfo->ui32NumResourceBindings; ResourceBinding* psBindings = psShaderInfo->psResourceBindings; for(i=0; i= psBindings[i].ui32BindPoint && ui32BindPoint < (psBindings[i].ui32BindPoint + psBindings[i].ui32BindCount)) { *ppsOutBinding = psBindings + i; return 1; } } } return 0; } int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar) { uint32_t i; ConstantBuffer* psThisPointerConstBuffer = psShaderInfo->psThisPointerConstBuffer; const uint32_t ui32NumVars = psThisPointerConstBuffer->ui32NumVars; for(i=0; i= psThisPointerConstBuffer->asVars[i].ui32StartOffset && ui32Offset < (psThisPointerConstBuffer->asVars[i].ui32StartOffset + psThisPointerConstBuffer->asVars[i].ui32Size)) { *ppsShaderVar = &psThisPointerConstBuffer->asVars[i]; return 1; } } return 0; } int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut) { uint32_t i; const uint32_t ui32NumVars = psShaderInfo->ui32NumInputSignatures; for(i=0; ipsInputSignatures; if(ui32Register == psInputSignatures[i].ui32Register) { *ppsOut = psInputSignatures+i; return 1; } } return 0; } int GetOutputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32CompMask, const uint32_t ui32Stream, ShaderInfo* psShaderInfo, InOutSignature** ppsOut) { uint32_t i; const uint32_t ui32NumVars = psShaderInfo->ui32NumOutputSignatures; for(i=0; ipsOutputSignatures; if(ui32Register == psOutputSignatures[i].ui32Register && (ui32CompMask & psOutputSignatures[i].ui32Mask) && ui32Stream == psOutputSignatures[i].ui32Stream) { *ppsOut = psOutputSignatures+i; return 1; } } return 0; } int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, ShaderInfo* psShaderInfo, InOutSignature** ppsOut) { uint32_t i; const uint32_t ui32NumVars = psShaderInfo->ui32NumOutputSignatures; for(i=0; ipsOutputSignatures; if(eSystemValueType == psOutputSignatures[i].eSystemValueType && ui32SemanticIndex == psOutputSignatures[i].ui32SemanticIndex) { *ppsOut = psOutputSignatures+i; return 1; } } return 0; } static int IsOffsetInType(ShaderVarType* psType, uint32_t parentOffset, uint32_t offsetToFind, const uint32_t* pui32Swizzle, int32_t* pi32Index, int32_t* pi32Rebase) { uint32_t thisOffset = parentOffset + psType->Offset; uint32_t thisSize = psType->Columns * psType->Rows * 4; if(psType->Elements) { thisSize += 16 * (psType->Elements - 1); } //Swizzle can point to another variable. In the example below //cbUIUpdates.g_uMaxFaces would be cb1[2].z. The scalars are combined //into vectors. psCBuf->ui32NumVars will be 3. // cbuffer cbUIUpdates // { // // float g_fLifeSpan; // Offset: 0 Size: 4 // float g_fLifeSpanVar; // Offset: 4 Size: 4 [unused] // float g_fRadiusMin; // Offset: 8 Size: 4 [unused] // float g_fRadiusMax; // Offset: 12 Size: 4 [unused] // float g_fGrowTime; // Offset: 16 Size: 4 [unused] // float g_fStepSize; // Offset: 20 Size: 4 // float g_fTurnRate; // Offset: 24 Size: 4 // float g_fTurnSpeed; // Offset: 28 Size: 4 [unused] // float g_fLeafRate; // Offset: 32 Size: 4 // float g_fShrinkTime; // Offset: 36 Size: 4 [unused] // uint g_uMaxFaces; // Offset: 40 Size: 4 // // } // Name Type Format Dim Slot Elements // ------------------------------ ---------- ------- ----------- ---- -------- // cbUIUpdates cbuffer NA NA 1 1 if(pui32Swizzle[0] == OPERAND_4_COMPONENT_Y) { offsetToFind += 4; } else if(pui32Swizzle[0] == OPERAND_4_COMPONENT_Z) { offsetToFind += 8; } else if(pui32Swizzle[0] == OPERAND_4_COMPONENT_W) { offsetToFind += 12; } if((offsetToFind >= thisOffset) && offsetToFind < (thisOffset + thisSize)) { if(psType->Class == SVC_MATRIX_ROWS || psType->Class == SVC_MATRIX_COLUMNS) { //Matrices are treated as arrays of vectors. pi32Index[0] = (offsetToFind - thisOffset) / 16; } //Check for array of vectors else if(psType->Class == SVC_VECTOR && psType->Elements > 1) { pi32Index[0] = (offsetToFind - thisOffset) / 16; } else if(psType->Class == SVC_VECTOR && psType->Columns > 1) { //Check for vector starting at a non-vec4 offset. // cbuffer $Globals // { // // float angle; // Offset: 0 Size: 4 // float2 angle2; // Offset: 4 Size: 8 // // } //cb0[0].x = angle //cb0[0].yzyy = angle2.xyxx //Rebase angle2 so that .y maps to .x, .z maps to .y pi32Rebase[0] = thisOffset % 16; } return 1; } return 0; } int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset, const uint32_t* pui32Swizzle, ConstantBuffer* psCBuf, ShaderVarType** ppsShaderVar, int32_t* pi32Index, int32_t* pi32Rebase) { uint32_t i; const uint32_t ui32BaseByteOffset = ui32Vec4Offset * 16; uint32_t ui32ByteOffset = ui32Vec4Offset * 16; const uint32_t ui32NumVars = psCBuf->ui32NumVars; for(i=0; iasVars[i].sType.Class == SVC_STRUCT) { uint32_t m = 0; for(m=0; m < psCBuf->asVars[i].sType.MemberCount; ++m) { ShaderVarType* psMember = psCBuf->asVars[i].sType.Members + m; ASSERT(psMember->Class != SVC_STRUCT); if(IsOffsetInType(psMember, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, pui32Swizzle, pi32Index, pi32Rebase)) { ppsShaderVar[0] = psMember; return 1; } } } else { if(IsOffsetInType(&psCBuf->asVars[i].sType, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, pui32Swizzle, pi32Index, pi32Rebase)) { ppsShaderVar[0] = &psCBuf->asVars[i].sType; return 1; } } } return 0; } ResourceGroup ResourceTypeToResourceGroup(ResourceType eType) { switch(eType) { case RTYPE_CBUFFER: return RGROUP_CBUFFER; case RTYPE_SAMPLER: return RGROUP_SAMPLER; case RTYPE_TEXTURE: case RTYPE_BYTEADDRESS: case RTYPE_STRUCTURED: return RGROUP_TEXTURE; case RTYPE_UAV_RWTYPED: case RTYPE_UAV_RWSTRUCTURED: case RTYPE_UAV_RWBYTEADDRESS: case RTYPE_UAV_APPEND_STRUCTURED: case RTYPE_UAV_CONSUME_STRUCTURED: case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER: return RGROUP_UAV; case RTYPE_TBUFFER: ASSERT(0); // Need to find out which group this belongs to return RGROUP_TEXTURE; } ASSERT(0); return RGROUP_CBUFFER; } void LoadShaderInfo(const uint32_t ui32MajorVersion, const uint32_t ui32MinorVersion, const ReflectionChunks* psChunks, ShaderInfo* psInfo) { uint32_t i; const uint32_t* pui32Inputs = psChunks->pui32Inputs; const uint32_t* pui32Inputs11 = psChunks->pui32Inputs11; const uint32_t* pui32Resources = psChunks->pui32Resources; const uint32_t* pui32Interfaces = psChunks->pui32Interfaces; const uint32_t* pui32Outputs = psChunks->pui32Outputs; const uint32_t* pui32Outputs11 = psChunks->pui32Outputs11; const uint32_t* pui32OutputsWithStreams = psChunks->pui32OutputsWithStreams; psInfo->eTessOutPrim = TESSELLATOR_OUTPUT_UNDEFINED; psInfo->eTessPartitioning = TESSELLATOR_PARTITIONING_UNDEFINED; for(i=0; iaePixelInputInterpolation[i] = INTERPOLATION_LINEAR; psInfo->ui32MajorVersion = ui32MajorVersion; psInfo->ui32MinorVersion = ui32MinorVersion; psInfo->ui32NumImports = 0; psInfo->ui32NumExports = 0; psInfo->psImports = 0; psInfo->psExports = 0; psInfo->ui32InputHash = 0; psInfo->ui32SymbolsOffset = 0; psInfo->ui32NumSamplers = 0; if(pui32Inputs) ReadInputSignatures(pui32Inputs, psInfo, 0); if(pui32Inputs11) ReadInputSignatures(pui32Inputs11, psInfo, 1); if(pui32Resources) ReadResources(pui32Resources, psInfo); if(pui32Interfaces) ReadInterfaces(pui32Interfaces, psInfo); if(pui32Outputs) ReadOutputSignatures(pui32Outputs, psInfo, 0, 0); if(pui32Outputs11) ReadOutputSignatures(pui32Outputs11, psInfo, 1, 1); if(pui32OutputsWithStreams) ReadOutputSignatures(pui32OutputsWithStreams, psInfo, 0, 1); for(i=0; iui32NumConstantBuffers;++i) { bstring cbufName = bfromcstr(&psInfo->psConstantBuffers[i].Name[0]); bstring cbufThisPointer = bfromcstr("$ThisPointer"); if(bstrcmp(cbufName, cbufThisPointer) == 0) { psInfo->psThisPointerConstBuffer = &psInfo->psConstantBuffers[i]; } bdestroy(cbufName); bdestroy(cbufThisPointer); } memset(psInfo->asSamplers, 0, sizeof(psInfo->asSamplers)); } void FreeShaderInfo(ShaderInfo* psShaderInfo) { uint32_t uStep; //Free any default values for constants. uint32_t cbuf; for(cbuf=0; cbufui32NumConstantBuffers; ++cbuf) { ConstantBuffer* psCBuf = &psShaderInfo->psConstantBuffers[cbuf]; uint32_t var; for(var=0; var < psCBuf->ui32NumVars; ++var) { ShaderVar* psVar = &psCBuf->asVars[var]; hlslcc_free(psVar->sType.Members); if(psVar->haveDefaultValue) { hlslcc_free(psVar->pui32DefaultValues); } } } hlslcc_free(psShaderInfo->psInputSignatures); hlslcc_free(psShaderInfo->psResourceBindings); hlslcc_free(psShaderInfo->psConstantBuffers); hlslcc_free(psShaderInfo->psClassTypes); hlslcc_free(psShaderInfo->psClassInstances); hlslcc_free(psShaderInfo->psOutputSignatures); hlslcc_free(psShaderInfo->psImports); hlslcc_free(psShaderInfo->psExports); for (uStep = 0; uStep < psShaderInfo->ui32NumTraceSteps; ++uStep) { hlslcc_free(psShaderInfo->psTraceSteps[uStep].psVariables); } hlslcc_free(psShaderInfo->psTraceSteps); psShaderInfo->ui32NumInputSignatures = 0; psShaderInfo->ui32NumResourceBindings = 0; psShaderInfo->ui32NumConstantBuffers = 0; psShaderInfo->ui32NumClassTypes = 0; psShaderInfo->ui32NumClassInstances = 0; psShaderInfo->ui32NumOutputSignatures = 0; psShaderInfo->ui32NumTraceSteps = 0; psShaderInfo->ui32NumImports = 0; psShaderInfo->ui32NumExports = 0; } typedef struct ConstantTableD3D9_TAG { uint32_t size; uint32_t creator; uint32_t version; uint32_t constants; uint32_t constantInfos; uint32_t flags; uint32_t target; } ConstantTableD3D9; // These enums match those in d3dx9shader.h. enum RegisterSet { RS_BOOL, RS_INT4, RS_FLOAT4, RS_SAMPLER, }; enum TypeClass { CLASS_SCALAR, CLASS_VECTOR, CLASS_MATRIX_ROWS, CLASS_MATRIX_COLUMNS, CLASS_OBJECT, CLASS_STRUCT, }; enum Type { PT_VOID, PT_BOOL, PT_INT, PT_FLOAT, PT_STRING, PT_TEXTURE, PT_TEXTURE1D, PT_TEXTURE2D, PT_TEXTURE3D, PT_TEXTURECUBE, PT_SAMPLER, PT_SAMPLER1D, PT_SAMPLER2D, PT_SAMPLER3D, PT_SAMPLERCUBE, PT_PIXELSHADER, PT_VERTEXSHADER, PT_PIXELFRAGMENT, PT_VERTEXFRAGMENT, PT_UNSUPPORTED, }; typedef struct ConstantInfoD3D9_TAG { uint32_t name; uint16_t registerSet; uint16_t registerIndex; uint16_t registerCount; uint16_t reserved; uint32_t typeInfo; uint32_t defaultValue; } ConstantInfoD3D9; typedef struct TypeInfoD3D9_TAG { uint16_t typeClass; uint16_t type; uint16_t rows; uint16_t columns; uint16_t elements; uint16_t structMembers; uint32_t structMemberInfos; } TypeInfoD3D9; typedef struct StructMemberInfoD3D9_TAG { uint32_t name; uint32_t typeInfo; } StructMemberInfoD3D9; void LoadD3D9ConstantTable(const char* data, ShaderInfo* psInfo) { ConstantTableD3D9* ctab; uint32_t constNum; ConstantInfoD3D9* cinfos; ConstantBuffer* psConstantBuffer; uint32_t ui32ConstantBufferSize = 0; uint32_t numResourceBindingsNeeded = 0; ShaderVar* var; ctab = (ConstantTableD3D9*)data; cinfos = (ConstantInfoD3D9*) (data + ctab->constantInfos); psInfo->ui32NumConstantBuffers++; //Only 1 Constant Table in d3d9 ASSERT(psInfo->ui32NumConstantBuffers==1); psConstantBuffer = hlslcc_malloc(sizeof(ConstantBuffer)); psInfo->psConstantBuffers = psConstantBuffer; psConstantBuffer->ui32NumVars = 0; strcpy(psConstantBuffer->Name, "$Globals"); //Determine how many resource bindings to create for(constNum = 0; constNum < ctab->constants; ++constNum) { if(cinfos[constNum].registerSet == RS_SAMPLER) { ++numResourceBindingsNeeded; } } psInfo->psResourceBindings = hlslcc_malloc(numResourceBindingsNeeded*sizeof(ResourceBinding)); var = &psConstantBuffer->asVars[0]; for(constNum = 0; constNum < ctab->constants; ++constNum) { TypeInfoD3D9* typeInfo = (TypeInfoD3D9*) (data + cinfos[constNum].typeInfo); if(cinfos[constNum].registerSet != RS_SAMPLER) { strcpy(var->Name, data + cinfos[constNum].name); FormatVariableName(var->Name); var->ui32Size = cinfos[constNum].registerCount * 16; var->ui32StartOffset = cinfos[constNum].registerIndex * 16; var->haveDefaultValue = 0; if(ui32ConstantBufferSize < (var->ui32Size + var->ui32StartOffset)) { ui32ConstantBufferSize = var->ui32Size + var->ui32StartOffset; } var->sType.Rows = typeInfo->rows; var->sType.Columns = typeInfo->columns; var->sType.Elements = typeInfo->elements; var->sType.MemberCount = typeInfo->structMembers; var->sType.Members = 0; var->sType.Offset = 0; var->sType.Parent = 0; var->sType.ParentCount = 0; switch(typeInfo->typeClass) { case CLASS_SCALAR: { var->sType.Class = SVC_SCALAR; break; } case CLASS_VECTOR: { var->sType.Class = SVC_VECTOR; break; } case CLASS_MATRIX_ROWS: { var->sType.Class = SVC_MATRIX_ROWS; break; } case CLASS_MATRIX_COLUMNS: { var->sType.Class = SVC_MATRIX_COLUMNS; break; } case CLASS_OBJECT: { var->sType.Class = SVC_OBJECT; break; } case CLASS_STRUCT: { var->sType.Class = SVC_STRUCT; break; } } switch(cinfos[constNum].registerSet) { case RS_BOOL: { var->sType.Type = SVT_BOOL; break; } case RS_INT4: { var->sType.Type = SVT_INT; break; } case RS_FLOAT4: { var->sType.Type = SVT_FLOAT; break; } } var++; psConstantBuffer->ui32NumVars++; } else { //Create a resource if it is sampler in order to replicate the d3d10+ //method of separating samplers from general constants. uint32_t ui32ResourceIndex = psInfo->ui32NumResourceBindings++; ResourceBinding* res = &psInfo->psResourceBindings[ui32ResourceIndex]; strcpy(res->Name, data + cinfos[constNum].name); FormatVariableName(res->Name); res->ui32BindPoint = cinfos[constNum].registerIndex; res->ui32BindCount = cinfos[constNum].registerCount; res->ui32Flags = 0; res->ui32NumSamples = 1; res->ui32ReturnType = 0; res->eType = RTYPE_TEXTURE; switch(typeInfo->type) { case PT_SAMPLER: case PT_SAMPLER1D: res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE1D; break; case PT_SAMPLER2D: res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE2D; break; case PT_SAMPLER3D: res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE2D; break; case PT_SAMPLERCUBE: res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURECUBE; break; } } } psConstantBuffer->ui32TotalSizeInBytes = ui32ConstantBufferSize; }