webgpuShaderProcessors.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { Nullable } from '../../types';
  2. import { IShaderProcessor } from '../Processors/iShaderProcessor';
  3. import { ShaderProcessingContext } from "../processors/shaderProcessingOptions";
  4. import { WebGPUShaderProcessingContext } from './webgpuShaderProcessingContext';
  5. /** @hidden */
  6. export class WebGPUShaderProcessor implements IShaderProcessor {
  7. // varyingProcessor?: (varying: string, isFragment: boolean) => string;
  8. // uniformProcessor?: (uniform: string, isFragment: boolean) => string;
  9. // uniformBufferProcessor?: (uniformBuffer: string, isFragment: boolean) => string;
  10. // endOfUniformBufferProcessor?: (closingBracketLine: string, isFragment: boolean) => string;
  11. // lineProcessor?: (line: string, isFragment: boolean) => string;
  12. // preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
  13. // postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
  14. public attributeProcessor(attribute: string, processingContext: Nullable<ShaderProcessingContext>) {
  15. const webgpuProcessingContext = processingContext! as WebGPUShaderProcessingContext;
  16. // return attribute.replace("attribute", "in");
  17. const attribRegex = new RegExp(/\s*attribute\s+(\S+)\s+(\S+)\s*;/gm);
  18. const match = attribRegex.exec(attribute);
  19. const location = webgpuProcessingContext.attributeNextLocation++;
  20. if (match != null) {
  21. const name = match[2];
  22. webgpuProcessingContext.availableAttributes[name] = location;
  23. attribute = attribute.replace(match[0], `layout(location = ${location}) in ${match[1]} ${name};`);
  24. }
  25. return attribute;
  26. }
  27. public varyingProcessor(varying: string, isFragment: boolean) {
  28. return varying.replace("varying", isFragment ? "in" : "out");
  29. // const inOut = isFragment ? "in" : "out";
  30. // const attribRegex = new RegExp(/\s+varying\s+(\w+)\s+/gm);
  31. // let location = 0;
  32. // let match = attribRegex.exec(code);
  33. // while (match != null) {
  34. // if (match[1]) {
  35. // code = code.replace(match[0], ` layout(location = ${location}) ${inOut} ${match[1]} `);
  36. // location++;
  37. // }
  38. // match = attribRegex.exec(code);
  39. // }
  40. // return code;
  41. }
  42. public postProcessor(code: string, defines: string[], isFragment: boolean) {
  43. const hasDrawBuffersExtension = code.search(/#extension.+GL_EXT_draw_buffers.+require/) !== -1;
  44. // Remove extensions
  45. var regex = /#extension.+(GL_OVR_multiview2|GL_OES_standard_derivatives|GL_EXT_shader_texture_lod|GL_EXT_frag_depth|GL_EXT_draw_buffers).+(enable|require)/g;
  46. code = code.replace(regex, "");
  47. // Replace instructions
  48. code = code.replace(/texture2D\s*\(/g, "texture(");
  49. if (isFragment) {
  50. code = code.replace(/texture2DLodEXT\s*\(/g, "textureLod(");
  51. code = code.replace(/textureCubeLodEXT\s*\(/g, "textureLod(");
  52. code = code.replace(/textureCube\s*\(/g, "texture(");
  53. code = code.replace(/gl_FragDepthEXT/g, "gl_FragDepth");
  54. code = code.replace(/gl_FragColor/g, "glFragColor");
  55. code = code.replace(/gl_FragData/g, "glFragData");
  56. code = code.replace(/void\s+?main\s*\(/g, (hasDrawBuffersExtension ? "" : "layout(location = 0) out vec4 glFragColor;\n") + "void main(");
  57. } else {
  58. var hasMultiviewExtension = defines.indexOf("#define MULTIVIEW") !== -1;
  59. if (hasMultiviewExtension) {
  60. return "#extension GL_OVR_multiview2 : require\nlayout (num_views = 2) in;\n" + code;
  61. }
  62. }
  63. // Flip Y.
  64. // TODO WEBGPU. Triple check this part and wait on Google News for this issue.
  65. if (!isFragment) {
  66. const lastClosingCurly = code.lastIndexOf("}");
  67. code = code.substring(0, lastClosingCurly);
  68. code += "gl_Position.y *= -1.; }";
  69. }
  70. return code;
  71. }
  72. }