WebGPUTextureUtils.js 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504
  1. import {
  2. GPUTextureFormat, GPUAddressMode, GPUFilterMode, GPUTextureDimension, GPUFeatureName, GPUTextureViewDimension
  3. } from './WebGPUConstants.js';
  4. import { ColorManagement } from '../../../math/ColorManagement.js';
  5. import WebGPUTexturePassUtils from './WebGPUTexturePassUtils.js';
  6. import {
  7. ByteType, ShortType,
  8. NearestFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter,
  9. RepeatWrapping, MirroredRepeatWrapping,
  10. RGB_ETC2_Format, RGBA_ETC2_EAC_Format,
  11. RGBAFormat, RGBFormat, RedFormat, RGFormat, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, UnsignedByteType, FloatType, HalfFloatType, SRGBTransfer, DepthFormat, DepthStencilFormat,
  12. RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format,
  13. RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, UnsignedIntType, UnsignedShortType, UnsignedInt248Type, UnsignedInt5999Type,
  14. NeverCompare, AlwaysCompare, LessCompare, LessEqualCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare, IntType, RedIntegerFormat, RGIntegerFormat, RGBAIntegerFormat,
  15. UnsignedInt101111Type, RGBA_BPTC_Format, RGB_ETC1_Format, RGB_S3TC_DXT1_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format
  16. } from '../../../constants.js';
  17. import { CubeTexture } from '../../../textures/CubeTexture.js';
  18. import { DepthTexture } from '../../../textures/DepthTexture.js';
  19. import { Texture } from '../../../textures/Texture.js';
  20. const _compareToWebGPU = {
  21. [ NeverCompare ]: 'never',
  22. [ LessCompare ]: 'less',
  23. [ EqualCompare ]: 'equal',
  24. [ LessEqualCompare ]: 'less-equal',
  25. [ GreaterCompare ]: 'greater',
  26. [ GreaterEqualCompare ]: 'greater-equal',
  27. [ AlwaysCompare ]: 'always',
  28. [ NotEqualCompare ]: 'not-equal'
  29. };
  30. const _flipMap = [ 0, 1, 3, 2, 4, 5 ];
  31. /**
  32. * A WebGPU backend utility module for managing textures.
  33. *
  34. * @private
  35. */
  36. class WebGPUTextureUtils {
  37. /**
  38. * Constructs a new utility object.
  39. *
  40. * @param {WebGPUBackend} backend - The WebGPU backend.
  41. */
  42. constructor( backend ) {
  43. /**
  44. * A reference to the WebGPU backend.
  45. *
  46. * @type {WebGPUBackend}
  47. */
  48. this.backend = backend;
  49. /**
  50. * A reference to the pass utils.
  51. *
  52. * @type {?WebGPUTexturePassUtils}
  53. * @default null
  54. */
  55. this._passUtils = null;
  56. /**
  57. * A dictionary for managing default textures. The key
  58. * is the texture format, the value the texture object.
  59. *
  60. * @type {Object<string,Texture>}
  61. */
  62. this.defaultTexture = {};
  63. /**
  64. * A dictionary for managing default cube textures. The key
  65. * is the texture format, the value the texture object.
  66. *
  67. * @type {Object<string,CubeTexture>}
  68. */
  69. this.defaultCubeTexture = {};
  70. /**
  71. * A default video frame.
  72. *
  73. * @type {?VideoFrame}
  74. * @default null
  75. */
  76. this.defaultVideoFrame = null;
  77. /**
  78. * Represents the color attachment of the default framebuffer.
  79. *
  80. * @type {?GPUTexture}
  81. * @default null
  82. */
  83. this.colorBuffer = null;
  84. /**
  85. * Represents the depth attachment of the default framebuffer.
  86. *
  87. * @type {DepthTexture}
  88. */
  89. this.depthTexture = new DepthTexture();
  90. this.depthTexture.name = 'depthBuffer';
  91. }
  92. /**
  93. * Creates a GPU sampler for the given texture.
  94. *
  95. * @param {Texture} texture - The texture to create the sampler for.
  96. */
  97. createSampler( texture ) {
  98. const backend = this.backend;
  99. const device = backend.device;
  100. const textureGPU = backend.get( texture );
  101. const samplerDescriptorGPU = {
  102. addressModeU: this._convertAddressMode( texture.wrapS ),
  103. addressModeV: this._convertAddressMode( texture.wrapT ),
  104. addressModeW: this._convertAddressMode( texture.wrapR ),
  105. magFilter: this._convertFilterMode( texture.magFilter ),
  106. minFilter: this._convertFilterMode( texture.minFilter ),
  107. mipmapFilter: this._convertFilterMode( texture.minFilter ),
  108. maxAnisotropy: 1
  109. };
  110. // anisotropy can only be used when all filter modes are set to linear.
  111. if ( samplerDescriptorGPU.magFilter === GPUFilterMode.Linear && samplerDescriptorGPU.minFilter === GPUFilterMode.Linear && samplerDescriptorGPU.mipmapFilter === GPUFilterMode.Linear ) {
  112. samplerDescriptorGPU.maxAnisotropy = texture.anisotropy;
  113. }
  114. if ( texture.isDepthTexture && texture.compareFunction !== null ) {
  115. samplerDescriptorGPU.compare = _compareToWebGPU[ texture.compareFunction ];
  116. }
  117. textureGPU.sampler = device.createSampler( samplerDescriptorGPU );
  118. }
  119. /**
  120. * Creates a default texture for the given texture that can be used
  121. * as a placeholder until the actual texture is ready for usage.
  122. *
  123. * @param {Texture} texture - The texture to create a default texture for.
  124. */
  125. createDefaultTexture( texture ) {
  126. let textureGPU;
  127. const format = getFormat( texture );
  128. if ( texture.isCubeTexture ) {
  129. textureGPU = this._getDefaultCubeTextureGPU( format );
  130. } else {
  131. textureGPU = this._getDefaultTextureGPU( format );
  132. }
  133. this.backend.get( texture ).texture = textureGPU;
  134. }
  135. /**
  136. * Defines a texture on the GPU for the given texture object.
  137. *
  138. * @param {Texture} texture - The texture.
  139. * @param {Object} [options={}] - Optional configuration parameter.
  140. */
  141. createTexture( texture, options = {} ) {
  142. const backend = this.backend;
  143. const textureData = backend.get( texture );
  144. if ( textureData.initialized ) {
  145. throw new Error( 'WebGPUTextureUtils: Texture already initialized.' );
  146. }
  147. if ( texture.isExternalTexture ) {
  148. textureData.texture = texture.sourceTexture;
  149. textureData.initialized = true;
  150. return;
  151. }
  152. if ( options.needsMipmaps === undefined ) options.needsMipmaps = false;
  153. if ( options.levels === undefined ) options.levels = 1;
  154. if ( options.depth === undefined ) options.depth = 1;
  155. const { width, height, depth, levels } = options;
  156. if ( texture.isFramebufferTexture ) {
  157. if ( options.renderTarget ) {
  158. options.format = this.backend.utils.getCurrentColorFormat( options.renderTarget );
  159. } else {
  160. options.format = this.backend.utils.getPreferredCanvasFormat();
  161. }
  162. }
  163. const dimension = this._getDimension( texture );
  164. const format = texture.internalFormat || options.format || getFormat( texture, backend.device );
  165. textureData.format = format;
  166. const { samples, primarySamples, isMSAA } = backend.utils.getTextureSampleData( texture );
  167. let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC;
  168. if ( texture.isStorageTexture === true ) {
  169. usage |= GPUTextureUsage.STORAGE_BINDING;
  170. }
  171. if ( texture.isCompressedTexture !== true && texture.isCompressedArrayTexture !== true && format !== GPUTextureFormat.RGB9E5UFloat ) {
  172. usage |= GPUTextureUsage.RENDER_ATTACHMENT;
  173. }
  174. const textureDescriptorGPU = {
  175. label: texture.name,
  176. size: {
  177. width: width,
  178. height: height,
  179. depthOrArrayLayers: depth,
  180. },
  181. mipLevelCount: levels,
  182. sampleCount: primarySamples,
  183. dimension: dimension,
  184. format: format,
  185. usage: usage
  186. };
  187. // texture creation
  188. if ( format === undefined ) {
  189. console.warn( 'WebGPURenderer: Texture format not supported.' );
  190. this.createDefaultTexture( texture );
  191. return;
  192. }
  193. if ( texture.isCubeTexture ) {
  194. textureDescriptorGPU.textureBindingViewDimension = GPUTextureViewDimension.Cube;
  195. }
  196. textureData.texture = backend.device.createTexture( textureDescriptorGPU );
  197. if ( isMSAA ) {
  198. const msaaTextureDescriptorGPU = Object.assign( {}, textureDescriptorGPU );
  199. msaaTextureDescriptorGPU.label = msaaTextureDescriptorGPU.label + '-msaa';
  200. msaaTextureDescriptorGPU.sampleCount = samples;
  201. msaaTextureDescriptorGPU.mipLevelCount = 1; // See https://www.w3.org/TR/webgpu/#texture-creation
  202. textureData.msaaTexture = backend.device.createTexture( msaaTextureDescriptorGPU );
  203. }
  204. textureData.initialized = true;
  205. textureData.textureDescriptorGPU = textureDescriptorGPU;
  206. }
  207. /**
  208. * Destroys the GPU data for the given texture object.
  209. *
  210. * @param {Texture} texture - The texture.
  211. */
  212. destroyTexture( texture ) {
  213. const backend = this.backend;
  214. const textureData = backend.get( texture );
  215. if ( textureData.texture !== undefined ) textureData.texture.destroy();
  216. if ( textureData.msaaTexture !== undefined ) textureData.msaaTexture.destroy();
  217. backend.delete( texture );
  218. }
  219. /**
  220. * Destroys the GPU sampler for the given texture.
  221. *
  222. * @param {Texture} texture - The texture to destroy the sampler for.
  223. */
  224. destroySampler( texture ) {
  225. const backend = this.backend;
  226. const textureData = backend.get( texture );
  227. delete textureData.sampler;
  228. }
  229. /**
  230. * Generates mipmaps for the given texture.
  231. *
  232. * @param {Texture} texture - The texture.
  233. */
  234. generateMipmaps( texture ) {
  235. const textureData = this.backend.get( texture );
  236. if ( texture.isCubeTexture ) {
  237. for ( let i = 0; i < 6; i ++ ) {
  238. this._generateMipmaps( textureData.texture, textureData.textureDescriptorGPU, i );
  239. }
  240. } else {
  241. const depth = texture.image.depth || 1;
  242. for ( let i = 0; i < depth; i ++ ) {
  243. this._generateMipmaps( textureData.texture, textureData.textureDescriptorGPU, i );
  244. }
  245. }
  246. }
  247. /**
  248. * Returns the color buffer representing the color
  249. * attachment of the default framebuffer.
  250. *
  251. * @return {GPUTexture} The color buffer.
  252. */
  253. getColorBuffer() {
  254. if ( this.colorBuffer ) this.colorBuffer.destroy();
  255. const backend = this.backend;
  256. const { width, height } = backend.getDrawingBufferSize();
  257. this.colorBuffer = backend.device.createTexture( {
  258. label: 'colorBuffer',
  259. size: {
  260. width: width,
  261. height: height,
  262. depthOrArrayLayers: 1
  263. },
  264. sampleCount: backend.utils.getSampleCount( backend.renderer.samples ),
  265. format: backend.utils.getPreferredCanvasFormat(),
  266. usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC
  267. } );
  268. return this.colorBuffer;
  269. }
  270. /**
  271. * Returns the depth buffer representing the depth
  272. * attachment of the default framebuffer.
  273. *
  274. * @param {boolean} [depth=true] - Whether depth is enabled or not.
  275. * @param {boolean} [stencil=false] - Whether stencil is enabled or not.
  276. * @return {GPUTexture} The depth buffer.
  277. */
  278. getDepthBuffer( depth = true, stencil = false ) {
  279. const backend = this.backend;
  280. const { width, height } = backend.getDrawingBufferSize();
  281. const depthTexture = this.depthTexture;
  282. const depthTextureGPU = backend.get( depthTexture ).texture;
  283. let format, type;
  284. if ( stencil ) {
  285. format = DepthStencilFormat;
  286. type = UnsignedInt248Type;
  287. } else if ( depth ) {
  288. format = DepthFormat;
  289. type = UnsignedIntType;
  290. }
  291. if ( depthTextureGPU !== undefined ) {
  292. if ( depthTexture.image.width === width && depthTexture.image.height === height && depthTexture.format === format && depthTexture.type === type ) {
  293. return depthTextureGPU;
  294. }
  295. this.destroyTexture( depthTexture );
  296. }
  297. depthTexture.name = 'depthBuffer';
  298. depthTexture.format = format;
  299. depthTexture.type = type;
  300. depthTexture.image.width = width;
  301. depthTexture.image.height = height;
  302. this.createTexture( depthTexture, { width, height } );
  303. return backend.get( depthTexture ).texture;
  304. }
  305. /**
  306. * Uploads the updated texture data to the GPU.
  307. *
  308. * @param {Texture} texture - The texture.
  309. * @param {Object} [options={}] - Optional configuration parameter.
  310. */
  311. updateTexture( texture, options ) {
  312. const textureData = this.backend.get( texture );
  313. const mipmaps = texture.mipmaps;
  314. const { textureDescriptorGPU } = textureData;
  315. if ( texture.isRenderTargetTexture || ( textureDescriptorGPU === undefined /* unsupported texture format */ ) )
  316. return;
  317. // transfer texture data
  318. if ( texture.isDataTexture ) {
  319. if ( mipmaps.length > 0 ) {
  320. for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
  321. const mipmap = mipmaps[ i ];
  322. this._copyBufferToTexture( mipmap, textureData.texture, textureDescriptorGPU, 0, texture.flipY, 0, i );
  323. }
  324. } else {
  325. this._copyBufferToTexture( options.image, textureData.texture, textureDescriptorGPU, 0, texture.flipY );
  326. }
  327. } else if ( texture.isArrayTexture || texture.isDataArrayTexture || texture.isData3DTexture ) {
  328. for ( let i = 0; i < options.image.depth; i ++ ) {
  329. this._copyBufferToTexture( options.image, textureData.texture, textureDescriptorGPU, i, texture.flipY, i );
  330. }
  331. } else if ( texture.isCompressedTexture || texture.isCompressedArrayTexture ) {
  332. this._copyCompressedBufferToTexture( texture.mipmaps, textureData.texture, textureDescriptorGPU );
  333. } else if ( texture.isCubeTexture ) {
  334. this._copyCubeMapToTexture( texture, textureData.texture, textureDescriptorGPU );
  335. } else {
  336. if ( mipmaps.length > 0 ) {
  337. for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
  338. const mipmap = mipmaps[ i ];
  339. this._copyImageToTexture( mipmap, textureData.texture, textureDescriptorGPU, 0, texture.flipY, texture.premultiplyAlpha, i );
  340. }
  341. } else {
  342. this._copyImageToTexture( options.image, textureData.texture, textureDescriptorGPU, 0, texture.flipY, texture.premultiplyAlpha );
  343. }
  344. }
  345. //
  346. textureData.version = texture.version;
  347. }
  348. /**
  349. * Returns texture data as a typed array.
  350. *
  351. * @async
  352. * @param {Texture} texture - The texture to copy.
  353. * @param {number} x - The x coordinate of the copy origin.
  354. * @param {number} y - The y coordinate of the copy origin.
  355. * @param {number} width - The width of the copy.
  356. * @param {number} height - The height of the copy.
  357. * @param {number} faceIndex - The face index.
  358. * @return {Promise<TypedArray>} A Promise that resolves with a typed array when the copy operation has finished.
  359. */
  360. async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) {
  361. const device = this.backend.device;
  362. const textureData = this.backend.get( texture );
  363. const textureGPU = textureData.texture;
  364. const format = textureData.textureDescriptorGPU.format;
  365. const bytesPerTexel = this._getBytesPerTexel( format );
  366. let bytesPerRow = width * bytesPerTexel;
  367. bytesPerRow = Math.ceil( bytesPerRow / 256 ) * 256; // Align to 256 bytes
  368. const readBuffer = device.createBuffer(
  369. {
  370. size: ( ( height - 1 ) * bytesPerRow ) + ( width * bytesPerTexel ), // see https://github.com/mrdoob/three.js/issues/31658#issuecomment-3229442010
  371. usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
  372. }
  373. );
  374. const encoder = device.createCommandEncoder();
  375. encoder.copyTextureToBuffer(
  376. {
  377. texture: textureGPU,
  378. origin: { x, y, z: faceIndex },
  379. },
  380. {
  381. buffer: readBuffer,
  382. bytesPerRow: bytesPerRow
  383. },
  384. {
  385. width: width,
  386. height: height
  387. }
  388. );
  389. const typedArrayType = this._getTypedArrayType( format );
  390. device.queue.submit( [ encoder.finish() ] );
  391. await readBuffer.mapAsync( GPUMapMode.READ );
  392. const buffer = readBuffer.getMappedRange();
  393. return new typedArrayType( buffer );
  394. }
  395. /**
  396. * Returns the default GPU texture for the given format.
  397. *
  398. * @private
  399. * @param {string} format - The GPU format.
  400. * @return {GPUTexture} The GPU texture.
  401. */
  402. _getDefaultTextureGPU( format ) {
  403. let defaultTexture = this.defaultTexture[ format ];
  404. if ( defaultTexture === undefined ) {
  405. const texture = new Texture();
  406. texture.minFilter = NearestFilter;
  407. texture.magFilter = NearestFilter;
  408. this.createTexture( texture, { width: 1, height: 1, format } );
  409. this.defaultTexture[ format ] = defaultTexture = texture;
  410. }
  411. return this.backend.get( defaultTexture ).texture;
  412. }
  413. /**
  414. * Returns the default GPU cube texture for the given format.
  415. *
  416. * @private
  417. * @param {string} format - The GPU format.
  418. * @return {GPUTexture} The GPU texture.
  419. */
  420. _getDefaultCubeTextureGPU( format ) {
  421. let defaultCubeTexture = this.defaultTexture[ format ];
  422. if ( defaultCubeTexture === undefined ) {
  423. const texture = new CubeTexture();
  424. texture.minFilter = NearestFilter;
  425. texture.magFilter = NearestFilter;
  426. this.createTexture( texture, { width: 1, height: 1, depth: 6 } );
  427. this.defaultCubeTexture[ format ] = defaultCubeTexture = texture;
  428. }
  429. return this.backend.get( defaultCubeTexture ).texture;
  430. }
  431. /**
  432. * Uploads cube texture image data to the GPU memory.
  433. *
  434. * @private
  435. * @param {CubeTexture} texture - The cube texture.
  436. * @param {GPUTexture} textureGPU - The GPU texture.
  437. * @param {Object} textureDescriptorGPU - The GPU texture descriptor.
  438. */
  439. _copyCubeMapToTexture( texture, textureGPU, textureDescriptorGPU ) {
  440. const images = texture.images;
  441. const mipmaps = texture.mipmaps;
  442. for ( let i = 0; i < 6; i ++ ) {
  443. const image = images[ i ];
  444. const flipIndex = texture.flipY === true ? _flipMap[ i ] : i;
  445. if ( image.isDataTexture ) {
  446. this._copyBufferToTexture( image.image, textureGPU, textureDescriptorGPU, flipIndex, texture.flipY );
  447. } else {
  448. this._copyImageToTexture( image, textureGPU, textureDescriptorGPU, flipIndex, texture.flipY, texture.premultiplyAlpha );
  449. }
  450. for ( let j = 0; j < mipmaps.length; j ++ ) {
  451. const mipmap = mipmaps[ j ];
  452. const image = mipmap.images[ i ];
  453. if ( image.isDataTexture ) {
  454. this._copyBufferToTexture( image.image, textureGPU, textureDescriptorGPU, flipIndex, texture.flipY, 0, j + 1 );
  455. } else {
  456. this._copyImageToTexture( image, textureGPU, textureDescriptorGPU, flipIndex, texture.flipY, texture.premultiplyAlpha, j + 1 );
  457. }
  458. }
  459. }
  460. }
  461. /**
  462. * Uploads texture image data to the GPU memory.
  463. *
  464. * @private
  465. * @param {HTMLImageElement|ImageBitmap|HTMLCanvasElement} image - The image data.
  466. * @param {GPUTexture} textureGPU - The GPU texture.
  467. * @param {Object} textureDescriptorGPU - The GPU texture descriptor.
  468. * @param {number} originDepth - The origin depth.
  469. * @param {boolean} flipY - Whether to flip texture data along their vertical axis or not.
  470. * @param {boolean} premultiplyAlpha - Whether the texture should have its RGB channels premultiplied by the alpha channel or not.
  471. * @param {number} [mipLevel=0] - The mip level where the data should be copied to.
  472. */
  473. _copyImageToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY, premultiplyAlpha, mipLevel = 0 ) {
  474. const device = this.backend.device;
  475. const width = ( mipLevel > 0 ) ? image.width : textureDescriptorGPU.size.width;
  476. const height = ( mipLevel > 0 ) ? image.height : textureDescriptorGPU.size.height;
  477. device.queue.copyExternalImageToTexture(
  478. {
  479. source: image,
  480. flipY: flipY
  481. }, {
  482. texture: textureGPU,
  483. mipLevel: mipLevel,
  484. origin: { x: 0, y: 0, z: originDepth },
  485. premultipliedAlpha: premultiplyAlpha
  486. }, {
  487. width: width,
  488. height: height,
  489. depthOrArrayLayers: 1
  490. }
  491. );
  492. }
  493. /**
  494. * Returns the pass utils singleton.
  495. *
  496. * @private
  497. * @return {WebGPUTexturePassUtils} The utils instance.
  498. */
  499. _getPassUtils() {
  500. let passUtils = this._passUtils;
  501. if ( passUtils === null ) {
  502. this._passUtils = passUtils = new WebGPUTexturePassUtils( this.backend.device );
  503. }
  504. return passUtils;
  505. }
  506. /**
  507. * Generates mipmaps for the given GPU texture.
  508. *
  509. * @private
  510. * @param {GPUTexture} textureGPU - The GPU texture object.
  511. * @param {Object} textureDescriptorGPU - The texture descriptor.
  512. * @param {number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view.
  513. */
  514. _generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer = 0 ) {
  515. this._getPassUtils().generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer );
  516. }
  517. /**
  518. * Flip the contents of the given GPU texture along its vertical axis.
  519. *
  520. * @private
  521. * @param {GPUTexture} textureGPU - The GPU texture object.
  522. * @param {Object} textureDescriptorGPU - The texture descriptor.
  523. * @param {number} [originDepth=0] - The origin depth.
  524. */
  525. _flipY( textureGPU, textureDescriptorGPU, originDepth = 0 ) {
  526. this._getPassUtils().flipY( textureGPU, textureDescriptorGPU, originDepth );
  527. }
  528. /**
  529. * Uploads texture buffer data to the GPU memory.
  530. *
  531. * @private
  532. * @param {Object} image - An object defining the image buffer data.
  533. * @param {GPUTexture} textureGPU - The GPU texture.
  534. * @param {Object} textureDescriptorGPU - The GPU texture descriptor.
  535. * @param {number} originDepth - The origin depth.
  536. * @param {boolean} flipY - Whether to flip texture data along their vertical axis or not.
  537. * @param {number} [depth=0] - The depth offset when copying array or 3D texture data.
  538. * @param {number} [mipLevel=0] - The mip level where the data should be copied to.
  539. */
  540. _copyBufferToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY, depth = 0, mipLevel = 0 ) {
  541. // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture()
  542. // @TODO: Consider to support valid buffer layouts with other formats like RGB
  543. const device = this.backend.device;
  544. const data = image.data;
  545. const bytesPerTexel = this._getBytesPerTexel( textureDescriptorGPU.format );
  546. const bytesPerRow = image.width * bytesPerTexel;
  547. device.queue.writeTexture(
  548. {
  549. texture: textureGPU,
  550. mipLevel: mipLevel,
  551. origin: { x: 0, y: 0, z: originDepth }
  552. },
  553. data,
  554. {
  555. offset: image.width * image.height * bytesPerTexel * depth,
  556. bytesPerRow
  557. },
  558. {
  559. width: image.width,
  560. height: image.height,
  561. depthOrArrayLayers: 1
  562. } );
  563. if ( flipY === true ) {
  564. this._flipY( textureGPU, textureDescriptorGPU, originDepth );
  565. }
  566. }
  567. /**
  568. * Uploads compressed texture data to the GPU memory.
  569. *
  570. * @private
  571. * @param {Array<Object>} mipmaps - An array with mipmap data.
  572. * @param {GPUTexture} textureGPU - The GPU texture.
  573. * @param {Object} textureDescriptorGPU - The GPU texture descriptor.
  574. */
  575. _copyCompressedBufferToTexture( mipmaps, textureGPU, textureDescriptorGPU ) {
  576. // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture()
  577. const device = this.backend.device;
  578. const blockData = this._getBlockData( textureDescriptorGPU.format );
  579. const isArrayTexture = textureDescriptorGPU.size.depthOrArrayLayers > 1;
  580. for ( let i = 0; i < mipmaps.length; i ++ ) {
  581. const mipmap = mipmaps[ i ];
  582. const width = mipmap.width;
  583. const height = mipmap.height;
  584. const depth = isArrayTexture ? textureDescriptorGPU.size.depthOrArrayLayers : 1;
  585. const bytesPerRow = Math.ceil( width / blockData.width ) * blockData.byteLength;
  586. const bytesPerImage = bytesPerRow * Math.ceil( height / blockData.height );
  587. for ( let j = 0; j < depth; j ++ ) {
  588. device.queue.writeTexture(
  589. {
  590. texture: textureGPU,
  591. mipLevel: i,
  592. origin: { x: 0, y: 0, z: j }
  593. },
  594. mipmap.data,
  595. {
  596. offset: j * bytesPerImage,
  597. bytesPerRow,
  598. rowsPerImage: Math.ceil( height / blockData.height )
  599. },
  600. {
  601. width: Math.ceil( width / blockData.width ) * blockData.width,
  602. height: Math.ceil( height / blockData.height ) * blockData.height,
  603. depthOrArrayLayers: 1
  604. }
  605. );
  606. }
  607. }
  608. }
  609. /**
  610. * This method is only relevant for compressed texture formats. It returns a block
  611. * data descriptor for the given GPU compressed texture format.
  612. *
  613. * @private
  614. * @param {string} format - The GPU compressed texture format.
  615. * @return {Object} The block data descriptor.
  616. */
  617. _getBlockData( format ) {
  618. if ( format === GPUTextureFormat.BC1RGBAUnorm || format === GPUTextureFormat.BC1RGBAUnormSRGB ) return { byteLength: 8, width: 4, height: 4 }; // DXT1
  619. if ( format === GPUTextureFormat.BC2RGBAUnorm || format === GPUTextureFormat.BC2RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT3
  620. if ( format === GPUTextureFormat.BC3RGBAUnorm || format === GPUTextureFormat.BC3RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT5
  621. if ( format === GPUTextureFormat.BC4RUnorm || format === GPUTextureFormat.BC4RSnorm ) return { byteLength: 8, width: 4, height: 4 }; // RGTC1
  622. if ( format === GPUTextureFormat.BC5RGUnorm || format === GPUTextureFormat.BC5RGSnorm ) return { byteLength: 16, width: 4, height: 4 }; // RGTC2
  623. if ( format === GPUTextureFormat.BC6HRGBUFloat || format === GPUTextureFormat.BC6HRGBFloat ) return { byteLength: 16, width: 4, height: 4 }; // BPTC (float)
  624. if ( format === GPUTextureFormat.BC7RGBAUnorm || format === GPUTextureFormat.BC7RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // BPTC (unorm)
  625. if ( format === GPUTextureFormat.ETC2RGB8Unorm || format === GPUTextureFormat.ETC2RGB8UnormSRGB ) return { byteLength: 8, width: 4, height: 4 };
  626. if ( format === GPUTextureFormat.ETC2RGB8A1Unorm || format === GPUTextureFormat.ETC2RGB8A1UnormSRGB ) return { byteLength: 8, width: 4, height: 4 };
  627. if ( format === GPUTextureFormat.ETC2RGBA8Unorm || format === GPUTextureFormat.ETC2RGBA8UnormSRGB ) return { byteLength: 16, width: 4, height: 4 };
  628. if ( format === GPUTextureFormat.EACR11Unorm ) return { byteLength: 8, width: 4, height: 4 };
  629. if ( format === GPUTextureFormat.EACR11Snorm ) return { byteLength: 8, width: 4, height: 4 };
  630. if ( format === GPUTextureFormat.EACRG11Unorm ) return { byteLength: 16, width: 4, height: 4 };
  631. if ( format === GPUTextureFormat.EACRG11Snorm ) return { byteLength: 16, width: 4, height: 4 };
  632. if ( format === GPUTextureFormat.ASTC4x4Unorm || format === GPUTextureFormat.ASTC4x4UnormSRGB ) return { byteLength: 16, width: 4, height: 4 };
  633. if ( format === GPUTextureFormat.ASTC5x4Unorm || format === GPUTextureFormat.ASTC5x4UnormSRGB ) return { byteLength: 16, width: 5, height: 4 };
  634. if ( format === GPUTextureFormat.ASTC5x5Unorm || format === GPUTextureFormat.ASTC5x5UnormSRGB ) return { byteLength: 16, width: 5, height: 5 };
  635. if ( format === GPUTextureFormat.ASTC6x5Unorm || format === GPUTextureFormat.ASTC6x5UnormSRGB ) return { byteLength: 16, width: 6, height: 5 };
  636. if ( format === GPUTextureFormat.ASTC6x6Unorm || format === GPUTextureFormat.ASTC6x6UnormSRGB ) return { byteLength: 16, width: 6, height: 6 };
  637. if ( format === GPUTextureFormat.ASTC8x5Unorm || format === GPUTextureFormat.ASTC8x5UnormSRGB ) return { byteLength: 16, width: 8, height: 5 };
  638. if ( format === GPUTextureFormat.ASTC8x6Unorm || format === GPUTextureFormat.ASTC8x6UnormSRGB ) return { byteLength: 16, width: 8, height: 6 };
  639. if ( format === GPUTextureFormat.ASTC8x8Unorm || format === GPUTextureFormat.ASTC8x8UnormSRGB ) return { byteLength: 16, width: 8, height: 8 };
  640. if ( format === GPUTextureFormat.ASTC10x5Unorm || format === GPUTextureFormat.ASTC10x5UnormSRGB ) return { byteLength: 16, width: 10, height: 5 };
  641. if ( format === GPUTextureFormat.ASTC10x6Unorm || format === GPUTextureFormat.ASTC10x6UnormSRGB ) return { byteLength: 16, width: 10, height: 6 };
  642. if ( format === GPUTextureFormat.ASTC10x8Unorm || format === GPUTextureFormat.ASTC10x8UnormSRGB ) return { byteLength: 16, width: 10, height: 8 };
  643. if ( format === GPUTextureFormat.ASTC10x10Unorm || format === GPUTextureFormat.ASTC10x10UnormSRGB ) return { byteLength: 16, width: 10, height: 10 };
  644. if ( format === GPUTextureFormat.ASTC12x10Unorm || format === GPUTextureFormat.ASTC12x10UnormSRGB ) return { byteLength: 16, width: 12, height: 10 };
  645. if ( format === GPUTextureFormat.ASTC12x12Unorm || format === GPUTextureFormat.ASTC12x12UnormSRGB ) return { byteLength: 16, width: 12, height: 12 };
  646. }
  647. /**
  648. * Converts the three.js uv wrapping constants to GPU address mode constants.
  649. *
  650. * @private
  651. * @param {number} value - The three.js constant defining a uv wrapping mode.
  652. * @return {string} The GPU address mode.
  653. */
  654. _convertAddressMode( value ) {
  655. let addressMode = GPUAddressMode.ClampToEdge;
  656. if ( value === RepeatWrapping ) {
  657. addressMode = GPUAddressMode.Repeat;
  658. } else if ( value === MirroredRepeatWrapping ) {
  659. addressMode = GPUAddressMode.MirrorRepeat;
  660. }
  661. return addressMode;
  662. }
  663. /**
  664. * Converts the three.js filter constants to GPU filter constants.
  665. *
  666. * @private
  667. * @param {number} value - The three.js constant defining a filter mode.
  668. * @return {string} The GPU filter mode.
  669. */
  670. _convertFilterMode( value ) {
  671. let filterMode = GPUFilterMode.Linear;
  672. if ( value === NearestFilter || value === NearestMipmapNearestFilter || value === NearestMipmapLinearFilter ) {
  673. filterMode = GPUFilterMode.Nearest;
  674. }
  675. return filterMode;
  676. }
  677. /**
  678. * Returns the bytes-per-texel value for the given GPU texture format.
  679. *
  680. * @private
  681. * @param {string} format - The GPU texture format.
  682. * @return {number} The bytes-per-texel.
  683. */
  684. _getBytesPerTexel( format ) {
  685. // 8-bit formats
  686. if ( format === GPUTextureFormat.R8Unorm ||
  687. format === GPUTextureFormat.R8Snorm ||
  688. format === GPUTextureFormat.R8Uint ||
  689. format === GPUTextureFormat.R8Sint ) return 1;
  690. // 16-bit formats
  691. if ( format === GPUTextureFormat.R16Uint ||
  692. format === GPUTextureFormat.R16Sint ||
  693. format === GPUTextureFormat.R16Float ||
  694. format === GPUTextureFormat.RG8Unorm ||
  695. format === GPUTextureFormat.RG8Snorm ||
  696. format === GPUTextureFormat.RG8Uint ||
  697. format === GPUTextureFormat.RG8Sint ) return 2;
  698. // 32-bit formats
  699. if ( format === GPUTextureFormat.R32Uint ||
  700. format === GPUTextureFormat.R32Sint ||
  701. format === GPUTextureFormat.R32Float ||
  702. format === GPUTextureFormat.RG16Uint ||
  703. format === GPUTextureFormat.RG16Sint ||
  704. format === GPUTextureFormat.RG16Float ||
  705. format === GPUTextureFormat.RGBA8Unorm ||
  706. format === GPUTextureFormat.RGBA8UnormSRGB ||
  707. format === GPUTextureFormat.RGBA8Snorm ||
  708. format === GPUTextureFormat.RGBA8Uint ||
  709. format === GPUTextureFormat.RGBA8Sint ||
  710. format === GPUTextureFormat.BGRA8Unorm ||
  711. format === GPUTextureFormat.BGRA8UnormSRGB ||
  712. // Packed 32-bit formats
  713. format === GPUTextureFormat.RGB9E5UFloat ||
  714. format === GPUTextureFormat.RGB10A2Unorm ||
  715. format === GPUTextureFormat.RG11B10UFloat ||
  716. format === GPUTextureFormat.Depth32Float ||
  717. format === GPUTextureFormat.Depth24Plus ||
  718. format === GPUTextureFormat.Depth24PlusStencil8 ||
  719. format === GPUTextureFormat.Depth32FloatStencil8 ) return 4;
  720. // 64-bit formats
  721. if ( format === GPUTextureFormat.RG32Uint ||
  722. format === GPUTextureFormat.RG32Sint ||
  723. format === GPUTextureFormat.RG32Float ||
  724. format === GPUTextureFormat.RGBA16Uint ||
  725. format === GPUTextureFormat.RGBA16Sint ||
  726. format === GPUTextureFormat.RGBA16Float ) return 8;
  727. // 128-bit formats
  728. if ( format === GPUTextureFormat.RGBA32Uint ||
  729. format === GPUTextureFormat.RGBA32Sint ||
  730. format === GPUTextureFormat.RGBA32Float ) return 16;
  731. }
  732. /**
  733. * Returns the corresponding typed array type for the given GPU texture format.
  734. *
  735. * @private
  736. * @param {string} format - The GPU texture format.
  737. * @return {TypedArray.constructor} The typed array type.
  738. */
  739. _getTypedArrayType( format ) {
  740. if ( format === GPUTextureFormat.R8Uint ) return Uint8Array;
  741. if ( format === GPUTextureFormat.R8Sint ) return Int8Array;
  742. if ( format === GPUTextureFormat.R8Unorm ) return Uint8Array;
  743. if ( format === GPUTextureFormat.R8Snorm ) return Int8Array;
  744. if ( format === GPUTextureFormat.RG8Uint ) return Uint8Array;
  745. if ( format === GPUTextureFormat.RG8Sint ) return Int8Array;
  746. if ( format === GPUTextureFormat.RG8Unorm ) return Uint8Array;
  747. if ( format === GPUTextureFormat.RG8Snorm ) return Int8Array;
  748. if ( format === GPUTextureFormat.RGBA8Uint ) return Uint8Array;
  749. if ( format === GPUTextureFormat.RGBA8Sint ) return Int8Array;
  750. if ( format === GPUTextureFormat.RGBA8Unorm || format === GPUTextureFormat.RGBA8UnormSRGB ) return Uint8Array;
  751. if ( format === GPUTextureFormat.RGBA8Snorm ) return Int8Array;
  752. if ( format === GPUTextureFormat.R16Uint ) return Uint16Array;
  753. if ( format === GPUTextureFormat.R16Sint ) return Int16Array;
  754. if ( format === GPUTextureFormat.RG16Uint ) return Uint16Array;
  755. if ( format === GPUTextureFormat.RG16Sint ) return Int16Array;
  756. if ( format === GPUTextureFormat.RGBA16Uint ) return Uint16Array;
  757. if ( format === GPUTextureFormat.RGBA16Sint ) return Int16Array;
  758. if ( format === GPUTextureFormat.R16Float ) return Uint16Array;
  759. if ( format === GPUTextureFormat.RG16Float ) return Uint16Array;
  760. if ( format === GPUTextureFormat.RGBA16Float ) return Uint16Array;
  761. if ( format === GPUTextureFormat.R32Uint ) return Uint32Array;
  762. if ( format === GPUTextureFormat.R32Sint ) return Int32Array;
  763. if ( format === GPUTextureFormat.R32Float ) return Float32Array;
  764. if ( format === GPUTextureFormat.RG32Uint ) return Uint32Array;
  765. if ( format === GPUTextureFormat.RG32Sint ) return Int32Array;
  766. if ( format === GPUTextureFormat.RG32Float ) return Float32Array;
  767. if ( format === GPUTextureFormat.RGBA32Uint ) return Uint32Array;
  768. if ( format === GPUTextureFormat.RGBA32Sint ) return Int32Array;
  769. if ( format === GPUTextureFormat.RGBA32Float ) return Float32Array;
  770. if ( format === GPUTextureFormat.BGRA8Unorm || format === GPUTextureFormat.BGRA8UnormSRGB ) return Uint8Array;
  771. if ( format === GPUTextureFormat.RGB10A2Unorm ) return Uint32Array;
  772. if ( format === GPUTextureFormat.RGB9E5UFloat ) return Uint32Array;
  773. if ( format === GPUTextureFormat.RG11B10UFloat ) return Uint32Array;
  774. if ( format === GPUTextureFormat.Depth32Float ) return Float32Array;
  775. if ( format === GPUTextureFormat.Depth24Plus ) return Uint32Array;
  776. if ( format === GPUTextureFormat.Depth24PlusStencil8 ) return Uint32Array;
  777. if ( format === GPUTextureFormat.Depth32FloatStencil8 ) return Float32Array;
  778. }
  779. /**
  780. * Returns the GPU dimensions for the given texture.
  781. *
  782. * @private
  783. * @param {Texture} texture - The texture.
  784. * @return {string} The GPU dimension.
  785. */
  786. _getDimension( texture ) {
  787. let dimension;
  788. if ( texture.is3DTexture || texture.isData3DTexture ) {
  789. dimension = GPUTextureDimension.ThreeD;
  790. } else {
  791. dimension = GPUTextureDimension.TwoD;
  792. }
  793. return dimension;
  794. }
  795. }
  796. /**
  797. * Returns the GPU format for the given texture.
  798. *
  799. * @param {Texture} texture - The texture.
  800. * @param {?GPUDevice} [device=null] - The GPU device which is used for feature detection.
  801. * It is not necessary to apply the device for most formats.
  802. * @return {string} The GPU format.
  803. */
  804. export function getFormat( texture, device = null ) {
  805. const format = texture.format;
  806. const type = texture.type;
  807. const colorSpace = texture.colorSpace;
  808. const transfer = ColorManagement.getTransfer( colorSpace );
  809. let formatGPU;
  810. if ( texture.isCompressedTexture === true || texture.isCompressedArrayTexture === true ) {
  811. switch ( format ) {
  812. case RGB_S3TC_DXT1_Format:
  813. case RGBA_S3TC_DXT1_Format:
  814. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.BC1RGBAUnormSRGB : GPUTextureFormat.BC1RGBAUnorm;
  815. break;
  816. case RGBA_S3TC_DXT3_Format:
  817. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.BC2RGBAUnormSRGB : GPUTextureFormat.BC2RGBAUnorm;
  818. break;
  819. case RGBA_S3TC_DXT5_Format:
  820. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.BC3RGBAUnormSRGB : GPUTextureFormat.BC3RGBAUnorm;
  821. break;
  822. case RED_RGTC1_Format:
  823. formatGPU = GPUTextureFormat.BC4RUnorm;
  824. break;
  825. case SIGNED_RED_RGTC1_Format:
  826. formatGPU = GPUTextureFormat.BC4RSnorm;
  827. break;
  828. case RED_GREEN_RGTC2_Format:
  829. formatGPU = GPUTextureFormat.BC5RGUnorm;
  830. break;
  831. case SIGNED_RED_GREEN_RGTC2_Format:
  832. formatGPU = GPUTextureFormat.BC5RGSnorm;
  833. break;
  834. case RGBA_BPTC_Format:
  835. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.BC7RGBAUnormSRGB : GPUTextureFormat.BC7RGBAUnorm;
  836. break;
  837. case RGB_ETC2_Format:
  838. case RGB_ETC1_Format:
  839. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ETC2RGB8UnormSRGB : GPUTextureFormat.ETC2RGB8Unorm;
  840. break;
  841. case RGBA_ETC2_EAC_Format:
  842. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ETC2RGBA8UnormSRGB : GPUTextureFormat.ETC2RGBA8Unorm;
  843. break;
  844. case RGBA_ASTC_4x4_Format:
  845. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC4x4UnormSRGB : GPUTextureFormat.ASTC4x4Unorm;
  846. break;
  847. case RGBA_ASTC_5x4_Format:
  848. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC5x4UnormSRGB : GPUTextureFormat.ASTC5x4Unorm;
  849. break;
  850. case RGBA_ASTC_5x5_Format:
  851. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC5x5UnormSRGB : GPUTextureFormat.ASTC5x5Unorm;
  852. break;
  853. case RGBA_ASTC_6x5_Format:
  854. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC6x5UnormSRGB : GPUTextureFormat.ASTC6x5Unorm;
  855. break;
  856. case RGBA_ASTC_6x6_Format:
  857. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC6x6UnormSRGB : GPUTextureFormat.ASTC6x6Unorm;
  858. break;
  859. case RGBA_ASTC_8x5_Format:
  860. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC8x5UnormSRGB : GPUTextureFormat.ASTC8x5Unorm;
  861. break;
  862. case RGBA_ASTC_8x6_Format:
  863. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC8x6UnormSRGB : GPUTextureFormat.ASTC8x6Unorm;
  864. break;
  865. case RGBA_ASTC_8x8_Format:
  866. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC8x8UnormSRGB : GPUTextureFormat.ASTC8x8Unorm;
  867. break;
  868. case RGBA_ASTC_10x5_Format:
  869. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC10x5UnormSRGB : GPUTextureFormat.ASTC10x5Unorm;
  870. break;
  871. case RGBA_ASTC_10x6_Format:
  872. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC10x6UnormSRGB : GPUTextureFormat.ASTC10x6Unorm;
  873. break;
  874. case RGBA_ASTC_10x8_Format:
  875. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC10x8UnormSRGB : GPUTextureFormat.ASTC10x8Unorm;
  876. break;
  877. case RGBA_ASTC_10x10_Format:
  878. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC10x10UnormSRGB : GPUTextureFormat.ASTC10x10Unorm;
  879. break;
  880. case RGBA_ASTC_12x10_Format:
  881. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC12x10UnormSRGB : GPUTextureFormat.ASTC12x10Unorm;
  882. break;
  883. case RGBA_ASTC_12x12_Format:
  884. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.ASTC12x12UnormSRGB : GPUTextureFormat.ASTC12x12Unorm;
  885. break;
  886. case RGBAFormat:
  887. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.RGBA8UnormSRGB : GPUTextureFormat.RGBA8Unorm;
  888. break;
  889. default:
  890. console.error( 'WebGPURenderer: Unsupported texture format.', format );
  891. }
  892. } else {
  893. switch ( format ) {
  894. case RGBAFormat:
  895. switch ( type ) {
  896. case ByteType:
  897. formatGPU = GPUTextureFormat.RGBA8Snorm;
  898. break;
  899. case ShortType:
  900. formatGPU = GPUTextureFormat.RGBA16Sint;
  901. break;
  902. case UnsignedShortType:
  903. formatGPU = GPUTextureFormat.RGBA16Uint;
  904. break;
  905. case UnsignedIntType:
  906. formatGPU = GPUTextureFormat.RGBA32Uint;
  907. break;
  908. case IntType:
  909. formatGPU = GPUTextureFormat.RGBA32Sint;
  910. break;
  911. case UnsignedByteType:
  912. formatGPU = ( transfer === SRGBTransfer ) ? GPUTextureFormat.RGBA8UnormSRGB : GPUTextureFormat.RGBA8Unorm;
  913. break;
  914. case HalfFloatType:
  915. formatGPU = GPUTextureFormat.RGBA16Float;
  916. break;
  917. case FloatType:
  918. formatGPU = GPUTextureFormat.RGBA32Float;
  919. break;
  920. default:
  921. console.error( 'WebGPURenderer: Unsupported texture type with RGBAFormat.', type );
  922. }
  923. break;
  924. case RGBFormat:
  925. switch ( type ) {
  926. case UnsignedInt5999Type:
  927. formatGPU = GPUTextureFormat.RGB9E5UFloat;
  928. break;
  929. case UnsignedInt101111Type:
  930. formatGPU = GPUTextureFormat.RG11B10UFloat;
  931. break;
  932. default:
  933. console.error( 'WebGPURenderer: Unsupported texture type with RGBFormat.', type );
  934. }
  935. break;
  936. case RedFormat:
  937. switch ( type ) {
  938. case ByteType:
  939. formatGPU = GPUTextureFormat.R8Snorm;
  940. break;
  941. case ShortType:
  942. formatGPU = GPUTextureFormat.R16Sint;
  943. break;
  944. case UnsignedShortType:
  945. formatGPU = GPUTextureFormat.R16Uint;
  946. break;
  947. case UnsignedIntType:
  948. formatGPU = GPUTextureFormat.R32Uint;
  949. break;
  950. case IntType:
  951. formatGPU = GPUTextureFormat.R32Sint;
  952. break;
  953. case UnsignedByteType:
  954. formatGPU = GPUTextureFormat.R8Unorm;
  955. break;
  956. case HalfFloatType:
  957. formatGPU = GPUTextureFormat.R16Float;
  958. break;
  959. case FloatType:
  960. formatGPU = GPUTextureFormat.R32Float;
  961. break;
  962. default:
  963. console.error( 'WebGPURenderer: Unsupported texture type with RedFormat.', type );
  964. }
  965. break;
  966. case RGFormat:
  967. switch ( type ) {
  968. case ByteType:
  969. formatGPU = GPUTextureFormat.RG8Snorm;
  970. break;
  971. case ShortType:
  972. formatGPU = GPUTextureFormat.RG16Sint;
  973. break;
  974. case UnsignedShortType:
  975. formatGPU = GPUTextureFormat.RG16Uint;
  976. break;
  977. case UnsignedIntType:
  978. formatGPU = GPUTextureFormat.RG32Uint;
  979. break;
  980. case IntType:
  981. formatGPU = GPUTextureFormat.RG32Sint;
  982. break;
  983. case UnsignedByteType:
  984. formatGPU = GPUTextureFormat.RG8Unorm;
  985. break;
  986. case HalfFloatType:
  987. formatGPU = GPUTextureFormat.RG16Float;
  988. break;
  989. case FloatType:
  990. formatGPU = GPUTextureFormat.RG32Float;
  991. break;
  992. default:
  993. console.error( 'WebGPURenderer: Unsupported texture type with RGFormat.', type );
  994. }
  995. break;
  996. case DepthFormat:
  997. switch ( type ) {
  998. case UnsignedShortType:
  999. formatGPU = GPUTextureFormat.Depth16Unorm;
  1000. break;
  1001. case UnsignedIntType:
  1002. formatGPU = GPUTextureFormat.Depth24Plus;
  1003. break;
  1004. case FloatType:
  1005. formatGPU = GPUTextureFormat.Depth32Float;
  1006. break;
  1007. default:
  1008. console.error( 'WebGPURenderer: Unsupported texture type with DepthFormat.', type );
  1009. }
  1010. break;
  1011. case DepthStencilFormat:
  1012. switch ( type ) {
  1013. case UnsignedInt248Type:
  1014. formatGPU = GPUTextureFormat.Depth24PlusStencil8;
  1015. break;
  1016. case FloatType:
  1017. if ( device && device.features.has( GPUFeatureName.Depth32FloatStencil8 ) === false ) {
  1018. console.error( 'WebGPURenderer: Depth textures with DepthStencilFormat + FloatType can only be used with the "depth32float-stencil8" GPU feature.' );
  1019. }
  1020. formatGPU = GPUTextureFormat.Depth32FloatStencil8;
  1021. break;
  1022. default:
  1023. console.error( 'WebGPURenderer: Unsupported texture type with DepthStencilFormat.', type );
  1024. }
  1025. break;
  1026. case RedIntegerFormat:
  1027. switch ( type ) {
  1028. case IntType:
  1029. formatGPU = GPUTextureFormat.R32Sint;
  1030. break;
  1031. case UnsignedIntType:
  1032. formatGPU = GPUTextureFormat.R32Uint;
  1033. break;
  1034. default:
  1035. console.error( 'WebGPURenderer: Unsupported texture type with RedIntegerFormat.', type );
  1036. }
  1037. break;
  1038. case RGIntegerFormat:
  1039. switch ( type ) {
  1040. case IntType:
  1041. formatGPU = GPUTextureFormat.RG32Sint;
  1042. break;
  1043. case UnsignedIntType:
  1044. formatGPU = GPUTextureFormat.RG32Uint;
  1045. break;
  1046. default:
  1047. console.error( 'WebGPURenderer: Unsupported texture type with RGIntegerFormat.', type );
  1048. }
  1049. break;
  1050. case RGBAIntegerFormat:
  1051. switch ( type ) {
  1052. case IntType:
  1053. formatGPU = GPUTextureFormat.RGBA32Sint;
  1054. break;
  1055. case UnsignedIntType:
  1056. formatGPU = GPUTextureFormat.RGBA32Uint;
  1057. break;
  1058. default:
  1059. console.error( 'WebGPURenderer: Unsupported texture type with RGBAIntegerFormat.', type );
  1060. }
  1061. break;
  1062. default:
  1063. console.error( 'WebGPURenderer: Unsupported texture format.', format );
  1064. }
  1065. }
  1066. return formatGPU;
  1067. }
  1068. export default WebGPUTextureUtils;
粤ICP备19079148号