createdfd.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /* -*- tab-width: 4; -*- */
  2. /* vi: set sw=2 ts=4 expandtab: */
  3. /* Copyright 2019-2020 The Khronos Group Inc.
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @~English
  9. * @brief Utilities for creating data format descriptors.
  10. */
  11. /*
  12. * Author: Andrew Garrard
  13. */
  14. #include <stdlib.h>
  15. #include <KHR/khr_df.h>
  16. #include "dfd.h"
  17. typedef enum { i_COLOR, i_NON_COLOR } channels_infotype;
  18. static uint32_t *writeHeader(int numSamples, int bytes, int suffix,
  19. channels_infotype infotype)
  20. {
  21. uint32_t *DFD = (uint32_t *) malloc(sizeof(uint32_t) *
  22. (1 + KHR_DF_WORD_SAMPLESTART +
  23. numSamples * KHR_DF_WORD_SAMPLEWORDS));
  24. uint32_t* BDFD = DFD+1;
  25. DFD[0] = sizeof(uint32_t) *
  26. (1 + KHR_DF_WORD_SAMPLESTART +
  27. numSamples * KHR_DF_WORD_SAMPLEWORDS);
  28. BDFD[KHR_DF_WORD_VENDORID] =
  29. (KHR_DF_VENDORID_KHRONOS << KHR_DF_SHIFT_VENDORID) |
  30. (KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT << KHR_DF_SHIFT_DESCRIPTORTYPE);
  31. BDFD[KHR_DF_WORD_VERSIONNUMBER] =
  32. (KHR_DF_VERSIONNUMBER_LATEST << KHR_DF_SHIFT_VERSIONNUMBER) |
  33. (((uint32_t)sizeof(uint32_t) *
  34. (KHR_DF_WORD_SAMPLESTART +
  35. numSamples * KHR_DF_WORD_SAMPLEWORDS)
  36. << KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE));
  37. BDFD[KHR_DF_WORD_MODEL] =
  38. ((KHR_DF_MODEL_RGBSDA << KHR_DF_SHIFT_MODEL) | /* Only supported model */
  39. (KHR_DF_FLAG_ALPHA_STRAIGHT << KHR_DF_SHIFT_FLAGS));
  40. if (infotype == i_COLOR) {
  41. BDFD[KHR_DF_WORD_PRIMARIES] |= KHR_DF_PRIMARIES_BT709 << KHR_DF_SHIFT_PRIMARIES; /* Assumed */
  42. } else {
  43. BDFD[KHR_DF_WORD_PRIMARIES] |= KHR_DF_PRIMARIES_UNSPECIFIED << KHR_DF_SHIFT_PRIMARIES;
  44. }
  45. if (suffix == s_SRGB) {
  46. BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_SRGB << KHR_DF_SHIFT_TRANSFER;
  47. } else {
  48. BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_LINEAR << KHR_DF_SHIFT_TRANSFER;
  49. }
  50. BDFD[KHR_DF_WORD_TEXELBLOCKDIMENSION0] = 0; /* Only 1x1x1x1 texel blocks supported */
  51. BDFD[KHR_DF_WORD_BYTESPLANE0] = bytes; /* bytesPlane0 = bytes, bytesPlane3..1 = 0 */
  52. BDFD[KHR_DF_WORD_BYTESPLANE4] = 0; /* bytesPlane7..5 = 0 */
  53. return DFD;
  54. }
  55. static uint32_t setChannelFlags(uint32_t channel, enum VkSuffix suffix)
  56. {
  57. switch (suffix) {
  58. case s_UNORM: break;
  59. case s_SNORM:
  60. channel |=
  61. KHR_DF_SAMPLE_DATATYPE_SIGNED;
  62. break;
  63. case s_USCALED: break;
  64. case s_SSCALED:
  65. channel |=
  66. KHR_DF_SAMPLE_DATATYPE_SIGNED;
  67. break;
  68. case s_UINT: break;
  69. case s_SINT:
  70. channel |=
  71. KHR_DF_SAMPLE_DATATYPE_SIGNED;
  72. break;
  73. case s_SFLOAT:
  74. channel |=
  75. KHR_DF_SAMPLE_DATATYPE_FLOAT |
  76. KHR_DF_SAMPLE_DATATYPE_SIGNED;
  77. break;
  78. case s_UFLOAT:
  79. channel |=
  80. KHR_DF_SAMPLE_DATATYPE_FLOAT;
  81. break;
  82. case s_SRGB:
  83. if (channel == KHR_DF_CHANNEL_RGBSDA_ALPHA) {
  84. channel |= KHR_DF_SAMPLE_DATATYPE_LINEAR;
  85. }
  86. break;
  87. }
  88. return channel;
  89. }
  90. static void writeSample(uint32_t *DFD, int sampleNo, int channel,
  91. int bits, int offset,
  92. int topSample, int bottomSample, enum VkSuffix suffix)
  93. {
  94. // Use this to avoid type-punning complaints from the gcc optimizer
  95. // with -Wall.
  96. union {
  97. uint32_t i;
  98. float f;
  99. } lower, upper;
  100. uint32_t *sample = DFD + 1 + KHR_DF_WORD_SAMPLESTART + sampleNo * KHR_DF_WORD_SAMPLEWORDS;
  101. if (channel == 3) channel = KHR_DF_CHANNEL_RGBSDA_ALPHA;
  102. if (channel == 3) channel = KHR_DF_CHANNEL_RGBSDA_ALPHA;
  103. channel = setChannelFlags(channel, suffix);
  104. sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
  105. (offset << KHR_DF_SAMPLESHIFT_BITOFFSET) |
  106. ((bits - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
  107. (channel << KHR_DF_SAMPLESHIFT_CHANNELID);
  108. sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
  109. switch (suffix) {
  110. case s_UNORM:
  111. case s_SRGB:
  112. default:
  113. if (bits > 32) {
  114. upper.i = 0xFFFFFFFFU;
  115. } else {
  116. upper.i = (uint32_t)((1U << bits) - 1U);
  117. }
  118. lower.i = 0U;
  119. break;
  120. case s_SNORM:
  121. if (bits > 32) {
  122. upper.i = 0x7FFFFFFF;
  123. } else {
  124. upper.i = topSample ? (1U << (bits - 1)) - 1 : (1U << bits) - 1;
  125. }
  126. lower.i = ~upper.i;
  127. if (bottomSample) lower.i += 1;
  128. break;
  129. case s_USCALED:
  130. case s_UINT:
  131. upper.i = bottomSample ? 1U : 0U;
  132. lower.i = 0U;
  133. break;
  134. case s_SSCALED:
  135. case s_SINT:
  136. upper.i = bottomSample ? 1U : 0U;
  137. lower.i = ~0U;
  138. break;
  139. case s_SFLOAT:
  140. upper.f = 1.0f;
  141. lower.f = -1.0f;
  142. break;
  143. case s_UFLOAT:
  144. upper.f = 1.0f;
  145. lower.f = 0.0f;
  146. break;
  147. }
  148. sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
  149. sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
  150. }
  151. /**
  152. * @~English
  153. * @brief Create a Data Format Descriptor for an unpacked format.
  154. *
  155. * @param bigEndian Set to 1 for big-endian byte ordering and
  156. 0 for little-endian byte ordering.
  157. * @param numChannels The number of color channels.
  158. * @param bytes The number of bytes per channel.
  159. * @param redBlueSwap Normally channels appear in consecutive R, G, B, A order
  160. * in memory; redBlueSwap inverts red and blue, allowing
  161. * B, G, R, A.
  162. * @param suffix Indicates the format suffix for the type.
  163. *
  164. * @return A data format descriptor in malloc'd data. The caller is responsible
  165. * for freeing the descriptor.
  166. **/
  167. uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes,
  168. int redBlueSwap, enum VkSuffix suffix)
  169. {
  170. uint32_t *DFD;
  171. if (bigEndian) {
  172. int channelCounter, channelByte;
  173. /* Number of samples = number of channels * bytes per channel */
  174. DFD = writeHeader(numChannels * bytes, numChannels * bytes, suffix, i_COLOR);
  175. /* First loop over the channels */
  176. for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
  177. int channel = channelCounter;
  178. if (redBlueSwap && (channel == 0 || channel == 2)) {
  179. channel ^= 2;
  180. }
  181. /* Loop over the bytes that constitute a channel */
  182. for (channelByte = 0; channelByte < bytes; ++channelByte) {
  183. writeSample(DFD, channelCounter * bytes + channelByte, channel,
  184. 8, 8 * (channelCounter * bytes + bytes - channelByte - 1),
  185. channelByte == bytes-1, channelByte == 0, suffix);
  186. }
  187. }
  188. } else { /* Little-endian */
  189. int sampleCounter;
  190. /* One sample per channel */
  191. DFD = writeHeader(numChannels, numChannels * bytes, suffix, i_COLOR);
  192. for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
  193. int channel = sampleCounter;
  194. if (redBlueSwap && (channel == 0 || channel == 2)) {
  195. channel ^= 2;
  196. }
  197. writeSample(DFD, sampleCounter, channel,
  198. 8 * bytes, 8 * sampleCounter * bytes,
  199. 1, 1, suffix);
  200. }
  201. }
  202. return DFD;
  203. }
  204. /**
  205. * @~English
  206. * @brief Create a Data Format Descriptor for a packed format.
  207. *
  208. * @param bigEndian Big-endian flag: Set to 1 for big-endian byte ordering and
  209. * 0 for little-endian byte ordering.
  210. * @param numChannels The number of color channels.
  211. * @param bits[] An array of length numChannels.
  212. * Each entry is the number of bits composing the channel, in
  213. * order starting at bit 0 of the packed type.
  214. * @param channels[] An array of length numChannels.
  215. * Each entry enumerates the channel type: 0 = red, 1 = green,
  216. * 2 = blue, 15 = alpha, in order starting at bit 0 of the
  217. * packed type. These values match channel IDs for RGBSDA in
  218. * the Khronos Data Format header. To simplify iteration
  219. * through channels, channel id 3 is a synonym for alpha.
  220. * @param suffix Indicates the format suffix for the type.
  221. *
  222. * @return A data format descriptor in malloc'd data. The caller is responsible
  223. * for freeing the descriptor.
  224. **/
  225. uint32_t *createDFDPacked(int bigEndian, int numChannels,
  226. int bits[], int channels[],
  227. enum VkSuffix suffix)
  228. {
  229. uint32_t *DFD = 0;
  230. if (numChannels == 6) {
  231. /* Special case E5B9G9R9 */
  232. DFD = writeHeader(numChannels, 4, s_UFLOAT, i_COLOR);
  233. writeSample(DFD, 0, 0,
  234. 9, 0,
  235. 1, 1, s_UNORM);
  236. KHR_DFDSETSVAL((DFD+1), 0, SAMPLEUPPER, 8448);
  237. writeSample(DFD, 1, 0 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
  238. 5, 27,
  239. 1, 1, s_UNORM);
  240. KHR_DFDSETSVAL((DFD+1), 1, SAMPLELOWER, 15);
  241. KHR_DFDSETSVAL((DFD+1), 1, SAMPLEUPPER, 31);
  242. writeSample(DFD, 2, 1,
  243. 9, 9,
  244. 1, 1, s_UNORM);
  245. KHR_DFDSETSVAL((DFD+1), 2, SAMPLEUPPER, 8448);
  246. writeSample(DFD, 3, 1 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
  247. 5, 27,
  248. 1, 1, s_UNORM);
  249. KHR_DFDSETSVAL((DFD+1), 3, SAMPLELOWER, 15);
  250. KHR_DFDSETSVAL((DFD+1), 3, SAMPLEUPPER, 31);
  251. writeSample(DFD, 4, 2,
  252. 9, 18,
  253. 1, 1, s_UNORM);
  254. KHR_DFDSETSVAL((DFD+1), 4, SAMPLEUPPER, 8448);
  255. writeSample(DFD, 5, 2 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
  256. 5, 27,
  257. 1, 1, s_UNORM);
  258. KHR_DFDSETSVAL((DFD+1), 5, SAMPLELOWER, 15);
  259. KHR_DFDSETSVAL((DFD+1), 5, SAMPLEUPPER, 31);
  260. } else if (bigEndian) {
  261. /* No packed format is larger than 32 bits. */
  262. /* No packed channel crosses more than two bytes. */
  263. int totalBits = 0;
  264. int bitChannel[32];
  265. int beChannelStart[4];
  266. int channelCounter;
  267. int bitOffset = 0;
  268. int BEMask;
  269. int numSamples = numChannels;
  270. int sampleCounter;
  271. for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
  272. beChannelStart[channelCounter] = totalBits;
  273. totalBits += bits[channelCounter];
  274. }
  275. BEMask = (totalBits - 1) & 0x18;
  276. for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
  277. bitChannel[bitOffset ^ BEMask] = channelCounter;
  278. if (((bitOffset + bits[channelCounter] - 1) & ~7) != (bitOffset & ~7)) {
  279. /* Continuation sample */
  280. bitChannel[((bitOffset + bits[channelCounter] - 1) & ~7) ^ BEMask] = channelCounter;
  281. numSamples++;
  282. }
  283. bitOffset += bits[channelCounter];
  284. }
  285. DFD = writeHeader(numSamples, totalBits >> 3, suffix, i_COLOR);
  286. sampleCounter = 0;
  287. for (bitOffset = 0; bitOffset < totalBits;) {
  288. if (bitChannel[bitOffset] == -1) {
  289. /* Done this bit, so this is the lower half of something. */
  290. /* We must therefore jump to the end of the byte and continue. */
  291. bitOffset = (bitOffset + 8) & ~7;
  292. } else {
  293. /* Start of a channel? */
  294. int thisChannel = bitChannel[bitOffset];
  295. if ((beChannelStart[thisChannel] ^ BEMask) == bitOffset) {
  296. /* Must be just one sample if we hit it first. */
  297. writeSample(DFD, sampleCounter++, channels[thisChannel],
  298. bits[thisChannel], bitOffset,
  299. 1, 1, suffix);
  300. bitOffset += bits[thisChannel];
  301. } else {
  302. /* Two samples. Move to the end of the first one we hit when we're done. */
  303. int firstSampleBits = 8 - (beChannelStart[thisChannel] & 0x7); /* Rest of the byte */
  304. int secondSampleBits = bits[thisChannel] - firstSampleBits; /* Rest of the bits */
  305. writeSample(DFD, sampleCounter++, channels[thisChannel],
  306. firstSampleBits, beChannelStart[thisChannel] ^ BEMask,
  307. 0, 1, suffix);
  308. /* Mark that we've already handled this sample */
  309. bitChannel[beChannelStart[thisChannel] ^ BEMask] = -1;
  310. writeSample(DFD, sampleCounter++, channels[thisChannel],
  311. secondSampleBits, bitOffset,
  312. 1, 0, suffix);
  313. bitOffset += secondSampleBits;
  314. }
  315. }
  316. }
  317. } else { /* Little-endian */
  318. int sampleCounter;
  319. int totalBits = 0;
  320. int bitOffset = 0;
  321. for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
  322. totalBits += bits[sampleCounter];
  323. }
  324. /* One sample per channel */
  325. DFD = writeHeader(numChannels, totalBits >> 3, suffix, i_COLOR);
  326. for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
  327. writeSample(DFD, sampleCounter, channels[sampleCounter],
  328. bits[sampleCounter], bitOffset,
  329. 1, 1, suffix);
  330. bitOffset += bits[sampleCounter];
  331. }
  332. }
  333. return DFD;
  334. }
  335. static khr_df_model_e compModelMapping[] = {
  336. KHR_DF_MODEL_BC1A, /*!< BC1, aka DXT1, no alpha. */
  337. KHR_DF_MODEL_BC1A, /*!< BC1, aka DXT1, punch-through alpha. */
  338. KHR_DF_MODEL_BC2, /*!< BC2, aka DXT2 and DXT3. */
  339. KHR_DF_MODEL_BC3, /*!< BC3, aka DXT4 and DXT5. */
  340. KHR_DF_MODEL_BC4, /*!< BC4. */
  341. KHR_DF_MODEL_BC5, /*!< BC5. */
  342. KHR_DF_MODEL_BC6H, /*!< BC6h HDR format. */
  343. KHR_DF_MODEL_BC7, /*!< BC7. */
  344. KHR_DF_MODEL_ETC2, /*!< ETC2 no alpha. */
  345. KHR_DF_MODEL_ETC2, /*!< ETC2 punch-through alpha. */
  346. KHR_DF_MODEL_ETC2, /*!< ETC2 independent alpha. */
  347. KHR_DF_MODEL_ETC2, /*!< R11 ETC2 single-channel. */
  348. KHR_DF_MODEL_ETC2, /*!< R11G11 ETC2 dual-channel. */
  349. KHR_DF_MODEL_ASTC, /*!< ASTC. */
  350. KHR_DF_MODEL_ETC1S, /*!< ETC1S. */
  351. KHR_DF_MODEL_PVRTC, /*!< PVRTC(1). */
  352. KHR_DF_MODEL_PVRTC2 /*!< PVRTC2. */
  353. };
  354. static uint32_t compSampleCount[] = {
  355. 1U, /*!< BC1, aka DXT1, no alpha. */
  356. 1U, /*!< BC1, aka DXT1, punch-through alpha. */
  357. 2U, /*!< BC2, aka DXT2 and DXT3. */
  358. 2U, /*!< BC3, aka DXT4 and DXT5. */
  359. 1U, /*!< BC4. */
  360. 2U, /*!< BC5. */
  361. 1U, /*!< BC6h HDR format. */
  362. 1U, /*!< BC7. */
  363. 1U, /*!< ETC2 no alpha. */
  364. 2U, /*!< ETC2 punch-through alpha. */
  365. 2U, /*!< ETC2 independent alpha. */
  366. 1U, /*!< R11 ETC2 single-channel. */
  367. 2U, /*!< R11G11 ETC2 dual-channel. */
  368. 1U, /*!< ASTC. */
  369. 1U, /*!< ETC1S. */
  370. 1U, /*!< PVRTC. */
  371. 1U /*!< PVRTC2. */
  372. };
  373. static khr_df_model_channels_e compFirstChannel[] = {
  374. KHR_DF_CHANNEL_BC1A_COLOR, /*!< BC1, aka DXT1, no alpha. */
  375. KHR_DF_CHANNEL_BC1A_ALPHAPRESENT, /*!< BC1, aka DXT1, punch-through alpha. */
  376. KHR_DF_CHANNEL_BC2_ALPHA, /*!< BC2, aka DXT2 and DXT3. */
  377. KHR_DF_CHANNEL_BC3_ALPHA, /*!< BC3, aka DXT4 and DXT5. */
  378. KHR_DF_CHANNEL_BC4_DATA, /*!< BC4. */
  379. KHR_DF_CHANNEL_BC5_RED, /*!< BC5. */
  380. KHR_DF_CHANNEL_BC6H_COLOR, /*!< BC6h HDR format. */
  381. KHR_DF_CHANNEL_BC7_COLOR, /*!< BC7. */
  382. KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 no alpha. */
  383. KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 punch-through alpha. */
  384. KHR_DF_CHANNEL_ETC2_ALPHA, /*!< ETC2 independent alpha. */
  385. KHR_DF_CHANNEL_ETC2_RED, /*!< R11 ETC2 single-channel. */
  386. KHR_DF_CHANNEL_ETC2_RED, /*!< R11G11 ETC2 dual-channel. */
  387. KHR_DF_CHANNEL_ASTC_DATA, /*!< ASTC. */
  388. KHR_DF_CHANNEL_ETC1S_RGB, /*!< ETC1S. */
  389. KHR_DF_CHANNEL_PVRTC_COLOR, /*!< PVRTC. */
  390. KHR_DF_CHANNEL_PVRTC2_COLOR /*!< PVRTC2. */
  391. };
  392. static khr_df_model_channels_e compSecondChannel[] = {
  393. KHR_DF_CHANNEL_BC1A_COLOR, /*!< BC1, aka DXT1, no alpha. */
  394. KHR_DF_CHANNEL_BC1A_ALPHAPRESENT, /*!< BC1, aka DXT1, punch-through alpha. */
  395. KHR_DF_CHANNEL_BC2_COLOR, /*!< BC2, aka DXT2 and DXT3. */
  396. KHR_DF_CHANNEL_BC3_COLOR, /*!< BC3, aka DXT4 and DXT5. */
  397. KHR_DF_CHANNEL_BC4_DATA, /*!< BC4. */
  398. KHR_DF_CHANNEL_BC5_GREEN, /*!< BC5. */
  399. KHR_DF_CHANNEL_BC6H_COLOR, /*!< BC6h HDR format. */
  400. KHR_DF_CHANNEL_BC7_COLOR, /*!< BC7. */
  401. KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 no alpha. */
  402. KHR_DF_CHANNEL_ETC2_ALPHA, /*!< ETC2 punch-through alpha. */
  403. KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 independent alpha. */
  404. KHR_DF_CHANNEL_ETC2_RED, /*!< R11 ETC2 single-channel. */
  405. KHR_DF_CHANNEL_ETC2_GREEN, /*!< R11G11 ETC2 dual-channel. */
  406. KHR_DF_CHANNEL_ASTC_DATA, /*!< ASTC. */
  407. KHR_DF_CHANNEL_ETC1S_RGB, /*!< ETC1S. */
  408. KHR_DF_CHANNEL_PVRTC_COLOR, /*!< PVRTC. */
  409. KHR_DF_CHANNEL_PVRTC2_COLOR /*!< PVRTC2. */
  410. };
  411. static uint32_t compSecondChannelOffset[] = {
  412. 0U, /*!< BC1, aka DXT1, no alpha. */
  413. 0U, /*!< BC1, aka DXT1, punch-through alpha. */
  414. 64U, /*!< BC2, aka DXT2 and DXT3. */
  415. 64U, /*!< BC3, aka DXT4 and DXT5. */
  416. 0U, /*!< BC4. */
  417. 64U, /*!< BC5. */
  418. 0U, /*!< BC6h HDR format. */
  419. 0U, /*!< BC7. */
  420. 0U, /*!< ETC2 no alpha. */
  421. 0U, /*!< ETC2 punch-through alpha. */
  422. 64U, /*!< ETC2 independent alpha. */
  423. 0U, /*!< R11 ETC2 single-channel. */
  424. 64U, /*!< R11G11 ETC2 dual-channel. */
  425. 0U, /*!< ASTC. */
  426. 0U, /*!< ETC1S. */
  427. 0U, /*!< PVRTC. */
  428. 0U /*!< PVRTC2. */
  429. };
  430. static uint32_t compChannelBits[] = {
  431. 64U, /*!< BC1, aka DXT1, no alpha. */
  432. 64U, /*!< BC1, aka DXT1, punch-through alpha. */
  433. 64U, /*!< BC2, aka DXT2 and DXT3. */
  434. 64U, /*!< BC3, aka DXT4 and DXT5. */
  435. 64U, /*!< BC4. */
  436. 64U, /*!< BC5. */
  437. 128U, /*!< BC6h HDR format. */
  438. 128U, /*!< BC7. */
  439. 64U, /*!< ETC2 no alpha. */
  440. 64U, /*!< ETC2 punch-through alpha. */
  441. 64U, /*!< ETC2 independent alpha. */
  442. 64U, /*!< R11 ETC2 single-channel. */
  443. 64U, /*!< R11G11 ETC2 dual-channel. */
  444. 128U, /*!< ASTC. */
  445. 64U, /*!< ETC1S. */
  446. 64U, /*!< PVRTC. */
  447. 64U /*!< PVRTC2. */
  448. };
  449. static uint32_t compBytes[] = {
  450. 8U, /*!< BC1, aka DXT1, no alpha. */
  451. 8U, /*!< BC1, aka DXT1, punch-through alpha. */
  452. 16U, /*!< BC2, aka DXT2 and DXT3. */
  453. 16U, /*!< BC3, aka DXT4 and DXT5. */
  454. 8U, /*!< BC4. */
  455. 16U, /*!< BC5. */
  456. 16U, /*!< BC6h HDR format. */
  457. 16U, /*!< BC7. */
  458. 8U, /*!< ETC2 no alpha. */
  459. 8U, /*!< ETC2 punch-through alpha. */
  460. 16U, /*!< ETC2 independent alpha. */
  461. 8U, /*!< R11 ETC2 single-channel. */
  462. 16U, /*!< R11G11 ETC2 dual-channel. */
  463. 16U, /*!< ASTC. */
  464. 8U, /*!< ETC1S. */
  465. 8U, /*!< PVRTC. */
  466. 8U /*!< PVRTC2. */
  467. };
  468. /**
  469. * @~English
  470. * @brief Create a Data Format Descriptor for a compressed format.
  471. *
  472. * @param compScheme Vulkan-style compression scheme enumeration.
  473. * @param bwidth Block width in texel coordinates.
  474. * @param bheight Block height in texel coordinates.
  475. * @param bdepth Block depth in texel coordinates.
  476. * @author Mark Callow, Edgewise Consulting.
  477. * @param suffix Indicates the format suffix for the type.
  478. *
  479. * @return A data format descriptor in malloc'd data. The caller is responsible
  480. * for freeing the descriptor.
  481. **/
  482. uint32_t *createDFDCompressed(enum VkCompScheme compScheme, int bwidth, int bheight, int bdepth,
  483. enum VkSuffix suffix)
  484. {
  485. uint32_t *DFD = 0;
  486. uint32_t numSamples = compSampleCount[compScheme];
  487. uint32_t* BDFD;
  488. uint32_t *sample;
  489. uint32_t channel;
  490. // Use union to avoid type-punning complaints from gcc optimizer
  491. // with -Wall.
  492. union {
  493. uint32_t i;
  494. float f;
  495. } lower, upper;
  496. DFD = (uint32_t *) malloc(sizeof(uint32_t) *
  497. (1 + KHR_DF_WORD_SAMPLESTART +
  498. numSamples * KHR_DF_WORD_SAMPLEWORDS));
  499. BDFD = DFD+1;
  500. DFD[0] = sizeof(uint32_t) *
  501. (1 + KHR_DF_WORD_SAMPLESTART +
  502. numSamples * KHR_DF_WORD_SAMPLEWORDS);
  503. BDFD[KHR_DF_WORD_VENDORID] =
  504. (KHR_DF_VENDORID_KHRONOS << KHR_DF_SHIFT_VENDORID) |
  505. (KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT << KHR_DF_SHIFT_DESCRIPTORTYPE);
  506. BDFD[KHR_DF_WORD_VERSIONNUMBER] =
  507. (KHR_DF_VERSIONNUMBER_LATEST << KHR_DF_SHIFT_VERSIONNUMBER) |
  508. (((uint32_t)sizeof(uint32_t) *
  509. (KHR_DF_WORD_SAMPLESTART +
  510. numSamples * KHR_DF_WORD_SAMPLEWORDS)
  511. << KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE));
  512. BDFD[KHR_DF_WORD_MODEL] =
  513. ((compModelMapping[compScheme] << KHR_DF_SHIFT_MODEL) |
  514. (KHR_DF_PRIMARIES_BT709 << KHR_DF_SHIFT_PRIMARIES) | /* Assumed */
  515. (KHR_DF_FLAG_ALPHA_STRAIGHT << KHR_DF_SHIFT_FLAGS));
  516. if (suffix == s_SRGB) {
  517. BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_SRGB << KHR_DF_SHIFT_TRANSFER;
  518. } else {
  519. BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_LINEAR << KHR_DF_SHIFT_TRANSFER;
  520. }
  521. BDFD[KHR_DF_WORD_TEXELBLOCKDIMENSION0] =
  522. (bwidth - 1) | ((bheight - 1) << KHR_DF_SHIFT_TEXELBLOCKDIMENSION1) | ((bdepth - 1) << KHR_DF_SHIFT_TEXELBLOCKDIMENSION2);
  523. /* bytesPlane0 = bytes, bytesPlane3..1 = 0 */
  524. BDFD[KHR_DF_WORD_BYTESPLANE0] = compBytes[compScheme];
  525. BDFD[KHR_DF_WORD_BYTESPLANE4] = 0; /* bytesPlane7..5 = 0 */
  526. sample = BDFD + KHR_DF_WORD_SAMPLESTART;
  527. channel = compFirstChannel[compScheme];
  528. channel = setChannelFlags(channel, suffix);
  529. sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
  530. (0 << KHR_DF_SAMPLESHIFT_BITOFFSET) |
  531. ((compChannelBits[compScheme] - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
  532. (channel << KHR_DF_SAMPLESHIFT_CHANNELID);
  533. sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
  534. switch (suffix) {
  535. case s_UNORM:
  536. case s_SRGB:
  537. default:
  538. upper.i = 0xFFFFFFFFU;
  539. lower.i = 0U;
  540. break;
  541. case s_SNORM:
  542. upper.i = 0x7FFFFFFF;
  543. lower.i = ~upper.i;
  544. break;
  545. case s_USCALED:
  546. case s_UINT:
  547. upper.i = 1U;
  548. lower.i = 0U;
  549. break;
  550. case s_SSCALED:
  551. case s_SINT:
  552. upper.i = 1U;
  553. lower.i = ~0U;
  554. break;
  555. case s_SFLOAT:
  556. upper.f = 1.0f;
  557. lower.f = -1.0f;
  558. break;
  559. case s_UFLOAT:
  560. upper.f = 1.0f;
  561. lower.f = 0.0f;
  562. break;
  563. }
  564. sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
  565. sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
  566. if (compSampleCount[compScheme] > 1) {
  567. sample += KHR_DF_WORD_SAMPLEWORDS;
  568. channel = compSecondChannel[compScheme];
  569. channel = setChannelFlags(channel, suffix);
  570. sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
  571. (compSecondChannelOffset[compScheme] << KHR_DF_SAMPLESHIFT_BITOFFSET) |
  572. ((compChannelBits[compScheme] - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
  573. (channel << KHR_DF_SAMPLESHIFT_CHANNELID);
  574. sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
  575. sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
  576. sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
  577. }
  578. return DFD;
  579. }
  580. /**
  581. * @~English
  582. * @brief Create a Data Format Descriptor for a depth-stencil format.
  583. *
  584. * @param depthBits The numeber of bits in the depth channel.
  585. * @param stencilBits The numeber of bits in the stencil channel.
  586. * @param sizeBytes The total byte size of the texel.
  587. *
  588. * @return A data format descriptor in malloc'd data. The caller is responsible
  589. * for freeing the descriptor.
  590. **/
  591. uint32_t *createDFDDepthStencil(int depthBits,
  592. int stencilBits,
  593. int sizeBytes)
  594. {
  595. /* N.B. Little-endian is assumed. */
  596. uint32_t *DFD = 0;
  597. DFD = writeHeader((depthBits > 0) + (stencilBits > 0),
  598. sizeBytes, s_UNORM, i_NON_COLOR);
  599. if (depthBits == 32) {
  600. writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_DEPTH,
  601. 32, 0,
  602. 1, 1, s_SFLOAT);
  603. } else if (depthBits > 0) {
  604. writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_DEPTH,
  605. depthBits, 0,
  606. 1, 1, s_UNORM);
  607. }
  608. if (stencilBits > 0) {
  609. if (depthBits > 0) {
  610. writeSample(DFD, 1, KHR_DF_CHANNEL_RGBSDA_STENCIL,
  611. stencilBits, depthBits,
  612. 1, 1, s_UINT);
  613. } else {
  614. writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_STENCIL,
  615. stencilBits, 0,
  616. 1, 1, s_UINT);
  617. }
  618. }
  619. return DFD;
  620. }