BsGLSLParamParser.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "GLSL/BsGLSLParamParser.h"
  4. #include "RenderAPI/BsGpuParams.h"
  5. namespace bs { namespace ct
  6. {
  7. INT32 GLSLAttribute::matchesName(const String& name)
  8. {
  9. if (name.length() >= mName.length())
  10. {
  11. if (name.substr(0, mName.length()) == mName)
  12. {
  13. String indexStr = name.substr(mName.length(), name.length());
  14. return parseUINT32(indexStr, 0);
  15. }
  16. }
  17. return -1;
  18. }
  19. List<VertexElement> GLSLParamParser::buildVertexDeclaration(GLuint glProgram)
  20. {
  21. GLint numAttributes = 0;
  22. glGetProgramiv(glProgram, GL_ACTIVE_ATTRIBUTES, &numAttributes);
  23. BS_CHECK_GL_ERROR();
  24. GLint maxNameSize = 0;
  25. glGetProgramiv(glProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameSize);
  26. BS_CHECK_GL_ERROR();
  27. GLchar* attributeName = (GLchar*)bs_alloc(sizeof(GLchar)* maxNameSize);
  28. List<VertexElement> elementList;
  29. for (GLint i = 0; i < numAttributes; i++)
  30. {
  31. GLint attribSize = 0;
  32. GLenum attribType = 0;
  33. glGetActiveAttrib(glProgram, i, maxNameSize, nullptr, &attribSize, &attribType, attributeName);
  34. BS_CHECK_GL_ERROR();
  35. VertexElementSemantic semantic = VES_POSITION;
  36. UINT16 index = 0;
  37. if (attribNameToElementSemantic(attributeName, semantic, index))
  38. {
  39. VertexElementType type = glTypeToAttributeType(attribType);
  40. UINT32 slot = glGetAttribLocation(glProgram, attributeName);
  41. BS_CHECK_GL_ERROR();
  42. elementList.push_back(VertexElement(0, slot, type, semantic, index));
  43. }
  44. else
  45. {
  46. // Ignore built-in attributes
  47. if(memcmp(attributeName, "gl_", 3) != 0)
  48. LOGWRN("Cannot determine vertex input attribute type for attribute: " + String(attributeName));
  49. }
  50. }
  51. bs_free(attributeName);
  52. return elementList;
  53. }
  54. UINT32 GLSLParamParser::calcInterfaceBlockElementSizeAndOffset(GpuParamDataType type, UINT32 arraySize, UINT32& offset)
  55. {
  56. const GpuParamDataTypeInfo& typeInfo = bs::GpuParams::PARAM_SIZES.lookup[type];
  57. UINT32 size = (typeInfo.baseTypeSize * typeInfo.numColumns * typeInfo.numRows) / 4;
  58. UINT32 alignment = typeInfo.alignment / 4;
  59. // Fix alignment if needed
  60. UINT32 alignOffset = offset % alignment;
  61. if (alignOffset != 0)
  62. {
  63. UINT32 padding = (alignment - alignOffset);
  64. offset += padding;
  65. }
  66. if (arraySize > 1)
  67. {
  68. // Array elements are always padded and aligned to vec4
  69. alignOffset = size % 4;
  70. if (alignOffset != 0)
  71. {
  72. UINT32 padding = (4 - alignOffset);
  73. size += padding;
  74. }
  75. alignOffset = offset % 4;
  76. if (alignOffset != 0)
  77. {
  78. UINT32 padding = (4 - alignOffset);
  79. offset += padding;
  80. }
  81. return size;
  82. }
  83. else
  84. return size;
  85. }
  86. VertexElementType GLSLParamParser::glTypeToAttributeType(GLenum glType)
  87. {
  88. switch (glType)
  89. {
  90. case GL_FLOAT:
  91. return VET_FLOAT1;
  92. case GL_FLOAT_VEC2:
  93. return VET_FLOAT2;
  94. case GL_FLOAT_VEC3:
  95. return VET_FLOAT3;
  96. case GL_FLOAT_VEC4:
  97. return VET_FLOAT4;
  98. case GL_INT:
  99. return VET_INT1;
  100. case GL_INT_VEC2:
  101. return VET_INT2;
  102. case GL_INT_VEC3:
  103. return VET_INT3;
  104. case GL_INT_VEC4:
  105. return VET_INT4;
  106. case GL_UNSIGNED_INT:
  107. return VET_UINT1;
  108. case GL_UNSIGNED_INT_VEC2:
  109. return VET_UINT2;
  110. case GL_UNSIGNED_INT_VEC3:
  111. return VET_UINT3;
  112. case GL_UNSIGNED_INT_VEC4:
  113. return VET_UINT4;
  114. default:
  115. BS_EXCEPT(NotImplementedException, "Unsupported vertex attribute type.");
  116. }
  117. return VET_FLOAT4;
  118. }
  119. bool GLSLParamParser::attribNameToElementSemantic(const String& name, VertexElementSemantic& semantic, UINT16& index)
  120. {
  121. static GLSLAttribute attributes[] =
  122. {
  123. GLSLAttribute("bs_position", VES_POSITION),
  124. GLSLAttribute("bs_normal", VES_NORMAL),
  125. GLSLAttribute("bs_tangent", VES_TANGENT),
  126. GLSLAttribute("bs_bitangent", VES_BITANGENT),
  127. GLSLAttribute("bs_texcoord", VES_TEXCOORD),
  128. GLSLAttribute("bs_color", VES_COLOR),
  129. GLSLAttribute("bs_blendweights", VES_BLEND_WEIGHTS),
  130. GLSLAttribute("bs_blendindices", VES_BLEND_INDICES),
  131. GLSLAttribute("POSITION", VES_POSITION),
  132. GLSLAttribute("NORMAL", VES_NORMAL),
  133. GLSLAttribute("TANGENT", VES_TANGENT),
  134. GLSLAttribute("BITANGENT", VES_BITANGENT),
  135. GLSLAttribute("TEXCOORD", VES_TEXCOORD),
  136. GLSLAttribute("COLOR", VES_COLOR),
  137. GLSLAttribute("BLENDWEIGHT", VES_BLEND_WEIGHTS),
  138. GLSLAttribute("BLENDINDICES", VES_BLEND_INDICES)
  139. };
  140. static const UINT32 numAttribs = sizeof(attributes) / sizeof(attributes[0]);
  141. for (UINT32 i = 0; i < numAttribs; i++)
  142. {
  143. INT32 attribIndex = attributes[i].matchesName(name);
  144. if (attribIndex != -1)
  145. {
  146. index = attribIndex;
  147. semantic = attributes[i].getSemantic();
  148. return true;
  149. }
  150. }
  151. return false;
  152. }
  153. void GLSLParamParser::buildUniformDescriptions(GLuint glProgram, GpuProgramType type, GpuParamDesc& returnParamDesc)
  154. {
  155. // Scan through the active uniform blocks
  156. GLint maxBufferSize = 0;
  157. glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxBufferSize);
  158. BS_CHECK_GL_ERROR();
  159. GLint maxBlockNameBufferSize = 0;
  160. glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxBlockNameBufferSize);
  161. BS_CHECK_GL_ERROR();
  162. GLint maxStorageBlockNameBufferSize = 0;
  163. #if BS_OPENGL_4_3 || BS_OPENGLES_3_1
  164. glGetProgramInterfaceiv(glProgram, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &maxStorageBlockNameBufferSize);
  165. BS_CHECK_GL_ERROR();
  166. #endif
  167. maxBufferSize = std::max(maxBufferSize, maxBlockNameBufferSize);
  168. maxBufferSize = std::max(maxBufferSize, maxStorageBlockNameBufferSize);
  169. GLchar* uniformName = (GLchar*)bs_alloc(sizeof(GLchar)* maxBufferSize);
  170. GpuParamBlockDesc newGlobalBlockDesc;
  171. newGlobalBlockDesc.slot = 0;
  172. newGlobalBlockDesc.set = mapParameterToSet(type, ParamType::UniformBlock);
  173. newGlobalBlockDesc.name = "BS_INTERNAL_Globals";
  174. newGlobalBlockDesc.blockSize = 0;
  175. newGlobalBlockDesc.isShareable = false;
  176. returnParamDesc.paramBlocks[newGlobalBlockDesc.name] = newGlobalBlockDesc;
  177. GpuParamBlockDesc& globalBlockDesc = returnParamDesc.paramBlocks[newGlobalBlockDesc.name];
  178. // Enumerate uniform blocks
  179. GLint uniformBlockCount = 0;
  180. #if BS_OPENGL_4_3 || BS_OPENGLES_3_1
  181. // Use program interface extension if available
  182. glGetProgramInterfaceiv(glProgram, GL_UNIFORM_BLOCK, GL_ACTIVE_RESOURCES, &uniformBlockCount);
  183. BS_CHECK_GL_ERROR();
  184. #else
  185. // Fall back to old API if not available
  186. glGetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCKS, &uniformBlockCount);
  187. BS_CHECK_GL_ERROR();
  188. #endif
  189. Map<UINT32, String> blockSlotToName;
  190. Set<String> blockNames;
  191. for (GLuint index = 0; index < (GLuint)uniformBlockCount; index++)
  192. {
  193. GLsizei unusedSize = 0;
  194. #if BS_OPENGL_4_3 || BS_OPENGLES_3_1
  195. glGetProgramResourceName(glProgram, GL_UNIFORM_BLOCK, index, maxBufferSize, &unusedSize, uniformName);
  196. BS_CHECK_GL_ERROR();
  197. #else
  198. glGetActiveUniformBlockName(glProgram, index, maxBlockNameBufferSize, &unusedSize, uniformName);
  199. BS_CHECK_GL_ERROR();
  200. #endif
  201. GpuParamBlockDesc newBlockDesc;
  202. newBlockDesc.slot = index + 1;
  203. newBlockDesc.set = mapParameterToSet(type, ParamType::UniformBlock);
  204. newBlockDesc.name = uniformName;
  205. newBlockDesc.blockSize = 0;
  206. newBlockDesc.isShareable = true;
  207. returnParamDesc.paramBlocks[newBlockDesc.name] = newBlockDesc;
  208. blockSlotToName.insert(std::make_pair(index + 1, newBlockDesc.name));
  209. blockNames.insert(newBlockDesc.name);
  210. }
  211. #if BS_OPENGL_4_3 || BS_OPENGLES_3_1
  212. // Scan through the shared storage blocks
  213. GLint storageBlockCount = 0;
  214. glGetProgramInterfaceiv(glProgram, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &storageBlockCount);
  215. BS_CHECK_GL_ERROR();
  216. for (GLuint index = 0; index < (GLuint)storageBlockCount; index++)
  217. {
  218. GLsizei unusedSize = 0;
  219. glGetProgramResourceName(glProgram, GL_SHADER_STORAGE_BLOCK, index, maxBufferSize, &unusedSize, uniformName);
  220. BS_CHECK_GL_ERROR();
  221. GpuParamObjectDesc bufferParam;
  222. bufferParam.name = uniformName;
  223. bufferParam.slot = index;
  224. bufferParam.type = GPOT_RWSTRUCTURED_BUFFER;
  225. bufferParam.set = mapParameterToSet(type, ParamType::StorageBlock);
  226. returnParamDesc.buffers.insert(std::make_pair(uniformName, bufferParam));
  227. }
  228. #endif
  229. Map<String, UINT32> foundFirstArrayIndex;
  230. Map<String, GpuParamDataDesc> foundStructs;
  231. // Get the number of active uniforms
  232. GLint uniformCount = 0;
  233. glGetProgramiv(glProgram, GL_ACTIVE_UNIFORMS, &uniformCount);
  234. BS_CHECK_GL_ERROR();
  235. // Loop over each of the active uniforms, and add them to the reference container
  236. // only do this for user defined uniforms, ignore built in gl state uniforms
  237. for (GLuint index = 0; index < (GLuint)uniformCount; index++)
  238. {
  239. GLsizei arraySize = 0;
  240. glGetActiveUniformName(glProgram, index, maxBufferSize, &arraySize, uniformName);
  241. BS_CHECK_GL_ERROR();
  242. String paramName = String(uniformName);
  243. // Naming rules and packing rules used here are described in
  244. // OpenGL Core Specification 2.11.4
  245. // Check if parameter is a part of a struct
  246. Vector<String> nameElements = StringUtil::tokenise(paramName, ".");
  247. bool inStruct = false;
  248. String structName;
  249. if (nameElements.size() > 1)
  250. {
  251. auto uniformBlockFind = blockNames.find(nameElements[0]);
  252. // Check if the name is not a struct, and instead a Uniform block namespace
  253. if (uniformBlockFind != blockNames.end())
  254. {
  255. // Possibly it's a struct inside a named uniform block
  256. if (nameElements.size() > 2)
  257. {
  258. inStruct = true;
  259. structName = nameElements[1];
  260. paramName = nameElements.back();
  261. }
  262. }
  263. else
  264. {
  265. inStruct = true;
  266. structName = nameElements[0];
  267. paramName = nameElements.back();
  268. }
  269. }
  270. String cleanParamName = paramName; // Param name without array indexes
  271. // Check if the parameter is in an array
  272. UINT32 arrayIdx = 0;
  273. bool isInArray = false;
  274. if (inStruct)
  275. {
  276. // If the uniform name has a "[" in it then its an array element uniform.
  277. String::size_type arrayStart = structName.find("[");
  278. String::size_type arrayEnd = structName.find("]");
  279. if (arrayStart != String::npos)
  280. {
  281. String strArrIdx = structName.substr(arrayStart + 1, arrayEnd - (arrayStart + 1));
  282. arrayIdx = parseUINT32(strArrIdx, 0);
  283. isInArray = true;
  284. structName = structName.substr(0, arrayStart);
  285. }
  286. }
  287. {
  288. // If the uniform name has a "[" in it then its an array element uniform.
  289. String::size_type arrayStart = cleanParamName.find("[");
  290. String::size_type arrayEnd = cleanParamName.find("]");
  291. if (arrayStart != String::npos)
  292. {
  293. String strArrIdx = cleanParamName.substr(arrayStart + 1, arrayEnd - (arrayStart + 1));
  294. // If in struct, we don't care about individual element array indices
  295. if(!inStruct)
  296. {
  297. arrayIdx = parseUINT32(strArrIdx, 0);
  298. isInArray = true;
  299. }
  300. cleanParamName = cleanParamName.substr(0, arrayStart);
  301. }
  302. }
  303. // GLSL will optimize out unused array indexes, so there's no guarantee that 0 is the first,
  304. // so we store the first one here
  305. int firstArrayIndex = 0;
  306. if (isInArray)
  307. {
  308. String nameToSearch = cleanParamName;
  309. if (inStruct)
  310. nameToSearch = structName;
  311. auto arrayIndexFind = foundFirstArrayIndex.find(nameToSearch);
  312. if (arrayIndexFind == foundFirstArrayIndex.end())
  313. {
  314. foundFirstArrayIndex[nameToSearch] = arrayIdx;
  315. }
  316. firstArrayIndex = foundFirstArrayIndex[nameToSearch];
  317. }
  318. GLint uniformType;
  319. glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_TYPE, &uniformType);
  320. BS_CHECK_GL_ERROR();
  321. GpuParamObjectType samplerType = GPOT_UNKNOWN;
  322. GpuParamObjectType textureType = GPOT_UNKNOWN;
  323. bool isSampler = false;
  324. bool isImage = false;
  325. bool isBuffer = false;
  326. bool isRWBuffer = false;
  327. switch (uniformType)
  328. {
  329. case GL_SAMPLER_1D:
  330. case GL_SAMPLER_1D_SHADOW:
  331. case GL_UNSIGNED_INT_SAMPLER_1D:
  332. case GL_INT_SAMPLER_1D:
  333. samplerType = GPOT_SAMPLER1D;
  334. textureType = GPOT_TEXTURE1D;
  335. isSampler = true;
  336. break;
  337. case GL_SAMPLER_1D_ARRAY:
  338. case GL_SAMPLER_1D_ARRAY_SHADOW:
  339. case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
  340. case GL_INT_SAMPLER_1D_ARRAY:
  341. samplerType = GPOT_SAMPLER1D;
  342. textureType = GPOT_TEXTURE1DARRAY;
  343. isSampler = true;
  344. break;
  345. case GL_SAMPLER_2D:
  346. case GL_SAMPLER_2D_SHADOW:
  347. case GL_UNSIGNED_INT_SAMPLER_2D:
  348. case GL_INT_SAMPLER_2D:
  349. samplerType = GPOT_SAMPLER2D;
  350. textureType = GPOT_TEXTURE2D;
  351. isSampler = true;
  352. break;
  353. case GL_SAMPLER_2D_ARRAY:
  354. case GL_SAMPLER_2D_ARRAY_SHADOW:
  355. case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
  356. case GL_INT_SAMPLER_2D_ARRAY:
  357. samplerType = GPOT_SAMPLER2D;
  358. textureType = GPOT_TEXTURE2DARRAY;
  359. isSampler = true;
  360. break;
  361. case GL_SAMPLER_2D_MULTISAMPLE:
  362. case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
  363. case GL_INT_SAMPLER_2D_MULTISAMPLE:
  364. samplerType = GPOT_SAMPLER2DMS;
  365. textureType = GPOT_TEXTURE2DMS;
  366. isSampler = true;
  367. break;
  368. case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
  369. case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
  370. case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
  371. samplerType = GPOT_SAMPLER2DMS;
  372. textureType = GPOT_TEXTURE2DMSARRAY;
  373. isSampler = true;
  374. break;
  375. case GL_SAMPLER_3D:
  376. case GL_UNSIGNED_INT_SAMPLER_3D:
  377. case GL_INT_SAMPLER_3D:
  378. samplerType = GPOT_SAMPLER3D;
  379. textureType = GPOT_TEXTURE3D;
  380. isSampler = true;
  381. break;
  382. case GL_SAMPLER_CUBE:
  383. case GL_SAMPLER_CUBE_SHADOW:
  384. case GL_UNSIGNED_INT_SAMPLER_CUBE:
  385. case GL_INT_SAMPLER_CUBE:
  386. samplerType = GPOT_SAMPLERCUBE;
  387. textureType = GPOT_TEXTURECUBE;
  388. isSampler = true;
  389. break;
  390. case GL_SAMPLER_CUBE_MAP_ARRAY:
  391. case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
  392. case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY:
  393. case GL_INT_SAMPLER_CUBE_MAP_ARRAY:
  394. samplerType = GPOT_SAMPLERCUBE;
  395. textureType = GPOT_TEXTURECUBEARRAY;
  396. isSampler = true;
  397. break;
  398. case GL_SAMPLER_BUFFER:
  399. case GL_UNSIGNED_INT_SAMPLER_BUFFER:
  400. case GL_INT_SAMPLER_BUFFER:
  401. isBuffer = true;
  402. break;
  403. #if BS_OPENGL_4_2 || BS_OPENGLES_3_1
  404. case GL_IMAGE_1D:
  405. case GL_UNSIGNED_INT_IMAGE_1D:
  406. case GL_INT_IMAGE_1D:
  407. textureType = GPOT_RWTEXTURE1D;
  408. isImage = true;
  409. break;
  410. case GL_IMAGE_1D_ARRAY:
  411. case GL_UNSIGNED_INT_IMAGE_1D_ARRAY:
  412. case GL_INT_IMAGE_1D_ARRAY:
  413. textureType = GPOT_RWTEXTURE1DARRAY;
  414. isImage = true;
  415. break;
  416. case GL_IMAGE_2D:
  417. case GL_UNSIGNED_INT_IMAGE_2D:
  418. case GL_INT_IMAGE_2D:
  419. textureType = GPOT_RWTEXTURE2D;
  420. isImage = true;
  421. break;
  422. case GL_IMAGE_2D_ARRAY:
  423. case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
  424. case GL_INT_IMAGE_2D_ARRAY:
  425. textureType = GPOT_RWTEXTURE2DARRAY;
  426. isImage = true;
  427. break;
  428. case GL_IMAGE_2D_MULTISAMPLE:
  429. case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE:
  430. case GL_INT_IMAGE_2D_MULTISAMPLE:
  431. textureType = GPOT_RWTEXTURE2DMS;
  432. isImage = true;
  433. break;
  434. case GL_IMAGE_2D_MULTISAMPLE_ARRAY:
  435. case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
  436. case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
  437. textureType = GPOT_RWTEXTURE2DMSARRAY;
  438. isImage = true;
  439. break;
  440. case GL_IMAGE_3D:
  441. case GL_UNSIGNED_INT_IMAGE_3D:
  442. case GL_INT_IMAGE_3D:
  443. textureType = GPOT_RWTEXTURE3D;
  444. isImage = true;
  445. break;
  446. case GL_IMAGE_BUFFER:
  447. case GL_UNSIGNED_INT_IMAGE_BUFFER:
  448. case GL_INT_IMAGE_BUFFER:
  449. isRWBuffer = true;
  450. break;
  451. #endif
  452. }
  453. if (isSampler)
  454. {
  455. GpuParamObjectDesc samplerParam;
  456. samplerParam.name = paramName;
  457. samplerParam.type = samplerType;
  458. samplerParam.slot = glGetUniformLocation(glProgram, uniformName);
  459. samplerParam.set = mapParameterToSet(type, ParamType::Sampler);
  460. GpuParamObjectDesc textureParam;
  461. textureParam.name = paramName;
  462. textureParam.type = textureType;
  463. textureParam.slot = samplerParam.slot;
  464. textureParam.set = mapParameterToSet(type, ParamType::Texture);
  465. returnParamDesc.samplers.insert(std::make_pair(paramName, samplerParam));
  466. returnParamDesc.textures.insert(std::make_pair(paramName, textureParam));
  467. BS_CHECK_GL_ERROR();
  468. }
  469. else if (isImage)
  470. {
  471. GpuParamObjectDesc textureParam;
  472. textureParam.name = paramName;
  473. textureParam.type = textureType;
  474. textureParam.slot = glGetUniformLocation(glProgram, uniformName);
  475. textureParam.set = mapParameterToSet(type, ParamType::Image);
  476. returnParamDesc.loadStoreTextures.insert(std::make_pair(paramName, textureParam));
  477. BS_CHECK_GL_ERROR();
  478. }
  479. else if (isBuffer)
  480. {
  481. GpuParamObjectDesc bufferParam;
  482. bufferParam.name = paramName;
  483. bufferParam.type = GPOT_BYTE_BUFFER;
  484. bufferParam.slot = glGetUniformLocation(glProgram, uniformName);
  485. bufferParam.set = mapParameterToSet(type, ParamType::Texture);
  486. returnParamDesc.buffers.insert(std::make_pair(paramName, bufferParam));
  487. BS_CHECK_GL_ERROR();
  488. }
  489. else if(isRWBuffer)
  490. {
  491. GpuParamObjectDesc bufferParam;
  492. bufferParam.name = paramName;
  493. bufferParam.type = GPOT_RWBYTE_BUFFER;
  494. bufferParam.slot = glGetUniformLocation(glProgram, uniformName);
  495. bufferParam.set = mapParameterToSet(type, ParamType::Image);
  496. returnParamDesc.buffers.insert(std::make_pair(paramName, bufferParam));
  497. BS_CHECK_GL_ERROR();
  498. }
  499. else
  500. {
  501. // If array index is larger than 0 and uniform is not a part of a struct,
  502. // it means we already processed it (struct arrays are processed differently)
  503. if (!inStruct && arrayIdx != 0)
  504. continue;
  505. GLint blockIndex;
  506. glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_BLOCK_INDEX, &blockIndex);
  507. BS_CHECK_GL_ERROR();
  508. GpuParamDataDesc gpuParam;
  509. if (isInArray)
  510. gpuParam.name = cleanParamName;
  511. else
  512. gpuParam.name = paramName;
  513. determineParamInfo(gpuParam, paramName, glProgram, index);
  514. if (blockIndex != -1)
  515. {
  516. GLint blockOffset;
  517. glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_OFFSET, &blockOffset);
  518. blockOffset = blockOffset / 4;
  519. gpuParam.gpuMemOffset = blockOffset;
  520. String& blockName = blockSlotToName[blockIndex + 1];
  521. GpuParamBlockDesc& curBlockDesc = returnParamDesc.paramBlocks[blockName];
  522. gpuParam.paramBlockSlot = curBlockDesc.slot;
  523. gpuParam.paramBlockSet = mapParameterToSet(type, ParamType::UniformBlock);
  524. gpuParam.cpuMemOffset = blockOffset;
  525. curBlockDesc.blockSize = std::max(curBlockDesc.blockSize, gpuParam.cpuMemOffset + gpuParam.arrayElementStride * gpuParam.arraySize);
  526. BS_CHECK_GL_ERROR();
  527. }
  528. else
  529. {
  530. gpuParam.gpuMemOffset = glGetUniformLocation(glProgram, uniformName);
  531. gpuParam.paramBlockSlot = 0;
  532. gpuParam.paramBlockSet = mapParameterToSet(type, ParamType::UniformBlock);
  533. gpuParam.cpuMemOffset = globalBlockDesc.blockSize;
  534. globalBlockDesc.blockSize = std::max(globalBlockDesc.blockSize, gpuParam.cpuMemOffset + gpuParam.arrayElementStride * gpuParam.arraySize);
  535. BS_CHECK_GL_ERROR();
  536. }
  537. // If parameter is not a part of a struct we're done. Also done if parameter is part of a struct, but
  538. // not part of a uniform block (in which case we treat struct members as separate parameters)
  539. if (!inStruct || blockIndex == -1)
  540. {
  541. returnParamDesc.params.insert(std::make_pair(gpuParam.name, gpuParam));
  542. continue;
  543. }
  544. // If the parameter is part of a struct, then we need to update the struct definition
  545. auto findExistingStruct = foundStructs.find(structName);
  546. // Create new definition if one doesn't exist
  547. if (findExistingStruct == foundStructs.end())
  548. {
  549. foundStructs[structName] = GpuParamDataDesc();
  550. GpuParamDataDesc& structDesc = foundStructs[structName];
  551. structDesc.type = GPDT_STRUCT;
  552. structDesc.name = structName;
  553. structDesc.arraySize = 1;
  554. structDesc.elementSize = 0;
  555. structDesc.arrayElementStride = 0;
  556. structDesc.gpuMemOffset = gpuParam.gpuMemOffset;
  557. structDesc.cpuMemOffset = gpuParam.cpuMemOffset;
  558. structDesc.paramBlockSlot = gpuParam.paramBlockSlot;
  559. structDesc.paramBlockSet = gpuParam.paramBlockSet;
  560. }
  561. // Update struct with size of the new parameter
  562. GpuParamDataDesc& structDesc = foundStructs[structName];
  563. if (arrayIdx == (UINT32)firstArrayIndex) // Determine element size only using the first array element
  564. {
  565. structDesc.elementSize = std::max(structDesc.elementSize, gpuParam.cpuMemOffset +
  566. gpuParam.arrayElementStride * gpuParam.arraySize);
  567. structDesc.gpuMemOffset = std::min(structDesc.gpuMemOffset, gpuParam.gpuMemOffset);
  568. structDesc.cpuMemOffset = std::min(structDesc.cpuMemOffset, gpuParam.cpuMemOffset);
  569. }
  570. structDesc.arraySize = std::max(structDesc.arraySize, arrayIdx + 1);
  571. }
  572. }
  573. for(auto& entry : foundStructs)
  574. {
  575. entry.second.elementSize = entry.second.elementSize - entry.second.cpuMemOffset;
  576. entry.second.arrayElementStride = Math::divideAndRoundUp(entry.second.elementSize, 4U) * 4;
  577. returnParamDesc.params.insert(std::make_pair(entry.first, entry.second));
  578. }
  579. // Param blocks always need to be a multiple of 4, so make it so
  580. for (auto iter = returnParamDesc.paramBlocks.begin(); iter != returnParamDesc.paramBlocks.end(); ++iter)
  581. {
  582. GpuParamBlockDesc& blockDesc = iter->second;
  583. if (blockDesc.blockSize % 4 != 0)
  584. blockDesc.blockSize += (4 - (blockDesc.blockSize % 4));
  585. }
  586. #if BS_DEBUG_MODE
  587. // Check if manually calculated and OpenGL buffer sizes match
  588. for (auto iter = returnParamDesc.paramBlocks.begin(); iter != returnParamDesc.paramBlocks.end(); ++iter)
  589. {
  590. if (iter->second.slot == 0)
  591. continue;
  592. GLint blockSize = 0;
  593. glGetActiveUniformBlockiv(glProgram, iter->second.slot - 1, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
  594. BS_CHECK_GL_ERROR();
  595. assert(blockSize % 4 == 0);
  596. blockSize = blockSize / 4;
  597. if ((INT32)iter->second.blockSize != blockSize)
  598. BS_EXCEPT(InternalErrorException, "OpenGL specified and manual uniform block buffer sizes don't match!");
  599. }
  600. #endif
  601. bs_free(uniformName);
  602. }
  603. void GLSLParamParser::determineParamInfo(GpuParamDataDesc& desc, const String& paramName, GLuint programHandle, GLuint uniformIndex)
  604. {
  605. GLint arraySize;
  606. glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_SIZE, &arraySize);
  607. BS_CHECK_GL_ERROR();
  608. desc.arraySize = arraySize;
  609. GLint uniformType;
  610. glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_TYPE, &uniformType);
  611. BS_CHECK_GL_ERROR();
  612. switch (uniformType)
  613. {
  614. case GL_BOOL:
  615. desc.type = GPDT_BOOL;
  616. desc.elementSize = 1;
  617. break;
  618. case GL_FLOAT:
  619. desc.type = GPDT_FLOAT1;
  620. desc.elementSize = 1;
  621. break;
  622. case GL_FLOAT_VEC2:
  623. desc.type = GPDT_FLOAT2;
  624. desc.elementSize = 2;
  625. break;
  626. case GL_FLOAT_VEC3:
  627. desc.type = GPDT_FLOAT3;
  628. desc.elementSize = 3;
  629. break;
  630. case GL_FLOAT_VEC4:
  631. desc.type = GPDT_FLOAT4;
  632. desc.elementSize = 4;
  633. break;
  634. case GL_INT:
  635. case GL_UNSIGNED_INT:
  636. desc.type = GPDT_INT1;
  637. desc.elementSize = 1;
  638. break;
  639. case GL_INT_VEC2:
  640. case GL_UNSIGNED_INT_VEC2:
  641. desc.type = GPDT_INT2;
  642. desc.elementSize = 2;
  643. break;
  644. case GL_INT_VEC3:
  645. case GL_UNSIGNED_INT_VEC3:
  646. desc.type = GPDT_INT3;
  647. desc.elementSize = 3;
  648. break;
  649. case GL_INT_VEC4:
  650. case GL_UNSIGNED_INT_VEC4:
  651. desc.type = GPDT_INT4;
  652. desc.elementSize = 4;
  653. break;
  654. case GL_FLOAT_MAT2:
  655. desc.type = GPDT_MATRIX_2X2;
  656. desc.elementSize = 4;
  657. break;
  658. case GL_FLOAT_MAT3:
  659. desc.type = GPDT_MATRIX_3X3;
  660. desc.elementSize = 9;
  661. break;
  662. case GL_FLOAT_MAT4:
  663. desc.type = GPDT_MATRIX_4X4;
  664. desc.elementSize = 16;
  665. break;
  666. case GL_FLOAT_MAT2x3:
  667. desc.type = GPDT_MATRIX_2X3;
  668. desc.elementSize = 6;
  669. break;
  670. case GL_FLOAT_MAT3x2:
  671. desc.type = GPDT_MATRIX_3X2;
  672. desc.elementSize = 6;
  673. break;
  674. case GL_FLOAT_MAT2x4:
  675. desc.type = GPDT_MATRIX_2X4;
  676. desc.elementSize = 8;
  677. break;
  678. case GL_FLOAT_MAT4x2:
  679. desc.type = GPDT_MATRIX_4X2;
  680. desc.elementSize = 8;
  681. break;
  682. case GL_FLOAT_MAT3x4:
  683. desc.type = GPDT_MATRIX_3X4;
  684. desc.elementSize = 12;
  685. break;
  686. case GL_FLOAT_MAT4x3:
  687. desc.type = GPDT_MATRIX_4X3;
  688. desc.elementSize = 12;
  689. break;
  690. default:
  691. BS_EXCEPT(InternalErrorException, "Invalid shader parameter type: " + toString(uniformType) + " for parameter " + paramName);
  692. }
  693. if (arraySize > 1)
  694. {
  695. GLint arrayStride;
  696. glGetActiveUniformsiv(programHandle, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE, &arrayStride);
  697. BS_CHECK_GL_ERROR();
  698. if (arrayStride > 0)
  699. {
  700. assert(arrayStride % 4 == 0);
  701. desc.arrayElementStride = arrayStride / 4;
  702. }
  703. else
  704. desc.arrayElementStride = desc.elementSize;
  705. }
  706. else
  707. desc.arrayElementStride = desc.elementSize;
  708. }
  709. UINT32 GLSLParamParser::mapParameterToSet(GpuProgramType progType, ParamType paramType)
  710. {
  711. UINT32 progTypeIdx = (UINT32)progType;
  712. UINT32 paramTypeIdx = (UINT32)paramType;
  713. return progTypeIdx * (UINT32)ParamType::Count + paramTypeIdx;
  714. }
  715. }}