ops_webgl.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import numpy as np
  2. import functools
  3. from tinygrad.dtype import dtypes, ImageDType
  4. from tinygrad.device import Compiled, Allocator, CompilerOptions
  5. from tinygrad.codegen.kernel import OptOps
  6. from tinygrad.renderer.cstyle import uops_to_cstyle
  7. from tinygrad.renderer.cstyle import GLSLLanguage
  8. import moderngl
  9. ctx = moderngl.create_standalone_context()
  10. max_dims = 4096
  11. dtype_map = { dtypes.float64: "f8", dtypes.float: "f4", dtypes.half: "f2", dtypes.int32: "i4", dtypes.uint32: "u4", dtypes.bool: "i1"}
  12. vertex_shader="#version 330\nprecision highp float;\nin vec2 in_position;in vec2 in_uv;out vec2 uv;void main(){\
  13. gl_Position=vec4(in_position,0.0,1.0);uv=in_uv;}"
  14. class WebGLProgram:
  15. def __init__(self, name: str, prg: str, bufs:int=0, vars:int=0):
  16. self.name, self.prg = name, ctx.program(vertex_shader=vertex_shader, fragment_shader=prg)
  17. def __call__(self, *bufs, global_size, local_size=None, vals=(), wait=False):
  18. vert = ctx.buffer(np.asarray([-1, 1, -1, -1, 1, 1, 1, -1], dtype='f4').tobytes())
  19. uv = ctx.buffer(np.asarray([0, 1, 0, 0, 1, 1, 1, 0], dtype='f4').tobytes())
  20. self.vao = ctx.vertex_array(self.prg, [])
  21. self.vao.bind(self.prg["in_position"].location if "in_position" in self.prg else 0, buffer=vert, cls='f', fmt='2f4')
  22. self.vao.bind(self.prg["in_uv"].location if "in_uv" in self.prg else 1, buffer=uv, cls='f', fmt='2f4')
  23. self.vao.vertices = vert.size//4//2
  24. self.fbo = ctx.framebuffer(color_attachments=[bufs[0]])
  25. for i, x in enumerate(bufs[1:], start=1):
  26. if f"data{i}" in self.prg:
  27. self.prg[f"data{i}"] = i
  28. x.use(i)
  29. if ("width" in self.prg): self.prg["width"].value = self.fbo.size[0]
  30. ctx.viewport = (0, 0, self.fbo.size[0], self.fbo.size[1])
  31. self.fbo.use()
  32. self.vao.render(mode=moderngl.TRIANGLE_STRIP)
  33. class RawWebGLAllocator(Allocator):
  34. def _alloc_image(self, dtype:ImageDType):
  35. tex = ctx.texture(dtype.shape, 1, dtype=dtype_map[dtype.base])
  36. tex.filter = (moderngl.NEAREST, moderngl.NEAREST)
  37. return tex
  38. def copyin(self, dest:moderngl.Texture, src: memoryview): dest.write(src)
  39. def copyout(self, dest:memoryview, src: moderngl.Texture):
  40. src.read_into(dest)
  41. return dest
  42. class WebGlDevice(Compiled):
  43. def __init__(self, device:str):
  44. super().__init__(RawWebGLAllocator(),
  45. CompilerOptions(device="WEBGL", global_max=[4096*4096,1,1], unsupported_opts=[OptOps.UPCAST, OptOps.UPCASTMID],
  46. supports_float4=False, supports_float4_alu=False, has_local=False, has_shared=False, dont_use_locals=True),
  47. functools.partial(uops_to_cstyle, GLSLLanguage()), lambda x: x, WebGLProgram)