webgpuPipelineContext.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. import { IPipelineContext } from '../IPipelineContext';
  2. import { Nullable } from '../../types';
  3. import { WebGPUEngine } from '../webgpuEngine';
  4. import { InternalTexture } from '../../Materials/Textures/internalTexture';
  5. import { Effect } from '../../Materials/effect';
  6. import { WebGPUShaderProcessingContext } from './webgpuShaderProcessingContext';
  7. import { UniformBuffer } from "../../Materials/uniformBuffer";
  8. import { IMatrixLike, IVector2Like, IVector3Like, IVector4Like, IColor3Like, IColor4Like } from '../../Maths/math.like';
  9. import { _IDoNeedToBeInTheBuild } from '../../Particles';
  10. const _uniformSizes: { [type: string]: number } = {
  11. "float": 1,
  12. "vec2": 2,
  13. "vec3": 3,
  14. "vec4": 4,
  15. "mat2": 4,
  16. "mat3": 9,
  17. "mat4": 16
  18. };
  19. /** @hidden */
  20. export interface IWebGPUPipelineContextSamplerCache {
  21. setIndex: number;
  22. textureBinding: number;
  23. samplerBinding: number;
  24. texture: InternalTexture;
  25. }
  26. /** @hidden */
  27. export interface IWebGPUPipelineContextVertexInputsCache {
  28. indexBuffer: Nullable<GPUBuffer>;
  29. indexOffset: number;
  30. vertexStartSlot: number;
  31. vertexBuffers: GPUBuffer[];
  32. vertexOffsets: number[];
  33. }
  34. /** @hidden */
  35. export class WebGPUPipelineContext implements IPipelineContext {
  36. public engine: WebGPUEngine;
  37. public availableAttributes: { [key: string]: number };
  38. public availableUBOs: { [key: string]: { setIndex: number, bindingIndex: number} };
  39. public availableSamplers: { [key: string]: { setIndex: number, bindingIndex: number} };
  40. public orderedAttributes: string[];
  41. public orderedUBOsAndSamplers: { name: string, isSampler: boolean }[][];
  42. public leftOverUniforms: { name: string, type: string }[];
  43. public leftOverUniformsByName: { [name: string]: string };
  44. public sources: {
  45. vertex: string
  46. fragment: string,
  47. };
  48. public stages: Nullable<GPURenderPipelineStageDescriptor>;
  49. public samplers: { [name: string]: Nullable<IWebGPUPipelineContextSamplerCache> } = { };
  50. public vertexInputs: IWebGPUPipelineContextVertexInputsCache;
  51. public bindGroupLayouts: (GPUBindGroupLayout | undefined)[];
  52. public bindGroups: GPUBindGroup[];
  53. public renderPipeline: GPURenderPipeline;
  54. /**
  55. * Stores the uniform buffer
  56. */
  57. public uniformBuffer: Nullable<UniformBuffer>;
  58. // Default implementation.
  59. public onCompiled?: () => void;
  60. public get isAsync() {
  61. return false;
  62. }
  63. public get isReady(): boolean {
  64. if (this.stages) {
  65. return true;
  66. }
  67. return false;
  68. }
  69. constructor(shaderProcessingContext: WebGPUShaderProcessingContext, engine: WebGPUEngine) {
  70. if (shaderProcessingContext) {
  71. this.availableAttributes = shaderProcessingContext.availableAttributes;
  72. this.availableUBOs = shaderProcessingContext.availableUBOs;
  73. this.availableSamplers = shaderProcessingContext.availableSamplers;
  74. this.orderedAttributes = shaderProcessingContext.orderedAttributes;
  75. this.orderedUBOsAndSamplers = shaderProcessingContext.orderedUBOsAndSamplers;
  76. this.leftOverUniforms = shaderProcessingContext.leftOverUniforms;
  77. this.leftOverUniformsByName = {};
  78. }
  79. }
  80. public _handlesSpectorRebuildCallback(onCompiled: (program: any) => void): void {
  81. // Nothing to do yet for spector.
  82. }
  83. public _fillEffectInformation(effect: Effect, uniformBuffersNames: { [key: string]: number }, uniformsNames: string[], uniforms: { [key: string]: Nullable<WebGLUniformLocation> }, samplerList: string[], samplers: { [key: string]: number }, attributesNames: string[], attributes: number[]) {
  84. const engine = this.engine;
  85. // TODO WEBGPU. Cleanup SEB on this entire function. Should not need anything in here or almost.
  86. let effectAvailableUniforms = engine.getUniforms(this, uniformsNames);
  87. effectAvailableUniforms.forEach((uniform, index) => {
  88. uniforms[uniformsNames[index]] = uniform;
  89. });
  90. // Prevent Memory Leak by reducing the number of string, refer to the string instead of copy.
  91. effect._fragmentSourceCode = "";
  92. effect._vertexSourceCode = "";
  93. // this._fragmentSourceCodeOverride = "";
  94. // this._vertexSourceCodeOverride = "";
  95. const foundSamplers = this.availableSamplers;
  96. let index: number;
  97. for (index = 0; index < samplerList.length; index++) {
  98. const name = samplerList[index];
  99. const sampler = foundSamplers[samplerList[index]];
  100. if (sampler == null || sampler == undefined) {
  101. samplerList.splice(index, 1);
  102. index--;
  103. }
  104. else {
  105. samplers[name] = index;
  106. }
  107. }
  108. attributes.push(...engine.getAttributes(this, attributesNames));
  109. // Build the uniform layout for the left over uniforms.
  110. this.buildUniformLayout();
  111. }
  112. /**
  113. * Build the uniform buffer used in the material.
  114. */
  115. public buildUniformLayout(): void {
  116. if (!this.leftOverUniforms.length) {
  117. return;
  118. }
  119. this.uniformBuffer = new UniformBuffer(this.engine);
  120. for (let leftOverUniform of this.leftOverUniforms) {
  121. const size = _uniformSizes[leftOverUniform.type];
  122. this.uniformBuffer.addUniform(leftOverUniform.name, size);
  123. // TODO WEBGPU. Replace with info from uniform buffer class
  124. this.leftOverUniformsByName[leftOverUniform.name] = leftOverUniform.type;
  125. }
  126. this.uniformBuffer.create();
  127. }
  128. /**
  129. * Release all associated resources.
  130. **/
  131. public dispose() {
  132. if (this.uniformBuffer) {
  133. this.uniformBuffer.dispose();
  134. }
  135. // TODO WEBGPU. Dispose all resources.
  136. }
  137. /**
  138. * Sets an interger value on a uniform variable.
  139. * @param uniformName Name of the variable.
  140. * @param value Value to be set.
  141. */
  142. public setInt(uniformName: string, value: number): void {
  143. throw "setInt not Supported in LeftOver UBO.";
  144. }
  145. /**
  146. * Sets an int array on a uniform variable.
  147. * @param uniformName Name of the variable.
  148. * @param array array to be set.
  149. */
  150. public setIntArray(uniformName: string, array: Int32Array): void {
  151. throw "setIntArray not Supported in LeftOver UBO.";
  152. }
  153. /**
  154. * Sets an int array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
  155. * @param uniformName Name of the variable.
  156. * @param array array to be set.
  157. */
  158. public setIntArray2(uniformName: string, array: Int32Array): void {
  159. throw "setIntArray2 not Supported in LeftOver UBO.";
  160. }
  161. /**
  162. * Sets an int array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
  163. * @param uniformName Name of the variable.
  164. * @param array array to be set.
  165. */
  166. public setIntArray3(uniformName: string, array: Int32Array): void {
  167. throw "setIntArray3 not Supported in LeftOver UBO.";
  168. }
  169. /**
  170. * Sets an int array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
  171. * @param uniformName Name of the variable.
  172. * @param array array to be set.
  173. */
  174. public setIntArray4(uniformName: string, array: Int32Array): void {
  175. throw "setIntArray4 not Supported in LeftOver UBO.";
  176. }
  177. /**
  178. * Sets an float array on a uniform variable.
  179. * @param uniformName Name of the variable.
  180. * @param array array to be set.
  181. */
  182. public setFloatArray(uniformName: string, array: Float32Array): void {
  183. // TODO WEBGPU. MorphTarget.
  184. throw "setFloatArray not Supported in LeftOver UBO.";
  185. }
  186. /**
  187. * Sets an float array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
  188. * @param uniformName Name of the variable.
  189. * @param array array to be set.
  190. */
  191. public setFloatArray2(uniformName: string, array: Float32Array): void {
  192. throw "setFloatArray2 not Supported in LeftOver UBO.";
  193. }
  194. /**
  195. * Sets an float array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
  196. * @param uniformName Name of the variable.
  197. * @param array array to be set.
  198. */
  199. public setFloatArray3(uniformName: string, array: Float32Array): void {
  200. throw "setFloatArray3 not Supported in LeftOver UBO.";
  201. }
  202. /**
  203. * Sets an float array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
  204. * @param uniformName Name of the variable.
  205. * @param array array to be set.
  206. */
  207. public setFloatArray4(uniformName: string, array: Float32Array): void {
  208. throw "setFloatArray4 not Supported in LeftOver UBO.";
  209. }
  210. /**
  211. * Sets an array on a uniform variable.
  212. * @param uniformName Name of the variable.
  213. * @param array array to be set.
  214. */
  215. public setArray(uniformName: string, array: number[]): void {
  216. // TODO WEBGPU.
  217. throw "setArray not Supported in LeftOver UBO.";
  218. }
  219. /**
  220. * Sets an array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
  221. * @param uniformName Name of the variable.
  222. * @param array array to be set.
  223. */
  224. public setArray2(uniformName: string, array: number[]): void {
  225. // TODO WEBGPU.
  226. throw "setArray2 not Supported in LeftOver UBO.";
  227. }
  228. /**
  229. * Sets an array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
  230. * @param uniformName Name of the variable.
  231. * @param array array to be set.
  232. * @returns this effect.
  233. */
  234. public setArray3(uniformName: string, array: number[]): void {
  235. // TODO WEBGPU.
  236. throw "setArray3 not Supported in LeftOver UBO.";
  237. }
  238. /**
  239. * Sets an array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
  240. * @param uniformName Name of the variable.
  241. * @param array array to be set.
  242. */
  243. public setArray4(uniformName: string, array: number[]): void {
  244. // TODO WEBGPU.
  245. throw "setArray4 not Supported in LeftOver UBO.";
  246. }
  247. /**
  248. * Sets matrices on a uniform variable.
  249. * @param uniformName Name of the variable.
  250. * @param matrices matrices to be set.
  251. */
  252. public setMatrices(uniformName: string, matrices: Float32Array): void {
  253. // TODO WEBGPU.
  254. throw "setMatrices not Supported in LeftOver UBO.";
  255. }
  256. /**
  257. * Sets matrix on a uniform variable.
  258. * @param uniformName Name of the variable.
  259. * @param matrix matrix to be set.
  260. */
  261. public setMatrix(uniformName: string, matrix: IMatrixLike): void {
  262. if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
  263. return;
  264. }
  265. this.uniformBuffer.updateMatrix(uniformName, matrix);
  266. }
  267. /**
  268. * Sets a 3x3 matrix on a uniform variable. (Speicified as [1,2,3,4,5,6,7,8,9] will result in [1,2,3][4,5,6][7,8,9] matrix)
  269. * @param uniformName Name of the variable.
  270. * @param matrix matrix to be set.
  271. */
  272. public setMatrix3x3(uniformName: string, matrix: Float32Array): void {
  273. if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
  274. return;
  275. }
  276. this.uniformBuffer.updateMatrix3x3(uniformName, matrix);
  277. }
  278. /**
  279. * Sets a 2x2 matrix on a uniform variable. (Speicified as [1,2,3,4] will result in [1,2][3,4] matrix)
  280. * @param uniformName Name of the variable.
  281. * @param matrix matrix to be set.
  282. */
  283. public setMatrix2x2(uniformName: string, matrix: Float32Array): void {
  284. if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
  285. return;
  286. }
  287. this.uniformBuffer.updateMatrix2x2(uniformName, matrix);
  288. }
  289. /**
  290. * Sets a float on a uniform variable.
  291. * @param uniformName Name of the variable.
  292. * @param value value to be set.
  293. * @returns this effect.
  294. */
  295. public setFloat(uniformName: string, value: number): void {
  296. if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
  297. return;
  298. }
  299. this.uniformBuffer.updateFloat(uniformName, value);
  300. }
  301. /**
  302. * Sets a boolean on a uniform variable.
  303. * @param uniformName Name of the variable.
  304. * @param bool value to be set.
  305. */
  306. public setBool(uniformName: string, bool: boolean): void {
  307. // this.engine.setBool(this._uniforms[uniformName], bool ? 1 : 0);
  308. // TODO WEBGPU.
  309. throw "setBool not Supported in LeftOver UBO.";
  310. }
  311. /**
  312. * Sets a Vector2 on a uniform variable.
  313. * @param uniformName Name of the variable.
  314. * @param vector2 vector2 to be set.
  315. */
  316. public setVector2(uniformName: string, vector2: IVector2Like): void {
  317. this.setFloat2(uniformName, vector2.x, vector2.y);
  318. }
  319. /**
  320. * Sets a float2 on a uniform variable.
  321. * @param uniformName Name of the variable.
  322. * @param x First float in float2.
  323. * @param y Second float in float2.
  324. */
  325. public setFloat2(uniformName: string, x: number, y: number): void {
  326. if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
  327. return;
  328. }
  329. this.uniformBuffer.updateFloat2(uniformName, x, y);
  330. }
  331. /**
  332. * Sets a Vector3 on a uniform variable.
  333. * @param uniformName Name of the variable.
  334. * @param vector3 Value to be set.
  335. */
  336. public setVector3(uniformName: string, vector3: IVector3Like): void {
  337. this.setFloat3(uniformName, vector3.x, vector3.y, vector3.z);
  338. }
  339. /**
  340. * Sets a float3 on a uniform variable.
  341. * @param uniformName Name of the variable.
  342. * @param x First float in float3.
  343. * @param y Second float in float3.
  344. * @param z Third float in float3.
  345. */
  346. public setFloat3(uniformName: string, x: number, y: number, z: number): void {
  347. if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
  348. return;
  349. }
  350. this.uniformBuffer.updateFloat3(uniformName, x, y, z);
  351. }
  352. /**
  353. * Sets a Vector4 on a uniform variable.
  354. * @param uniformName Name of the variable.
  355. * @param vector4 Value to be set.
  356. */
  357. public setVector4(uniformName: string, vector4: IVector4Like): void {
  358. this.setFloat4(uniformName, vector4.x, vector4.y, vector4.z, vector4.w);
  359. }
  360. /**
  361. * Sets a float4 on a uniform variable.
  362. * @param uniformName Name of the variable.
  363. * @param x First float in float4.
  364. * @param y Second float in float4.
  365. * @param z Third float in float4.
  366. * @param w Fourth float in float4.
  367. * @returns this effect.
  368. */
  369. public setFloat4(uniformName: string, x: number, y: number, z: number, w: number): void {
  370. if (!this.uniformBuffer || !this.leftOverUniformsByName[uniformName]) {
  371. return;
  372. }
  373. this.uniformBuffer.updateFloat4(uniformName, x, y, z, w);
  374. }
  375. /**
  376. * Sets a Color3 on a uniform variable.
  377. * @param uniformName Name of the variable.
  378. * @param color3 Value to be set.
  379. */
  380. public setColor3(uniformName: string, color3: IColor3Like): void {
  381. this.setFloat3(uniformName, color3.b, color3.g, color3.b);
  382. }
  383. /**
  384. * Sets a Color4 on a uniform variable.
  385. * @param uniformName Name of the variable.
  386. * @param color3 Value to be set.
  387. * @param alpha Alpha value to be set.
  388. */
  389. public setColor4(uniformName: string, color3: IColor3Like, alpha: number): void {
  390. this.setFloat4(uniformName, color3.b, color3.g, color3.b, alpha);
  391. }
  392. /**
  393. * Sets a Color4 on a uniform variable
  394. * @param uniformName defines the name of the variable
  395. * @param color4 defines the value to be set
  396. */
  397. public setDirectColor4(uniformName: string, color4: IColor4Like): void {
  398. this.setFloat4(uniformName, color4.b, color4.g, color4.b, color4.a);
  399. }
  400. }