Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
9.1 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #include <d3d10.h>
  9. #undef GetCommandLine
  10. #include "inputlayoutdx10.h"
  11. #include "materialsystem/imesh.h"
  12. #include "shaderdevicedx10.h"
  13. // NOTE: This has to be the last file included!
  14. #include "tier0/memdbgon.h"
  15. //-----------------------------------------------------------------------------
  16. // Standard input layouts
  17. //-----------------------------------------------------------------------------
  18. static const DXGI_FORMAT s_pSizeLookup[] =
  19. {
  20. DXGI_FORMAT_UNKNOWN, // Should be unused...
  21. DXGI_FORMAT_R32_FLOAT, // D3DDECLTYPE_FLOAT1
  22. DXGI_FORMAT_R32G32_FLOAT, // D3DDECLTYPE_FLOAT2,
  23. DXGI_FORMAT_R32G32B32_FLOAT, // D3DDECLTYPE_FLOAT3,
  24. DXGI_FORMAT_R32G32B32A32_FLOAT, // D3DDECLTYPE_FLOAT4
  25. };
  26. struct FieldInfo_t
  27. {
  28. const char *m_pSemanticString;
  29. unsigned int m_nSemanticIndex;
  30. uint64 m_nFormatMask;
  31. int m_nFieldSize;
  32. };
  33. static FieldInfo_t s_pFieldInfo[] =
  34. {
  35. { "POSITION", 0, VERTEX_POSITION, sizeof( float ) * 3 },
  36. { "BLENDWEIGHT", 0, VERTEX_BONE_WEIGHT_MASK, 0 },
  37. { "BLENDINDICES", 0, VERTEX_BONE_INDEX, 4 },
  38. { "NORMAL", 0, VERTEX_NORMAL, sizeof( float ) * 3 },
  39. { "COLOR", 0, VERTEX_COLOR, 4 },
  40. { "SPECULAR", 0, VERTEX_SPECULAR, 4 },
  41. { "TEXCOORD", 0, VERTEX_TEXCOORD_MASK(0), 0 },
  42. { "TEXCOORD", 1, VERTEX_TEXCOORD_MASK(1), 0 },
  43. { "TEXCOORD", 2, VERTEX_TEXCOORD_MASK(2), 0 },
  44. { "TEXCOORD", 3, VERTEX_TEXCOORD_MASK(3), 0 },
  45. { "TEXCOORD", 4, VERTEX_TEXCOORD_MASK(4), 0 },
  46. { "TEXCOORD", 5, VERTEX_TEXCOORD_MASK(5), 0 },
  47. { "TEXCOORD", 6, VERTEX_TEXCOORD_MASK(6), 0 },
  48. { "TEXCOORD", 7, VERTEX_TEXCOORD_MASK(7), 0 },
  49. { "TANGENT", 0, VERTEX_TANGENT_S, sizeof( float ) * 3 },
  50. { "BINORMAL", 0, VERTEX_TANGENT_T, sizeof( float ) * 3 },
  51. { "USERDATA", 0, USER_DATA_SIZE_MASK, 0 },
  52. { NULL, 0, 0 },
  53. };
  54. static D3D10_INPUT_ELEMENT_DESC s_pVertexDesc[] =
  55. {
  56. { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  57. { "BLENDWEIGHT", 0, DXGI_FORMAT_UNKNOWN, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  58. { "BLENDINDICES", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  59. { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  60. { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  61. { "SPECULAR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  62. { "TEXCOORD", 0, DXGI_FORMAT_UNKNOWN, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  63. { "TEXCOORD", 1, DXGI_FORMAT_UNKNOWN, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  64. { "TEXCOORD", 2, DXGI_FORMAT_UNKNOWN, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  65. { "TEXCOORD", 3, DXGI_FORMAT_UNKNOWN, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  66. { "TEXCOORD", 4, DXGI_FORMAT_UNKNOWN, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  67. { "TEXCOORD", 5, DXGI_FORMAT_UNKNOWN, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  68. { "TEXCOORD", 6, DXGI_FORMAT_UNKNOWN, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  69. { "TEXCOORD", 7, DXGI_FORMAT_UNKNOWN, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  70. { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  71. { "BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  72. { "USERDATA", 0, DXGI_FORMAT_UNKNOWN, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  73. };
  74. static D3D10_INPUT_ELEMENT_DESC s_pFallbackVertexDesc[] =
  75. {
  76. { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 15, 0, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  77. { "BLENDWEIGHT", 0, DXGI_FORMAT_R32G32_FLOAT, 15, 12, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  78. { "BLENDINDICES", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 15, 20, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  79. { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 15, 24, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  80. { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 15, 36, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  81. { "SPECULAR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 15, 40, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  82. { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 15, 44, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  83. { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 15, 52, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  84. { "TEXCOORD", 2, DXGI_FORMAT_R32G32_FLOAT, 15, 60, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  85. { "TEXCOORD", 3, DXGI_FORMAT_R32G32_FLOAT, 15, 68, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  86. { "TEXCOORD", 4, DXGI_FORMAT_R32G32_FLOAT, 15, 76, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  87. { "TEXCOORD", 5, DXGI_FORMAT_R32G32_FLOAT, 15, 84, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  88. { "TEXCOORD", 6, DXGI_FORMAT_R32G32_FLOAT, 15, 92, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  89. { "TEXCOORD", 7, DXGI_FORMAT_R32G32_FLOAT, 15, 100, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  90. { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 15, 108, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  91. { "BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 15, 120, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  92. { "USERDATA", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 15, 132, D3D10_INPUT_PER_INSTANCE_DATA, UINT_MAX },
  93. };
  94. //-----------------------------------------------------------------------------
  95. // Computes the required input desc based on the vertex format
  96. //-----------------------------------------------------------------------------
  97. static void PrintInputDesc( int nCount, const D3D10_INPUT_ELEMENT_DESC *pDecl )
  98. {
  99. for ( int i = 0; i < nCount; i++ )
  100. {
  101. Msg( "%s (%d): Stream: %d, Offset: %d, Instanced? %c\n",
  102. pDecl[i].SemanticName,
  103. pDecl[i].SemanticIndex,
  104. ( int )pDecl[i].InputSlot,
  105. ( int )pDecl[i].AlignedByteOffset,
  106. pDecl[i].InputSlotClass == D3D10_INPUT_PER_VERTEX_DATA ? 'n' : 'y'
  107. );
  108. }
  109. }
  110. //-----------------------------------------------------------------------------
  111. // Checks to see if a shader requires a particular field
  112. //-----------------------------------------------------------------------------
  113. static bool CheckShaderSignatureExpectations( ID3D10ShaderReflection* pReflection, const char* pSemantic, unsigned int nSemanticIndex )
  114. {
  115. D3D10_SHADER_DESC shaderDesc;
  116. D3D10_SIGNATURE_PARAMETER_DESC paramDesc;
  117. Assert( pSemantic );
  118. Assert( pReflection );
  119. pReflection->GetDesc( &shaderDesc );
  120. for ( unsigned int k=0; k < shaderDesc.InputParameters; k++ )
  121. {
  122. pReflection->GetInputParameterDesc( k, &paramDesc );
  123. if ( ( nSemanticIndex == paramDesc.SemanticIndex ) && !Q_stricmp( pSemantic, paramDesc.SemanticName ) )
  124. return true;
  125. }
  126. return false;
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Computes the required input desc based on the vertex format
  130. //-----------------------------------------------------------------------------
  131. static unsigned int ComputeInputDesc( VertexFormat_t fmt, D3D10_INPUT_ELEMENT_DESC *pDecl, ID3D10ShaderReflection* pReflection )
  132. {
  133. unsigned int nCount = 0;
  134. int nOffset = 0;
  135. // Fix up the global table so we don't need special-case code
  136. int nBoneCount = NumBoneWeights( fmt );
  137. s_pFieldInfo[1].m_nFieldSize = sizeof( float ) * nBoneCount;
  138. s_pVertexDesc[1].Format = s_pSizeLookup[ nBoneCount ];
  139. int nUserDataSize = UserDataSize( fmt );
  140. s_pFieldInfo[16].m_nFieldSize = sizeof( float ) * nUserDataSize;
  141. s_pVertexDesc[16].Format = s_pSizeLookup[ nUserDataSize ];
  142. // NOTE: Fix s_pFieldInfo, s_pVertexDesc, s_pFallbackVertexDesc if you add more fields
  143. // As well as the fallback stream (stream #15)
  144. COMPILE_TIME_ASSERT( VERTEX_MAX_TEXTURE_COORDINATES == 8 );
  145. for ( int i = 0; i < VERTEX_MAX_TEXTURE_COORDINATES; ++i )
  146. {
  147. int nTexCoordCount = TexCoordSize( i, fmt );
  148. s_pFieldInfo[6+i].m_nFieldSize = sizeof( float ) * nTexCoordCount;
  149. s_pVertexDesc[6+i].Format = s_pSizeLookup[ nTexCoordCount ];
  150. }
  151. // FIXME: Change this loop so CheckShaderSignatureExpectations is called once!
  152. for ( int i = 0; s_pFieldInfo[i].m_pSemanticString; ++i )
  153. {
  154. if ( fmt & s_pFieldInfo[i].m_nFormatMask )
  155. {
  156. memcpy( &pDecl[nCount], &s_pVertexDesc[i], sizeof(D3D10_INPUT_ELEMENT_DESC) );
  157. pDecl[nCount].AlignedByteOffset = nOffset;
  158. nOffset += s_pFieldInfo[i].m_nFieldSize;
  159. ++nCount;
  160. }
  161. else if ( CheckShaderSignatureExpectations( pReflection, s_pFieldInfo[i].m_pSemanticString, s_pFieldInfo[i].m_nSemanticIndex ) )
  162. {
  163. memcpy( &pDecl[nCount], &s_pFallbackVertexDesc[i], sizeof(D3D10_INPUT_ELEMENT_DESC) );
  164. ++nCount;
  165. }
  166. }
  167. // For debugging only...
  168. // PrintInputDesc( nCount, pDecl );
  169. return nCount;
  170. }
  171. //-----------------------------------------------------------------------------
  172. // Gets the input layout associated with a vertex format
  173. //-----------------------------------------------------------------------------
  174. ID3D10InputLayout *CreateInputLayout( VertexFormat_t fmt, ID3D10ShaderReflection* pReflection, const void *pByteCode, size_t nByteCodeLen )
  175. {
  176. D3D10_INPUT_ELEMENT_DESC pDecl[32];
  177. unsigned int nDeclCount = ComputeInputDesc( fmt, pDecl, pReflection );
  178. ID3D10InputLayout *pInputLayout;
  179. HRESULT hr = D3D10Device()->CreateInputLayout( pDecl, nDeclCount, pByteCode, nByteCodeLen, &pInputLayout );
  180. if ( FAILED( hr ) )
  181. {
  182. Warning( "CreateInputLayout::Unable to create input layout for format %X!\n", fmt );
  183. return NULL;
  184. }
  185. return pInputLayout;
  186. }