WebGPUTextureUtils.js 41 KB

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