~eliasnaur/gio-patches

5 3

[PATCH gio 0/2] [PATCH v3] gpu: native yuv format support

~dejadeja9
Details
Message ID
<159388339974.26803.16846442073837397453-0@git.sr.ht>
DKIM signature
missing
Download raw message
I hope this addresses all the comments except for "YStride check". I
believe the check is unnecessary because width could be smaller than the
the stride as a normal case when alignment is needed. One possible
optimization for `(t *gpuTexture) Upload` is that we may use
SubTexImage2D but that can be left for the future. One thing I am not
sure is whether `texUnits [3]*gpuTexture` should be updated to 4.

Deja Deja (2):
  gpu: native yuv support
  gpu: update shaders.go

 app/internal/d3d11/backend_windows.go |  14 +-
 app/internal/d3d11/d3d11_windows.go   |   1 +
 gpu/backend/backend.go                |   3 +-
 gpu/gl/backend.go                     |  18 +--
 gpu/gpu.go                            | 144 +++++++++++++----
 gpu/path.go                           |   8 +-
 gpu/shaders.go                        | 221 +++++++++++++++++++++++---
 gpu/shaders/blit.frag                 |   2 +
 gpu/shaders/common.inc                |  14 ++
 gpu/shaders/cover.frag                |   4 +-
 internal/cmd/convertshaders/main.go   |  10 +-
 op/paint/paint.go                     |  23 +--
 12 files changed, 367 insertions(+), 95 deletions(-)

-- 
2.26.2

[PATCH gio 1/2] gpu: native yuv support

~dejadeja9
Details
Message ID
<159388339974.26803.16846442073837397453-1@git.sr.ht>
In-Reply-To
<159388339974.26803.16846442073837397453-0@git.sr.ht> (view parent)
DKIM signature
missing
Download raw message
Patch: +170 -71
From: Deja Deja <dejadejade9@outlook.com>

---
 app/internal/d3d11/backend_windows.go |  14 +--
 app/internal/d3d11/d3d11_windows.go   |   1 +
 gpu/backend/backend.go                |   3 +-
 gpu/gl/backend.go                     |  18 ++--
 gpu/gpu.go                            | 144 ++++++++++++++++++++------
 gpu/path.go                           |   8 +-
 gpu/shaders/blit.frag                 |   2 +
 gpu/shaders/common.inc                |  14 +++
 gpu/shaders/cover.frag                |   4 +-
 internal/cmd/convertshaders/main.go   |  10 +-
 op/paint/paint.go                     |  23 ++--
 11 files changed, 170 insertions(+), 71 deletions(-)

diff --git a/app/internal/d3d11/backend_windows.go b/app/internal/d3d11/backend_windows.go
index 48ff175..94247c6 100644
--- a/app/internal/d3d11/backend_windows.go
+++ b/app/internal/d3d11/backend_windows.go
@@ -300,6 +300,8 @@ func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, mi
		d3dfmt = b.dev.floatFormat
	case backend.TextureFormatSRGB:
		d3dfmt = _DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
	case backend.TextureFormatLuminance:
		d3dfmt = _DXGI_FORMAT_R8_UNORM
	default:
		return nil, fmt.Errorf("unsupported texture format %d", format)
	}
@@ -666,17 +668,9 @@ func (b *Backend) BlendFunc(sfactor, dfactor backend.BlendFactor) {
	b.blendState.dfactor = dfactor
}

func (t *Texture) Upload(img *image.RGBA) {
	b := img.Bounds()
	w := b.Dx()
	if img.Stride != w*4 {
		panic("unsupported stride")
	}
	start := (b.Min.X + b.Min.Y*w) * 4
	end := (b.Max.X + (b.Max.Y-1)*w) * 4
	pixels := img.Pix[start:end]
func (t *Texture) Upload(pixels []byte, w, h, bpp int) {
	res := (*_ID3D11Resource)(unsafe.Pointer(t.tex))
	t.backend.dev.ctx.UpdateSubresource(res, uint32(img.Stride), uint32(len(pixels)), pixels)
	t.backend.dev.ctx.UpdateSubresource(res, uint32(bpp*w), uint32(len(pixels)), pixels)
}

func (t *Texture) Release() {
diff --git a/app/internal/d3d11/d3d11_windows.go b/app/internal/d3d11/d3d11_windows.go
index 3dd2138..544936b 100644
--- a/app/internal/d3d11/d3d11_windows.go
+++ b/app/internal/d3d11/d3d11_windows.go
@@ -565,6 +565,7 @@ const (
	_DXGI_FORMAT_R32G32B32A32_FLOAT  = 2
	_DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29
	_DXGI_FORMAT_R16_SINT            = 59
	_DXGI_FORMAT_R8_UNORM            = 61
	_DXGI_FORMAT_R16G16_SINT         = 38
	_DXGI_FORMAT_R16_UINT            = 57
	_DXGI_FORMAT_D24_UNORM_S8_UINT   = 45
diff --git a/gpu/backend/backend.go b/gpu/backend/backend.go
index 871eea4..bd6927a 100644
--- a/gpu/backend/backend.go
+++ b/gpu/backend/backend.go
@@ -150,7 +150,7 @@ type Timer interface {
}

type Texture interface {
	Upload(img *image.RGBA)
	Upload(pix []byte, width, height, bpp int)
	Release()
}

@@ -176,6 +176,7 @@ const (
const (
	TextureFormatSRGB TextureFormat = iota
	TextureFormatFloat
	TextureFormatLuminance
)

const (
diff --git a/gpu/gl/backend.go b/gpu/gl/backend.go
index 02037c3..5ff7caa 100644
--- a/gpu/gl/backend.go
+++ b/gpu/gl/backend.go
@@ -36,7 +36,7 @@ type glstate struct {
	// nattr is the current number of enabled vertex arrays.
	nattr    int
	prog     *gpuProgram
	texUnits [2]*gpuTexture
	texUnits [3]*gpuTexture
	layout   *gpuInputLayout
	buffer   bufferBinding
}
@@ -130,6 +130,7 @@ func NewBackend(f Functions) (*Backend, error) {
	if err != nil {
		return nil, err
	}

	ubo := ver[0] >= 3 && gles
	b := &Backend{
		glver:       ver,
@@ -221,6 +222,8 @@ func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, mi
		tex.triple = b.floatTriple
	case backend.TextureFormatSRGB:
		tex.triple = b.srgbaTriple
	case backend.TextureFormatLuminance:
		tex.triple = b.alphaTriple
	default:
		return nil, errors.New("unsupported texture format")
	}
@@ -703,18 +706,9 @@ func (t *gpuTexture) Release() {
	t.backend.funcs.DeleteTexture(t.obj)
}

func (t *gpuTexture) Upload(img *image.RGBA) {
func (t *gpuTexture) Upload(pix []byte, w, h, bpp int) {
	t.backend.BindTexture(0, t)
	var pixels []byte
	b := img.Bounds()
	w, h := b.Dx(), b.Dy()
	if img.Stride != w*4 {
		panic("unsupported stride")
	}
	start := (b.Min.X + b.Min.Y*w) * 4
	end := (b.Max.X + (b.Max.Y-1)*w) * 4
	pixels = img.Pix[start:end]
	t.backend.funcs.TexImage2D(TEXTURE_2D, 0, t.triple.internalFormat, w, h, t.triple.format, t.triple.typ, pixels)
	t.backend.funcs.TexImage2D(TEXTURE_2D, 0, t.triple.internalFormat, w, h, t.triple.format, t.triple.typ, pix)
}

func (t *gpuTimer) Begin() {
diff --git a/gpu/gpu.go b/gpu/gpu.go
index 321b2a8..6a96ad1 100644
--- a/gpu/gpu.go
+++ b/gpu/gpu.go
@@ -109,8 +109,9 @@ type material struct {
	opaque   bool
	// For materialTypeColor.
	color f32color.RGBA
	// For materialTypeTexture.
	// For materialTypeTexture & materialYCbCr.
	texture *texture

	uvTrans f32.Affine2D
}

@@ -122,7 +123,7 @@ type clipOp struct {
// imageOpData is the shadow of paint.ImageOp.
type imageOpData struct {
	rect   image.Rectangle
	src    *image.RGBA
	src    image.Image
	handle interface{}
}

@@ -146,16 +147,25 @@ func (op *clipOp) decode(data []byte) {
	}
}

func decodeImageOp(data []byte, refs []interface{}) imageOpData {
func decodeImageOp(data []byte, refs []interface{}) (mtype materialType, imgData imageOpData) {
	if opconst.OpType(data[0]) != opconst.TypeImage {
		panic("invalid op")
	}
	handle := refs[1]
	if handle == nil {
		return imageOpData{}
		return materialColor, imageOpData{}
	}
	bo := binary.LittleEndian
	return imageOpData{

	if _, ok := refs[0].(*image.RGBA); ok {
		mtype = materialTexture
	} else if _, ok := refs[0].(*image.YCbCr); ok {
		mtype = materialYCbCr
	} else {
		panic("invalid image type")
	}

	imgData = imageOpData{
		rect: image.Rectangle{
			Min: image.Point{
				X: int(bo.Uint32(data[1:])),
@@ -166,9 +176,10 @@ func decodeImageOp(data []byte, refs []interface{}) imageOpData {
				Y: int(bo.Uint32(data[13:])),
			},
		},
		src:    refs[0].(*image.RGBA),
		src:    refs[0].(image.Image),
		handle: handle,
	}
	return
}

func decodeColorOp(data []byte) color.RGBA {
@@ -210,14 +221,14 @@ type resource interface {
}

type texture struct {
	src *image.RGBA
	tex backend.Texture
	src image.Image
	tex []backend.Texture
}

type blitter struct {
	ctx         backend.Device
	viewport    image.Point
	prog        [2]*program
	prog        [3]*program
	layout      backend.InputLayout
	colUniforms *blitColUniforms
	texUniforms *blitTexUniforms
@@ -274,6 +285,7 @@ const (
const (
	materialColor materialType = iota
	materialTexture
	materialYCbCr
)

func New(ctx backend.Device) (*GPU, error) {
@@ -383,22 +395,68 @@ func (g *GPU) Profile() string {
	return g.profile
}

func (r *renderer) texHandle(t *texture) backend.Texture {
	if t.tex != nil {
func (r *renderer) bindTexture(t *texture) {
	tex := r.texHandle(t)
	for i, t := range tex {
		r.ctx.BindTexture(i, t)
	}
}

func (r *renderer) texHandle(t *texture) []backend.Texture {
	if len(t.tex) > 0 {
		return t.tex
	}
	tex, err := r.ctx.NewTexture(backend.TextureFormatSRGB, t.src.Bounds().Dx(), t.src.Bounds().Dy(), backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
	if err != nil {
		panic(err)

	w, h := t.src.Bounds().Dx(), t.src.Bounds().Dy()
	switch src := t.src.(type) {
	case *image.RGBA:
		tex, err := r.ctx.NewTexture(backend.TextureFormatSRGB, src.Bounds().Dx(), src.Bounds().Dy(), backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
		if err != nil {
			panic(err)
		}
		tex.Upload(src.Pix, src.Bounds().Dx(), src.Bounds().Dy(), 4)
		t.tex = append(t.tex, tex)
	case *image.YCbCr:
		//use YStride instead of Bounds().Dx() as Bounds().Dx() could be smaller than YStride due to padding
		w = src.YStride
		ytex, err := r.ctx.NewTexture(backend.TextureFormatLuminance, w, h, backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
		if err != nil {
			panic(err)
		}
		ytex.Upload(src.Y, w, h, 1)

		wsub, hsub := 1, 1
		switch src.SubsampleRatio {
		case image.YCbCrSubsampleRatio420:
			wsub, hsub = 2, 2
		case image.YCbCrSubsampleRatio444:
			break
		case image.YCbCrSubsampleRatio422:
			wsub, hsub = 2, 1
		}

		utex, err := r.ctx.NewTexture(backend.TextureFormatLuminance, w/wsub, h/hsub, backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
		if err != nil {
			panic(err)
		}
		utex.Upload(src.Cb, w/wsub, h/hsub, 1)

		vtex, err := r.ctx.NewTexture(backend.TextureFormatLuminance, w/wsub, h/hsub, backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
		if err != nil {
			panic(err)
		}
		vtex.Upload(src.Cr, w/wsub, h/hsub, 1)
		t.tex = append(t.tex, ytex, utex, vtex)
	}
	tex.Upload(t.src)
	t.tex = tex

	return t.tex
}

func (t *texture) release() {
	if t.tex != nil {
		t.tex.Release()
	for _, tex := range t.tex {
		if tex != nil {
			tex.Release()
		}
	}
}

@@ -436,8 +494,9 @@ func newBlitter(ctx backend.Device) *blitter {
	}
	b.colUniforms = new(blitColUniforms)
	b.texUniforms = new(blitTexUniforms)

	prog, layout, err := createColorPrograms(ctx, shader_blit_vert, shader_blit_frag,
		[2]interface{}{&b.colUniforms.vert, &b.texUniforms.vert}, [2]interface{}{&b.colUniforms.frag, nil})
		[3]interface{}{&b.colUniforms.vert, &b.texUniforms.vert, &b.texUniforms.vert}, [3]interface{}{&b.colUniforms.frag, nil, nil})
	if err != nil {
		panic(err)
	}
@@ -454,8 +513,8 @@ func (b *blitter) release() {
	b.layout.Release()
}

func createColorPrograms(b backend.Device, vsSrc backend.ShaderSources, fsSrc [2]backend.ShaderSources, vertUniforms, fragUniforms [2]interface{}) ([2]*program, backend.InputLayout, error) {
	var progs [2]*program
func createColorPrograms(b backend.Device, vsSrc backend.ShaderSources, fsSrc [3]backend.ShaderSources, vertUniforms, fragUniforms [3]interface{}) ([3]*program, backend.InputLayout, error) {
	var progs [3]*program
	prog, err := b.NewProgram(vsSrc, fsSrc[materialTexture])
	if err != nil {
		return progs, nil, err
@@ -471,6 +530,7 @@ func createColorPrograms(b backend.Device, vsSrc backend.ShaderSources, fsSrc [2
		prog.SetFragmentUniforms(fragBuffer.buf)
	}
	progs[materialTexture] = newProgram(prog, vertBuffer, fragBuffer)

	prog, err = b.NewProgram(vsSrc, fsSrc[materialColor])
	if err != nil {
		progs[materialTexture].Release()
@@ -485,13 +545,32 @@ func createColorPrograms(b backend.Device, vsSrc backend.ShaderSources, fsSrc [2
		prog.SetFragmentUniforms(fragBuffer.buf)
	}
	progs[materialColor] = newProgram(prog, vertBuffer, fragBuffer)

	prog, err = b.NewProgram(vsSrc, fsSrc[materialYCbCr])
	if err != nil {
		progs[materialTexture].Release()
		progs[materialColor].Release()
		return progs, nil, err
	}
	if u := vertUniforms[materialYCbCr]; u != nil {
		vertBuffer = newUniformBuffer(b, u)
		prog.SetVertexUniforms(vertBuffer.buf)
	}
	if u := fragUniforms[materialYCbCr]; u != nil {
		fragBuffer = newUniformBuffer(b, u)
		prog.SetFragmentUniforms(fragBuffer.buf)
	}
	progs[materialYCbCr] = newProgram(prog, vertBuffer, fragBuffer)

	layout, err := b.NewInputLayout(vsSrc, []backend.InputDesc{
		{Type: backend.DataTypeFloat, Size: 2, Offset: 0},
		{Type: backend.DataTypeFloat, Size: 2, Offset: 4 * 2},
	})
	if err != nil {
		progs[materialTexture].Release()
		progs[materialColor].Release()
		for _, prog := range progs {
			prog.Release()
		}

		return progs, nil, err
	}
	return progs, layout, nil
@@ -759,8 +838,7 @@ loop:
			state.matType = materialColor
			state.color = decodeColorOp(encOp.Data)
		case opconst.TypeImage:
			state.matType = materialTexture
			state.image = decodeImageOp(encOp.Data, encOp.Refs)
			state.matType, state.image = decodeImageOp(encOp.Data, encOp.Refs)
		case opconst.TypePaint:
			op := decodePaintOp(encOp.Data)
			// Transform (if needed) the painting rectangle and if so generate a clip path,
@@ -847,10 +925,10 @@ func (d *drawState) materialFor(cache *resourceCache, rect f32.Rectangle, off f3
		m.material = materialColor
		m.color = f32color.RGBAFromSRGB(d.color)
		m.opaque = m.color.A == 1.0
	case materialTexture:
		m.material = materialTexture
	case materialTexture, materialYCbCr:
		m.material = d.matType
		dr := boundRectF(rect.Add(off))
		sz := d.image.src.Bounds().Size()
		var sz image.Point = d.image.src.Bounds().Size()
		sr := layout.FRect(d.image.rect)
		if dx := float32(dr.Dx()); dx != 0 {
			// Don't clip 1 px width sources.
@@ -890,8 +968,8 @@ func (r *renderer) drawZOps(ops []imageOp) {
		img := ops[i]
		m := img.material
		switch m.material {
		case materialTexture:
			r.ctx.BindTexture(0, r.texHandle(m.texture))
		case materialTexture, materialYCbCr:
			r.bindTexture(m.texture)
		}
		drc := img.clip
		scale, off := clipSpaceTransform(drc, r.blitter.viewport)
@@ -910,8 +988,8 @@ func (r *renderer) drawOps(ops []imageOp) {
	for _, img := range ops {
		m := img.material
		switch m.material {
		case materialTexture:
			r.ctx.BindTexture(0, r.texHandle(m.texture))
		case materialTexture, materialYCbCr:
			r.bindTexture(m.texture)
		}
		drc := img.clip

@@ -949,7 +1027,7 @@ func (b *blitter) blit(z float32, mat materialType, col f32color.RGBA, scale, of
	case materialColor:
		b.colUniforms.frag.color = col
		uniforms = &b.colUniforms.vert.blitUniforms
	case materialTexture:
	case materialTexture, materialYCbCr:
		t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
		b.texUniforms.vert.blitUniforms.uvTransformR1 = [4]float32{t1, t2, t3, 0}
		b.texUniforms.vert.blitUniforms.uvTransformR2 = [4]float32{t4, t5, t6, 0}
diff --git a/gpu/path.go b/gpu/path.go
index 2dd5875..8de1a11 100644
--- a/gpu/path.go
+++ b/gpu/path.go
@@ -28,7 +28,7 @@ type pather struct {

type coverer struct {
	ctx         backend.Device
	prog        [2]*program
	prog        [3]*program
	texUniforms *coverTexUniforms
	colUniforms *coverColUniforms
	layout      backend.InputLayout
@@ -150,8 +150,8 @@ func newCoverer(ctx backend.Device) *coverer {
	c.colUniforms = new(coverColUniforms)
	c.texUniforms = new(coverTexUniforms)
	prog, layout, err := createColorPrograms(ctx, shader_cover_vert, shader_cover_frag,
		[2]interface{}{&c.colUniforms.vert, &c.texUniforms.vert},
		[2]interface{}{&c.colUniforms.frag, nil},
		[3]interface{}{&c.colUniforms.vert, &c.texUniforms.vert, &c.texUniforms.vert},
		[3]interface{}{&c.colUniforms.frag, nil, nil},
	)
	if err != nil {
		panic(err)
@@ -374,7 +374,7 @@ func (c *coverer) cover(z float32, mat materialType, col f32color.RGBA, scale, o
	case materialColor:
		c.colUniforms.frag.color = col
		uniforms = &c.colUniforms.vert.coverUniforms
	case materialTexture:
	case materialTexture, materialYCbCr:
		t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
		c.texUniforms.vert.uvTransformR1 = [4]float32{t1, t2, t3, 0}
		c.texUniforms.vert.uvTransformR2 = [4]float32{t4, t5, t6, 0}
diff --git a/gpu/shaders/blit.frag b/gpu/shaders/blit.frag
index 907f010..f9f0344 100644
--- a/gpu/shaders/blit.frag
+++ b/gpu/shaders/blit.frag
@@ -4,6 +4,8 @@

precision mediump float;

#include <common.inc>

layout(location=0) in vec2 vUV;

{{.Header}}
diff --git a/gpu/shaders/common.inc b/gpu/shaders/common.inc
index a1a3dd9..e1ec8ea 100644
--- a/gpu/shaders/common.inc
+++ b/gpu/shaders/common.inc
@@ -49,3 +49,17 @@ vec4 toClipSpace(vec4 pos) {
vec3 transform3x2(m3x2 t, vec3 v) {
	return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v));
}

// transform matrix from http://www.fourcc.org/source/YUV420P-OpenGL-GLSLang.c
vec4 yuv2rgb(in sampler2D ytex, in sampler2D utex, in sampler2D vtex, in vec2 vUV) {
	float r,g,b,y,u,v;
	y = (texture(ytex, vUV).r - .0625) * 1.1643;
	u = texture(utex, vUV).r - 0.5;
	v = texture(vtex, vUV).r - 0.5;

	r = y+1.5958*v;
	g = y-0.39173*u-0.81290*v;
	b = y+2.017*u;

	return vec4(r, g, b, 1.0);
}
diff --git a/gpu/shaders/cover.frag b/gpu/shaders/cover.frag
index 5a051f8..8dff3ee 100644
--- a/gpu/shaders/cover.frag
+++ b/gpu/shaders/cover.frag
@@ -4,6 +4,8 @@

precision mediump float;

#include "common.inc"

{{.Header}}

// Use high precision to be pixel accurate for
@@ -11,7 +13,7 @@ precision mediump float;
layout(location = 0) in highp vec2 vCoverUV;
layout(location = 1) in vec2 vUV;

layout(binding = 1) uniform sampler2D cover;
layout(binding = 4) uniform sampler2D cover;

layout(location = 0) out vec4 fragColor;

diff --git a/internal/cmd/convertshaders/main.go b/internal/cmd/convertshaders/main.go
index 250137e..915a8fd 100644
--- a/internal/cmd/convertshaders/main.go
+++ b/internal/cmd/convertshaders/main.go
@@ -70,7 +70,7 @@ func generate() error {
		if ext := filepath.Ext(shader); ext != ".vert" && ext != ".frag" {
			continue
		}
		const nvariants = 2
		const nvariants = 3
		var variants [nvariants]struct {
			backend.ShaderSources
			hlslSrc string
@@ -84,6 +84,14 @@ func generate() error {
				FetchColorExpr: `texture(tex, vUV)`,
				Header:         `layout(binding=0) uniform sampler2D tex;`,
			},
			{
				FetchColorExpr: `yuv2rgb(ytex, utex, vtex, vUV)`,
				Header: `
				layout(binding=0) uniform sampler2D ytex;
				layout(binding=1) uniform sampler2D utex;
				layout(binding=2) uniform sampler2D vtex;
				`,
			},
		}
		for i := range args {
			glsl100es, reflect, err := convertShader(tmp, glslcc, shader, "gles", "100", &args[i], false)
diff --git a/op/paint/paint.go b/op/paint/paint.go
index b4a9a56..c9ad3d5 100644
--- a/op/paint/paint.go
+++ b/op/paint/paint.go
@@ -24,7 +24,7 @@ type ImageOp struct {

	uniform bool
	color   color.RGBA
	src     *image.RGBA
	src     image.Image

	// handle is a key to uniquely identify this ImageOp
	// in a map of cached textures.
@@ -53,6 +53,8 @@ type PaintOp struct {
// ensure that changes to an image is reflected in the display of
// it.
func NewImageOp(src image.Image) ImageOp {
	nodraw := false
	bounds := src.Bounds()
	switch src := src.(type) {
	case *image.Uniform:
		col := color.RGBAModel.Convert(src.C).(color.RGBA)
@@ -61,17 +63,20 @@ func NewImageOp(src image.Image) ImageOp {
			color:   col,
		}
	case *image.RGBA:
		bounds := src.Bounds()
		if bounds.Min == (image.Point{}) && src.Stride == bounds.Dx()*4 {
			return ImageOp{
				Rect:   src.Bounds(),
				src:    src,
				handle: new(int),
			}
		nodraw = (bounds.Min == image.Point{} && src.Stride == bounds.Dx()*4)
	case *image.YCbCr:
		nodraw = (bounds.Min == image.Point{})
	}

	if nodraw {
		return ImageOp{
			Rect:   src.Bounds(),
			src:    src,
			handle: new(int),
		}
	}

	sz := src.Bounds().Size()
	sz := bounds.Size()
	// Copy the image into a GPU friendly format.
	dst := image.NewRGBA(image.Rectangle{
		Max: sz,
-- 
2.26.2

[PATCH gio 2/2] gpu: update shaders.go

~dejadeja9
Details
Message ID
<159388339974.26803.16846442073837397453-2@git.sr.ht>
In-Reply-To
<159388339974.26803.16846442073837397453-0@git.sr.ht> (view parent)
DKIM signature
missing
Download raw message
From: Deja Deja <dejadejade9@outlook.com>

---
 gpu/shaders.go | 221 +++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 197 insertions(+), 24 deletions(-)

diff --git a/gpu/shaders.go b/gpu/shaders.go
index d8e8435..e22dd84 100644
--- a/gpu/shaders.go
+++ b/gpu/shaders.go
@@ -12,11 +12,20 @@ var (
 				Locations: []backend.UniformLocation{{Name: "_12._color", Type: 0x0, Size: 4, Offset: 0}},
 				Size:      16,
 			},
-			GLSL100ES: "precision mediump float;\nprecision highp int;\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nvarying vec2 vUV;\n\nvoid main()\n{\n    gl_FragData[0] = _12._color;\n}\n\n",
-			GLSL300ES: "#version 300 es\nprecision mediump float;\nprecision highp int;\n\nlayout(std140) uniform Color\n{\n    vec4 _color;\n} _12;\n\nlayout(location = 0) out vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n}\n\n",
-			GLSL130:   "#version 130\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nout vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n}\n\n",
-			GLSL150:   "#version 150\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nout vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n}\n\n",
+			GLSL100ES: "precision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nvarying vec2 vUV;\n\nvoid main()\n{\n    gl_FragData[0] = _12._color;\n}\n\n",
+			GLSL300ES: "#version 300 es\nprecision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nlayout(std140) uniform Color\n{\n    vec4 _color;\n} _12;\n\nlayout(location = 0) out vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n}\n\n",
+			GLSL130:   "#version 130\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nout vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n}\n\n",
+			GLSL150:   "#version 150\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nout vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n}\n\n",
 			/*
+			   struct m3x2
+			   {
+			       float3 r0;
+			       float3 r1;
+			   };
+
+			   static const m3x2 _25 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, -1.0f, 1.0f) };
+			   static const m3x2 _27 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, 1.0f, 0.0f) };
+
 			   cbuffer Color : register(b0)
 			   {
 			       float4 _12_color : packoffset(c0);
@@ -55,11 +64,20 @@ var (
 		},
 		{
 			Textures:  []backend.TextureBinding{{Name: "tex", Binding: 0}},
-			GLSL100ES: "precision mediump float;\nprecision highp int;\n\nuniform mediump sampler2D tex;\n\nvarying vec2 vUV;\n\nvoid main()\n{\n    gl_FragData[0] = texture2D(tex, vUV);\n}\n\n",
-			GLSL300ES: "#version 300 es\nprecision mediump float;\nprecision highp int;\n\nuniform mediump sampler2D tex;\n\nlayout(location = 0) out vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n}\n\n",
-			GLSL130:   "#version 130\n\nuniform sampler2D tex;\n\nout vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n}\n\n",
-			GLSL150:   "#version 150\n\nuniform sampler2D tex;\n\nout vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n}\n\n",
+			GLSL100ES: "precision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform mediump sampler2D tex;\n\nvarying vec2 vUV;\n\nvoid main()\n{\n    gl_FragData[0] = texture2D(tex, vUV);\n}\n\n",
+			GLSL300ES: "#version 300 es\nprecision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform mediump sampler2D tex;\n\nlayout(location = 0) out vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n}\n\n",
+			GLSL130:   "#version 130\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform sampler2D tex;\n\nout vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n}\n\n",
+			GLSL150:   "#version 150\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform sampler2D tex;\n\nout vec4 fragColor;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n}\n\n",
 			/*
+			   struct m3x2
+			   {
+			       float3 r0;
+			       float3 r1;
+			   };
+
+			   static const m3x2 _27 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, -1.0f, 1.0f) };
+			   static const m3x2 _29 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, 1.0f, 0.0f) };
+
 			   Texture2D<float4> tex : register(t0);
 			   SamplerState _tex_sampler : register(s0);
 
@@ -93,6 +111,71 @@ var (
 			*/
 			HLSL: []byte{0x44, 0x58, 0x42, 0x43, 0xb7, 0x3f, 0x1d, 0xb1, 0x80, 0xcd, 0x80, 0xa3, 0x57, 0x9, 0xfb, 0x5a, 0x9f, 0x56, 0xd6, 0xda, 0x1, 0x0, 0x0, 0x0, 0x94, 0x2, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0xa4, 0x0, 0x0, 0x0, 0x10, 0x1, 0x0, 0x0, 0x8c, 0x1, 0x0, 0x0, 0x2c, 0x2, 0x0, 0x0, 0x60, 0x2, 0x0, 0x0, 0x41, 0x6f, 0x6e, 0x39, 0x64, 0x0, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x3c, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x28, 0x0, 0x1, 0x0, 0x24, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x3, 0xb0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x0, 0x8, 0xf, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0xb0, 0x0, 0x8, 0xe4, 0xa0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x8, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0xff, 0xff, 0x0, 0x0, 0x53, 0x48, 0x44, 0x52, 0x64, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x19, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0
 , 0x3, 0x0, 0x60, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x62, 0x10, 0x0, 0x3, 0x32, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x3, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x1, 0x53, 0x54, 0x41, 0x54, 0x74, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x44, 0x45, 0x46, 0x98, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xff, 0x0, 0x1, 0x0, 0x0, 0x6d, 0x0, 0x0, 0x0, 0x5c, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x69, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x5f, 0x74, 0x65, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x74, 0x65, 0x78, 0x0, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x0, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x0,
  0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x0, 0xab, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x0, 0xab, 0xab},
 		},
+		{
+			Textures:  []backend.TextureBinding{{Name: "ytex", Binding: 0}, {Name: "utex", Binding: 1}, {Name: "vtex", Binding: 2}},
+			GLSL100ES: "precision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform mediump sampler2D ytex;\nuniform mediump sampler2D utex;\nuniform mediump sampler2D vtex;\n\nvarying vec2 vUV;\n\nvec4 yuv2rgb(mediump sampler2D ytex_1, mediump sampler2D utex_1, mediump sampler2D vtex_1, vec2 vUV_1)\n{\n    float y = (texture2D(ytex_1, vUV_1).x - 0.0625) * 1.16429996490478515625;\n    float u = texture2D(utex_1, vUV_1).x - 0.5;\n    float v = texture2D(vtex_1, vUV_1).x - 0.5;\n    float r = y + (1.59580004215240478515625 * v);\n    float g = (y - (0.391730010509490966796875 * u)) - (0.812900006771087646484375 * v);\n    float b = y + (2.0169999599456787109375 * u);\n    return vec4(r, g, b, 1.0);\n}\n\nvoid main()\n{\n    highp vec2 param = vUV;\n    gl_FragData[0] = yuv2rgb(ytex, utex, vtex, param);\n}\n\n",
+			GLSL300ES: "#version 300 es\nprecision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform mediump sampler2D ytex;\nuniform mediump sampler2D utex;\nuniform mediump sampler2D vtex;\n\nlayout(location = 0) out vec4 fragColor;\nin vec2 vUV;\n\nvec4 yuv2rgb(mediump sampler2D ytex_1, mediump sampler2D utex_1, mediump sampler2D vtex_1, vec2 vUV_1)\n{\n    float y = (texture(ytex_1, vUV_1).x - 0.0625) * 1.16429996490478515625;\n    float u = texture(utex_1, vUV_1).x - 0.5;\n    float v = texture(vtex_1, vUV_1).x - 0.5;\n    float r = y + (1.59580004215240478515625 * v);\n    float g = (y - (0.391730010509490966796875 * u)) - (0.812900006771087646484375 * v);\n    float b = y + (2.0169999599456787109375 * u);\n    return vec4(r, g, b, 1.0);\n}\n\nvoid main()\n{\n    highp vec2 param = vUV;\n    fragColor = yuv2rgb(ytex, utex, vtex, param);\n}\n\n",
+			GLSL130:   "#version 130\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform sampler2D ytex;\nuniform sampler2D utex;\nuniform sampler2D vtex;\n\nout vec4 fragColor;\nin vec2 vUV;\n\nvec4 yuv2rgb(sampler2D ytex_1, sampler2D utex_1, sampler2D vtex_1, vec2 vUV_1)\n{\n    float y = (texture(ytex_1, vUV_1).x - 0.0625) * 1.16429996490478515625;\n    float u = texture(utex_1, vUV_1).x - 0.5;\n    float v = texture(vtex_1, vUV_1).x - 0.5;\n    float r = y + (1.59580004215240478515625 * v);\n    float g = (y - (0.391730010509490966796875 * u)) - (0.812900006771087646484375 * v);\n    float b = y + (2.0169999599456787109375 * u);\n    return vec4(r, g, b, 1.0);\n}\n\nvoid main()\n{\n    vec2 param = vUV;\n    fragColor = yuv2rgb(ytex, utex, vtex, param);\n}\n\n",
+			GLSL150:   "#version 150\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform sampler2D ytex;\nuniform sampler2D utex;\nuniform sampler2D vtex;\n\nout vec4 fragColor;\nin vec2 vUV;\n\nvec4 yuv2rgb(sampler2D ytex_1, sampler2D utex_1, sampler2D vtex_1, vec2 vUV_1)\n{\n    float y = (texture(ytex_1, vUV_1).x - 0.0625) * 1.16429996490478515625;\n    float u = texture(utex_1, vUV_1).x - 0.5;\n    float v = texture(vtex_1, vUV_1).x - 0.5;\n    float r = y + (1.59580004215240478515625 * v);\n    float g = (y - (0.391730010509490966796875 * u)) - (0.812900006771087646484375 * v);\n    float b = y + (2.0169999599456787109375 * u);\n    return vec4(r, g, b, 1.0);\n}\n\nvoid main()\n{\n    vec2 param = vUV;\n    fragColor = yuv2rgb(ytex, utex, vtex, param);\n}\n\n",
+			/*
+			   struct m3x2
+			   {
+			       float3 r0;
+			       float3 r1;
+			   };
+
+			   static const m3x2 _90 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, -1.0f, 1.0f) };
+			   static const m3x2 _92 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, 1.0f, 0.0f) };
+
+			   Texture2D<float4> ytex : register(t0);
+			   SamplerState _ytex_sampler : register(s0);
+			   Texture2D<float4> utex : register(t1);
+			   SamplerState _utex_sampler : register(s1);
+			   Texture2D<float4> vtex : register(t2);
+			   SamplerState _vtex_sampler : register(s2);
+
+			   static float4 fragColor;
+			   static float2 vUV;
+
+			   struct SPIRV_Cross_Input
+			   {
+			       float2 vUV : TEXCOORD0;
+			   };
+
+			   struct SPIRV_Cross_Output
+			   {
+			       float4 fragColor : SV_Target0;
+			   };
+
+			   float4 yuv2rgb(Texture2D<float4> ytex_1, SamplerState _ytex_1_sampler, Texture2D<float4> utex_1, SamplerState _utex_1_sampler, Texture2D<float4> vtex_1, SamplerState _vtex_1_sampler, float2 vUV_1)
+			   {
+			       float y = (ytex_1.Sample(_ytex_1_sampler, vUV_1).x - 0.0625f) * 1.16429996490478515625f;
+			       float u = utex_1.Sample(_utex_1_sampler, vUV_1).x - 0.5f;
+			       float v = vtex_1.Sample(_vtex_1_sampler, vUV_1).x - 0.5f;
+			       float r = y + (1.59580004215240478515625f * v);
+			       float g = (y - (0.391730010509490966796875f * u)) - (0.812900006771087646484375f * v);
+			       float b = y + (2.0169999599456787109375f * u);
+			       return float4(r, g, b, 1.0f);
+			   }
+
+			   void frag_main()
+			   {
+			       float2 param = vUV;
+			       fragColor = yuv2rgb(ytex, _ytex_sampler, utex, _utex_sampler, vtex, _vtex_sampler, param);
+			   }
+
+			   SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+			   {
+			       vUV = stage_input.vUV;
+			       frag_main();
+			       SPIRV_Cross_Output stage_output;
+			       stage_output.fragColor = fragColor;
+			       return stage_output;
+			   }
+
+			*/
+			HLSL: []byte{0x44, 0x58, 0x42, 0x43, 0x1f, 0xa2, 0x7, 0x1a, 0x7a, 0x8a, 0x91, 0x4b, 0x4a, 0xe7, 0x68, 0x64, 0x31, 0xa4, 0xfd, 0xd6, 0x1, 0x0, 0x0, 0x0, 0x14, 0x6, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0xb0, 0x1, 0x0, 0x0, 0xe8, 0x3, 0x0, 0x0, 0x64, 0x4, 0x0, 0x0, 0xac, 0x5, 0x0, 0x0, 0xe0, 0x5, 0x0, 0x0, 0x41, 0x6f, 0x6e, 0x39, 0x70, 0x1, 0x0, 0x0, 0x70, 0x1, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x40, 0x1, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x3, 0x0, 0x24, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x2, 0x2, 0x2, 0x0, 0x0, 0x2, 0xff, 0xff, 0x51, 0x0, 0x0, 0x5, 0x0, 0x0, 0xf, 0xa0, 0x0, 0x0, 0x80, 0xbd, 0xc8, 0x7, 0x95, 0x3f, 0x0, 0x0, 0x0, 0xbf, 0x2d, 0x43, 0xcc, 0x3f, 0x51, 0x0, 0x0, 0x5, 0x1, 0x0, 0xf, 0xa0, 0xd6, 0x90, 0xc8, 0x3e, 0x37, 0x1a, 0x50, 0x3f, 0x87, 0x16, 0x1, 0x40, 0x0, 0x0, 0x80, 0x3f, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x3, 0xb0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x
 0, 0x0, 0x90, 0x0, 0x8, 0xf, 0xa0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x1, 0x8, 0xf, 0xa0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x2, 0x8, 0xf, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0xb0, 0x1, 0x8, 0xe4, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x1, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0xb0, 0x0, 0x8, 0xe4, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x2, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0xb0, 0x2, 0x8, 0xe4, 0xa0, 0x2, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0xaa, 0xa0, 0x2, 0x0, 0x0, 0x3, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0xa0, 0x5, 0x0, 0x0, 0x3, 0x0, 0x0, 0x2, 0x80, 0x0, 0x0, 0x55, 0x80, 0x0, 0x0, 0x55, 0xa0, 0x4, 0x0, 0x0, 0x4, 0x0, 0x0, 0x4, 0x80, 0x0, 0x0, 0x0, 0x80, 0x1, 0x0, 0x0, 0xa1, 0x0, 0x0, 0x55, 0x80, 0x4, 0x0, 0x0, 0x4, 0x1, 0x0, 0x4, 0x80, 0x0, 0x0, 0x0, 0x80, 0x1, 0x0, 0xaa, 0xa0, 0x0, 0x0, 0x55, 0x80, 0x2, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x80, 0x2, 0x0, 0x0, 0x80, 0x0, 0x0, 0xaa, 0xa0, 0x4, 0x0, 0x0, 0x4, 0x1, 0x0, 0
 x2, 0x80, 0x0, 0x0, 0x0, 0x80, 0x1, 0x0, 0x55, 0xa1, 
0x0, 0x0, 0xaa, 0x80, 0x4, 0x0, 0x0, 0x4, 0x1, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0xff, 0xa0, 0x0, 0x0, 0x55, 0x80, 0x1, 0x0, 0x0, 0x2, 0x1, 0x0, 0x8, 0x80, 0x1, 0x0, 0xff, 0xa0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x8, 0xf, 0x80, 0x1, 0x0, 0xe4, 0x80, 0xff, 0xff, 0x0, 0x0, 0x53, 0x48, 0x44, 0x52, 0x30, 0x2, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x8c, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x2, 0x0, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x2, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x62, 0x10, 0x0, 0x3, 0x32, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x3, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x
 9, 0xf2, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x12, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0x38, 0x0, 0x0, 0xa, 0x32, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x40, 0x0, 0x0, 0xd6, 0x90, 0xc8, 0x3e, 0x87, 0x16, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x46, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x42, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x80, 0xbd, 0x32, 0x0, 0x0, 0xa, 0x12, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0xc8
 , 0x7, 0x95, 0x3f, 0xa, 0x0, 0x10, 0x80, 0x41, 0x0, 0
x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x0, 0x0, 0x9, 0x42, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0xc8, 0x7, 0x95, 0x3f, 0x1a, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x46, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x22, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0x32, 0x0, 0x0, 0xa, 0x22, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x0, 0x10, 0x80, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x37, 0x1a, 0x50, 0x3f, 0xa, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x7, 0x12, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x2d, 0x43, 0xcc, 0x3f, 0x32, 0x0, 0x0, 0x9, 0x12, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x
 10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0xc8, 0x7, 0x95, 0x3f, 0xa, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x0, 0x0, 0x5, 0x82, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3f, 0x3e, 0x0, 0x0, 0x1, 0x53, 0x54, 0x41, 0x54, 0x74, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x44, 0x45, 0x46, 0x40, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0,
  0x4, 0xff, 0xff, 0x0, 0x1, 0x0, 0x0, 0x15, 0x1, 0x0,
 0x0, 0xdc, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xea, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x6, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0xb, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x10, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x5f, 0x79, 0x74
 , 0x65, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x5f, 0x75, 0x74, 0x65, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x5f, 0x76, 0x74, 0x65, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x79, 0x74, 0x65, 0x78, 0x0, 0x75, 0x74, 0x65, 0x78, 0x0, 0x76, 0x74, 0x65, 0x78, 0x0, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x0, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x0, 0xab, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x
 0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 
0x0, 0x0, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x0, 0xab, 0xab},
+		},
 	}
 	shader_blit_vert = backend.ShaderSources{
 		Inputs: []backend.InputLocation{{Name: "pos", Location: 0, Semantic: "POSITION", SemanticIndex: 0, Type: 0x0, Size: 2}, {Name: "uv", Location: 1, Semantic: "NORMAL", SemanticIndex: 0, Type: 0x0, Size: 2}},
@@ -183,19 +266,28 @@ var (
 				Locations: []backend.UniformLocation{{Name: "_12._color", Type: 0x0, Size: 4, Offset: 0}},
 				Size:      16,
 			},
-			Textures:  []backend.TextureBinding{{Name: "cover", Binding: 1}},
-			GLSL100ES: "precision mediump float;\nprecision highp int;\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nuniform mediump sampler2D cover;\n\nvarying highp vec2 vCoverUV;\nvarying vec2 vUV;\n\nvoid main()\n{\n    gl_FragData[0] = _12._color;\n    float cover_1 = abs(texture2D(cover, vCoverUV).x);\n    gl_FragData[0] *= cover_1;\n}\n\n",
-			GLSL300ES: "#version 300 es\nprecision mediump float;\nprecision highp int;\n\nlayout(std140) uniform Color\n{\n    vec4 _color;\n} _12;\n\nuniform mediump sampler2D cover;\n\nlayout(location = 0) out vec4 fragColor;\nin highp vec2 vCoverUV;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
-			GLSL130:   "#version 130\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nuniform sampler2D cover;\n\nout vec4 fragColor;\nin vec2 vCoverUV;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
-			GLSL150:   "#version 150\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nuniform sampler2D cover;\n\nout vec4 fragColor;\nin vec2 vCoverUV;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
+			Textures:  []backend.TextureBinding{{Name: "cover", Binding: 4}},
+			GLSL100ES: "precision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nuniform mediump sampler2D cover;\n\nvarying highp vec2 vCoverUV;\nvarying vec2 vUV;\n\nvoid main()\n{\n    gl_FragData[0] = _12._color;\n    float cover_1 = abs(texture2D(cover, vCoverUV).x);\n    gl_FragData[0] *= cover_1;\n}\n\n",
+			GLSL300ES: "#version 300 es\nprecision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nlayout(std140) uniform Color\n{\n    vec4 _color;\n} _12;\n\nuniform mediump sampler2D cover;\n\nlayout(location = 0) out vec4 fragColor;\nin highp vec2 vCoverUV;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
+			GLSL130:   "#version 130\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nuniform sampler2D cover;\n\nout vec4 fragColor;\nin vec2 vCoverUV;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
+			GLSL150:   "#version 150\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nstruct Color\n{\n    vec4 _color;\n};\n\nuniform Color _12;\n\nuniform sampler2D cover;\n\nout vec4 fragColor;\nin vec2 vCoverUV;\nin vec2 vUV;\n\nvoid main()\n{\n    fragColor = _12._color;\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
 			/*
+			   struct m3x2
+			   {
+			       float3 r0;
+			       float3 r1;
+			   };
+
+			   static const m3x2 _44 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, -1.0f, 1.0f) };
+			   static const m3x2 _46 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, 1.0f, 0.0f) };
+
 			   cbuffer Color : register(b0)
 			   {
 			       float4 _12_color : packoffset(c0);
 			   };
 
-			   Texture2D<float4> cover : register(t1);
-			   SamplerState _cover_sampler : register(s1);
+			   Texture2D<float4> cover : register(t4);
+			   SamplerState _cover_sampler : register(s4);
 
 			   static float4 fragColor;
 			   static float2 vCoverUV;
@@ -230,19 +322,28 @@ var (
 			   }
 
 			*/
-			HLSL: []byte{0x44, 0x58, 0x42, 0x43, 0x94, 0xe9, 0xc3, 0x12, 0xd8, 0xfb, 0xb, 0x3b, 0xe, 0xda, 0x43, 0x25, 0xcb, 0x53, 0x1c, 0x9d, 0x1, 0x0, 0x0, 0x0, 0x84, 0x3, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0xcc, 0x0, 0x0, 0x0, 0x74, 0x1, 0x0, 0x0, 0xf0, 0x1, 0x0, 0x0, 0x4, 0x3, 0x0, 0x0, 0x50, 0x3, 0x0, 0x0, 0x41, 0x6f, 0x6e, 0x39, 0x8c, 0x0, 0x0, 0x0, 0x8c, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x58, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x1, 0x0, 0x28, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x34, 0x0, 0x1, 0x0, 0x24, 0x0, 0x0, 0x0, 0x34, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0xf, 0xb0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x0, 0x8, 0xf, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0xb0, 0x0, 0x8, 0xe4, 0xa0, 0x23, 0x0, 0x0, 0x2, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x80, 0x5, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0x0, 0x80, 0x0
 , 0x0, 0xe4, 0xa0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x8, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0xff, 0xff, 0x0, 0x0, 0x53, 0x48, 0x44, 0x52, 0xa0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x59, 0x0, 0x0, 0x4, 0x46, 0x8e, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x62, 0x10, 0x0, 0x3, 0x32, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x3, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x2, 0x1, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x9, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x10, 0x80, 0x81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x8e, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x1, 0
 x53, 0x54, 0x41, 0x54, 0x74, 0x0, 0x0, 0x0, 0x3, 0x0,
 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x44, 0x45, 0x46, 0xc, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x98, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xff, 0x0, 0x1, 0x0, 0x0, 0xe4, 0x0, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8b, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0
 x0, 0xff, 0xff, 0xff, 0xff, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x91, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x0, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x0, 0xab, 0x91, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xb0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xd4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, 0x31, 0x32, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x0, 0xab, 0xab, 0x1, 0x0, 0x3, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 
 0x6c, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x0, 
0x49, 0x53, 0x47, 0x4e, 0x44, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x0, 0xab, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x0, 0xab, 0xab},
+			HLSL: []byte{0x44, 0x58, 0x42, 0x43, 0x5c, 0x8a, 0x5f, 0x1f, 0x2d, 0xe1, 0x56, 0x53, 0xa, 0x3b, 0x7f, 0x19, 0x1b, 0xae, 0x62, 0xd9, 0x1, 0x0, 0x0, 0x0, 0x84, 0x3, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0xcc, 0x0, 0x0, 0x0, 0x74, 0x1, 0x0, 0x0, 0xf0, 0x1, 0x0, 0x0, 0x4, 0x3, 0x0, 0x0, 0x50, 0x3, 0x0, 0x0, 0x41, 0x6f, 0x6e, 0x39, 0x8c, 0x0, 0x0, 0x0, 0x8c, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x58, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x1, 0x0, 0x28, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x34, 0x0, 0x1, 0x0, 0x24, 0x0, 0x0, 0x0, 0x34, 0x0, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0xf, 0xb0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x0, 0x8, 0xf, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0xb0, 0x0, 0x8, 0xe4, 0xa0, 0x23, 0x0, 0x0, 0x2, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x80, 0x5, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0x0, 0x80, 0x
 0, 0x0, 0xe4, 0xa0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x8, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0xff, 0xff, 0x0, 0x0, 0x53, 0x48, 0x44, 0x52, 0xa0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x59, 0x0, 0x0, 0x4, 0x46, 0x8e, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x62, 0x10, 0x0, 0x3, 0x32, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x3, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x2, 0x1, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x9, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x10, 0x80, 0x81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x8e, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x1, 
 0x53, 0x54, 0x41, 0x54, 0x74, 0x0, 0x0, 0x0, 0x3, 0x0
, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x44, 0x45, 0x46, 0xc, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x98, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xff, 0x0, 0x1, 0x0, 0x0, 0xe4, 0x0, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8b, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 
 0x0, 0xff, 0xff, 0xff, 0xff, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x91, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x0, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x0, 0xab, 0x91, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xb0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xd4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, 0x31, 0x32, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x0, 0xab, 0xab, 0x1, 0x0, 0x3, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69,
  0x6c, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x0,
 0x49, 0x53, 0x47, 0x4e, 0x44, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x0, 0xab, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x0, 0xab, 0xab},
 		},
 		{
-			Textures:  []backend.TextureBinding{{Name: "tex", Binding: 0}, {Name: "cover", Binding: 1}},
-			GLSL100ES: "precision mediump float;\nprecision highp int;\n\nuniform mediump sampler2D tex;\nuniform mediump sampler2D cover;\n\nvarying vec2 vUV;\nvarying highp vec2 vCoverUV;\n\nvoid main()\n{\n    gl_FragData[0] = texture2D(tex, vUV);\n    float cover_1 = abs(texture2D(cover, vCoverUV).x);\n    gl_FragData[0] *= cover_1;\n}\n\n",
-			GLSL300ES: "#version 300 es\nprecision mediump float;\nprecision highp int;\n\nuniform mediump sampler2D tex;\nuniform mediump sampler2D cover;\n\nlayout(location = 0) out vec4 fragColor;\nin vec2 vUV;\nin highp vec2 vCoverUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
-			GLSL130:   "#version 130\n\nuniform sampler2D tex;\nuniform sampler2D cover;\n\nout vec4 fragColor;\nin vec2 vUV;\nin vec2 vCoverUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
-			GLSL150:   "#version 150\n\nuniform sampler2D tex;\nuniform sampler2D cover;\n\nout vec4 fragColor;\nin vec2 vUV;\nin vec2 vCoverUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
+			Textures:  []backend.TextureBinding{{Name: "tex", Binding: 0}, {Name: "cover", Binding: 4}},
+			GLSL100ES: "precision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform mediump sampler2D tex;\nuniform mediump sampler2D cover;\n\nvarying vec2 vUV;\nvarying highp vec2 vCoverUV;\n\nvoid main()\n{\n    gl_FragData[0] = texture2D(tex, vUV);\n    float cover_1 = abs(texture2D(cover, vCoverUV).x);\n    gl_FragData[0] *= cover_1;\n}\n\n",
+			GLSL300ES: "#version 300 es\nprecision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform mediump sampler2D tex;\nuniform mediump sampler2D cover;\n\nlayout(location = 0) out vec4 fragColor;\nin vec2 vUV;\nin highp vec2 vCoverUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
+			GLSL130:   "#version 130\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform sampler2D tex;\nuniform sampler2D cover;\n\nout vec4 fragColor;\nin vec2 vUV;\nin vec2 vCoverUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
+			GLSL150:   "#version 150\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform sampler2D tex;\nuniform sampler2D cover;\n\nout vec4 fragColor;\nin vec2 vUV;\nin vec2 vCoverUV;\n\nvoid main()\n{\n    fragColor = texture(tex, vUV);\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
 			/*
+			   struct m3x2
+			   {
+			       float3 r0;
+			       float3 r1;
+			   };
+
+			   static const m3x2 _41 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, -1.0f, 1.0f) };
+			   static const m3x2 _43 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, 1.0f, 0.0f) };
+
 			   Texture2D<float4> tex : register(t0);
 			   SamplerState _tex_sampler : register(s0);
-			   Texture2D<float4> cover : register(t1);
-			   SamplerState _cover_sampler : register(s1);
+			   Texture2D<float4> cover : register(t4);
+			   SamplerState _cover_sampler : register(s4);
 
 			   static float4 fragColor;
 			   static float2 vUV;
@@ -277,7 +378,79 @@ var (
 			   }
 
 			*/
-			HLSL: []byte{0x44, 0x58, 0x42, 0x43, 0xcb, 0xa0, 0xb0, 0x5b, 0x6e, 0x48, 0xa6, 0x5a, 0x1c, 0x34, 0x50, 0xfe, 0xd4, 0x6f, 0x72, 0xb5, 0x1, 0x0, 0x0, 0x0, 0xbc, 0x3, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0xec, 0x0, 0x0, 0x0, 0xcc, 0x1, 0x0, 0x0, 0x48, 0x2, 0x0, 0x0, 0x3c, 0x3, 0x0, 0x0, 0x88, 0x3, 0x0, 0x0, 0x41, 0x6f, 0x6e, 0x39, 0xac, 0x0, 0x0, 0x0, 0xac, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x2, 0x0, 0x24, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x2, 0xff, 0xff, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0xf, 0xb0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x0, 0x8, 0xf, 0xa0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x1, 0x8, 0xf, 0xa0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x3, 0x80, 0x0, 0x0, 0x1b, 0xb0, 0x42, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0x0, 0x8, 0xe4, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x1, 0x0, 0xf, 0x8
 0, 0x0, 0x0, 0xe4, 0xb0, 0x1, 0x8, 0xe4, 0xa0, 0x23, 0x0, 0x0, 0x2, 0x1, 0x0, 0x1, 0x80, 0x1, 0x0, 0x0, 0x80, 0x5, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0x1, 0x0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x2, 0x0, 0x8, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0xff, 0xff, 0x0, 0x0, 0x53, 0x48, 0x44, 0x52, 0xd8, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x36, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x62, 0x10, 0x0, 0x3, 0x32, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x62, 0x10, 0x0, 0x3, 0xc2, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x3, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe6, 0x1a, 0x10, 0x0, 0x0, 0x0, 0x
 0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x
0, 0x60, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x46, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x8, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0xe, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x10, 0x80, 0x81, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x1, 0x53, 0x54, 0x41, 0x54, 0x74, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x
 0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x44, 0x45, 0x46, 0xec, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xff, 0x0, 0x1, 0x0, 0x0, 0xc2, 0x0, 0x0, 0x0, 0x9c, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xa9, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xb8, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0xbc, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x5f, 0x74, 0x65, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0
 x72, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 
0x0, 0x74, 0x65, 0x78, 0x0, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x0, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x0, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x44, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xc, 0x0, 0x0, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x0, 0xab, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x0, 0xab, 0xab},
+			HLSL: []byte{0x44, 0x58, 0x42, 0x43, 0x59, 0x85, 0xda, 0xe2, 0x44, 0xf4, 0xf7, 0x56, 0xd0, 0x87, 0xcd, 0x6d, 0xc9, 0x52, 0x60, 0xd5, 0x1, 0x0, 0x0, 0x0, 0xbc, 0x3, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0xec, 0x0, 0x0, 0x0, 0xcc, 0x1, 0x0, 0x0, 0x48, 0x2, 0x0, 0x0, 0x3c, 0x3, 0x0, 0x0, 0x88, 0x3, 0x0, 0x0, 0x41, 0x6f, 0x6e, 0x39, 0xac, 0x0, 0x0, 0x0, 0xac, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x2, 0x0, 0x24, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x1, 0x0, 0x0, 0x2, 0xff, 0xff, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0xf, 0xb0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x0, 0x8, 0xf, 0xa0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x1, 0x8, 0xf, 0xa0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x3, 0x80, 0x0, 0x0, 0x1b, 0xb0, 0x42, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0x0, 0x8, 0xe4, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x1, 0x0, 0xf, 0x8
 0, 0x0, 0x0, 0xe4, 0xb0, 0x1, 0x8, 0xe4, 0xa0, 0x23, 0x0, 0x0, 0x2, 0x1, 0x0, 0x1, 0x80, 0x1, 0x0, 0x0, 0x80, 0x5, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0x1, 0x0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x2, 0x0, 0x8, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0xff, 0xff, 0x0, 0x0, 0x53, 0x48, 0x44, 0x52, 0xd8, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x36, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x62, 0x10, 0x0, 0x3, 0x32, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x62, 0x10, 0x0, 0x3, 0xc2, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x3, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe6, 0x1a, 0x10, 0x0, 0x0, 0x0, 0x
 0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x
0, 0x60, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x46, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x8, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0xe, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x10, 0x80, 0x81, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x1, 0x53, 0x54, 0x41, 0x54, 0x74, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x
 0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x44, 0x45, 0x46, 0xec, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xff, 0x0, 0x1, 0x0, 0x0, 0xc2, 0x0, 0x0, 0x0, 0x9c, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xa9, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xb8, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0xbc, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x5f, 0x74, 0x65, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0
 x72, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 
0x0, 0x74, 0x65, 0x78, 0x0, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x0, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x0, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x44, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xc, 0x0, 0x0, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x0, 0xab, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x0, 0xab, 0xab},
+		},
+		{
+			Textures:  []backend.TextureBinding{{Name: "ytex", Binding: 0}, {Name: "utex", Binding: 1}, {Name: "vtex", Binding: 2}, {Name: "cover", Binding: 4}},
+			GLSL100ES: "precision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform mediump sampler2D ytex;\nuniform mediump sampler2D utex;\nuniform mediump sampler2D vtex;\nuniform mediump sampler2D cover;\n\nvarying vec2 vUV;\nvarying highp vec2 vCoverUV;\n\nvec4 yuv2rgb(mediump sampler2D ytex_1, mediump sampler2D utex_1, mediump sampler2D vtex_1, vec2 vUV_1)\n{\n    float y = (texture2D(ytex_1, vUV_1).x - 0.0625) * 1.16429996490478515625;\n    float u = texture2D(utex_1, vUV_1).x - 0.5;\n    float v = texture2D(vtex_1, vUV_1).x - 0.5;\n    float r = y + (1.59580004215240478515625 * v);\n    float g = (y - (0.391730010509490966796875 * u)) - (0.812900006771087646484375 * v);\n    float b = y + (2.0169999599456787109375 * u);\n    return vec4(r, g, b, 1.0);\n}\n\nvoid main()\n{\n    highp vec2 param = vUV;\n    gl_FragData[0] = yuv2rgb(ytex, utex, vtex, param);\n    float cover_1 = abs(texture2D(cover, vCoverUV).x);\n    gl_FragData[0] *= cov
 er_1;\n}\n\n",
+			GLSL300ES: "#version 300 es\nprecision mediump float;\nprecision highp int;\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform mediump sampler2D ytex;\nuniform mediump sampler2D utex;\nuniform mediump sampler2D vtex;\nuniform mediump sampler2D cover;\n\nlayout(location = 0) out vec4 fragColor;\nin vec2 vUV;\nin highp vec2 vCoverUV;\n\nvec4 yuv2rgb(mediump sampler2D ytex_1, mediump sampler2D utex_1, mediump sampler2D vtex_1, vec2 vUV_1)\n{\n    float y = (texture(ytex_1, vUV_1).x - 0.0625) * 1.16429996490478515625;\n    float u = texture(utex_1, vUV_1).x - 0.5;\n    float v = texture(vtex_1, vUV_1).x - 0.5;\n    float r = y + (1.59580004215240478515625 * v);\n    float g = (y - (0.391730010509490966796875 * u)) - (0.812900006771087646484375 * v);\n    float b = y + (2.0169999599456787109375 * u);\n    return vec4(r, g, b, 1.0);\n}\n\nvoid main()\n{\n    highp vec2 param = vUV;\n    fragColor = yuv2rgb(ytex, utex, vtex, param);\n    float cover_1 = abs(texture(cover, vCov
 erUV).x);\n    fragColor *= cover_1;\n}\n\n",
+			GLSL130:   "#version 130\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform sampler2D ytex;\nuniform sampler2D utex;\nuniform sampler2D vtex;\nuniform sampler2D cover;\n\nout vec4 fragColor;\nin vec2 vUV;\nin vec2 vCoverUV;\n\nvec4 yuv2rgb(sampler2D ytex_1, sampler2D utex_1, sampler2D vtex_1, vec2 vUV_1)\n{\n    float y = (texture(ytex_1, vUV_1).x - 0.0625) * 1.16429996490478515625;\n    float u = texture(utex_1, vUV_1).x - 0.5;\n    float v = texture(vtex_1, vUV_1).x - 0.5;\n    float r = y + (1.59580004215240478515625 * v);\n    float g = (y - (0.391730010509490966796875 * u)) - (0.812900006771087646484375 * v);\n    float b = y + (2.0169999599456787109375 * u);\n    return vec4(r, g, b, 1.0);\n}\n\nvoid main()\n{\n    vec2 param = vUV;\n    fragColor = yuv2rgb(ytex, utex, vtex, param);\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
+			GLSL150:   "#version 150\n\nstruct m3x2\n{\n    vec3 r0;\n    vec3 r1;\n};\n\nuniform sampler2D ytex;\nuniform sampler2D utex;\nuniform sampler2D vtex;\nuniform sampler2D cover;\n\nout vec4 fragColor;\nin vec2 vUV;\nin vec2 vCoverUV;\n\nvec4 yuv2rgb(sampler2D ytex_1, sampler2D utex_1, sampler2D vtex_1, vec2 vUV_1)\n{\n    float y = (texture(ytex_1, vUV_1).x - 0.0625) * 1.16429996490478515625;\n    float u = texture(utex_1, vUV_1).x - 0.5;\n    float v = texture(vtex_1, vUV_1).x - 0.5;\n    float r = y + (1.59580004215240478515625 * v);\n    float g = (y - (0.391730010509490966796875 * u)) - (0.812900006771087646484375 * v);\n    float b = y + (2.0169999599456787109375 * u);\n    return vec4(r, g, b, 1.0);\n}\n\nvoid main()\n{\n    vec2 param = vUV;\n    fragColor = yuv2rgb(ytex, utex, vtex, param);\n    float cover_1 = abs(texture(cover, vCoverUV).x);\n    fragColor *= cover_1;\n}\n\n",
+			/*
+			   struct m3x2
+			   {
+			       float3 r0;
+			       float3 r1;
+			   };
+
+			   static const m3x2 _101 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, -1.0f, 1.0f) };
+			   static const m3x2 _103 = { float3(1.0f, 0.0f, 0.0f), float3(0.0f, 1.0f, 0.0f) };
+
+			   Texture2D<float4> ytex : register(t0);
+			   SamplerState _ytex_sampler : register(s0);
+			   Texture2D<float4> utex : register(t1);
+			   SamplerState _utex_sampler : register(s1);
+			   Texture2D<float4> vtex : register(t2);
+			   SamplerState _vtex_sampler : register(s2);
+			   Texture2D<float4> cover : register(t4);
+			   SamplerState _cover_sampler : register(s4);
+
+			   static float4 fragColor;
+			   static float2 vUV;
+			   static float2 vCoverUV;
+
+			   struct SPIRV_Cross_Input
+			   {
+			       float2 vCoverUV : TEXCOORD0;
+			       float2 vUV : TEXCOORD1;
+			   };
+
+			   struct SPIRV_Cross_Output
+			   {
+			       float4 fragColor : SV_Target0;
+			   };
+
+			   float4 yuv2rgb(Texture2D<float4> ytex_1, SamplerState _ytex_1_sampler, Texture2D<float4> utex_1, SamplerState _utex_1_sampler, Texture2D<float4> vtex_1, SamplerState _vtex_1_sampler, float2 vUV_1)
+			   {
+			       float y = (ytex_1.Sample(_ytex_1_sampler, vUV_1).x - 0.0625f) * 1.16429996490478515625f;
+			       float u = utex_1.Sample(_utex_1_sampler, vUV_1).x - 0.5f;
+			       float v = vtex_1.Sample(_vtex_1_sampler, vUV_1).x - 0.5f;
+			       float r = y + (1.59580004215240478515625f * v);
+			       float g = (y - (0.391730010509490966796875f * u)) - (0.812900006771087646484375f * v);
+			       float b = y + (2.0169999599456787109375f * u);
+			       return float4(r, g, b, 1.0f);
+			   }
+
+			   void frag_main()
+			   {
+			       float2 param = vUV;
+			       fragColor = yuv2rgb(ytex, _ytex_sampler, utex, _utex_sampler, vtex, _vtex_sampler, param);
+			       float cover_1 = abs(cover.Sample(_cover_sampler, vCoverUV).x);
+			       fragColor *= cover_1;
+			   }
+
+			   SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+			   {
+			       vUV = stage_input.vUV;
+			       vCoverUV = stage_input.vCoverUV;
+			       frag_main();
+			       SPIRV_Cross_Output stage_output;
+			       stage_output.fragColor = fragColor;
+			       return stage_output;
+			   }
+
+			*/
+			HLSL: []byte{0x44, 0x58, 0x42, 0x43, 0x37, 0x7f, 0x44, 0x70, 0x7c, 0xbd, 0x8b, 0x33, 0x70, 0x43, 0x59, 0xd9, 0xb5, 0xeb, 0x39, 0x63, 0x1, 0x0, 0x0, 0x0, 0x34, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0xf8, 0x1, 0x0, 0x0, 0x9c, 0x4, 0x0, 0x0, 0x18, 0x5, 0x0, 0x0, 0xb4, 0x6, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x41, 0x6f, 0x6e, 0x39, 0xb8, 0x1, 0x0, 0x0, 0xb8, 0x1, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0x84, 0x1, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x34, 0x0, 0x4, 0x0, 0x24, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x2, 0x2, 0x2, 0x0, 0x4, 0x4, 0x3, 0x0, 0x0, 0x2, 0xff, 0xff, 0x51, 0x0, 0x0, 0x5, 0x0, 0x0, 0xf, 0xa0, 0x0, 0x0, 0x80, 0xbd, 0xc8, 0x7, 0x95, 0x3f, 0x0, 0x0, 0x0, 0xbf, 0x2d, 0x43, 0xcc, 0x3f, 0x51, 0x0, 0x0, 0x5, 0x1, 0x0, 0xf, 0xa0, 0xd6, 0x90, 0xc8, 0x3e, 0x37, 0x1a, 0x50, 0x3f, 0x87, 0x16, 0x1, 0x40, 0x0, 0x0, 0x80, 0x3f, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0xf, 0xb0, 0x1f, 0x
 0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x0, 0x8, 0xf, 0xa0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x1, 0x8, 0xf, 0xa0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x2, 0x8, 0xf, 0xa0, 0x1f, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x90, 0x3, 0x8, 0xf, 0xa0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x3, 0x80, 0x0, 0x0, 0x1b, 0xb0, 0x42, 0x0, 0x0, 0x3, 0x1, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0xb0, 0x3, 0x8, 0xe4, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x2, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0x0, 0x8, 0xe4, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x3, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0x1, 0x8, 0xe4, 0xa0, 0x42, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0x2, 0x8, 0xe4, 0xa0, 0x23, 0x0, 0x0, 0x2, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x80, 0x2, 0x0, 0x0, 0x3, 0x0, 0x0, 0x4, 0x80, 0x2, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0xa0, 0x5, 0x0, 0x0, 0x3, 0x0, 0x0, 0x4, 0x80, 0x0, 0x0, 0xaa, 0x80, 0x0, 0x0, 0x55, 0xa0, 0x2, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0xaa, 0xa0, 0x2, 0x0, 0x0, 0x3, 0x0, 0x0, 0
 x8, 0x80, 0x3, 0x0, 0x0, 0x80, 0x0, 0x0, 0xaa, 0xa0, 
0x4, 0x0, 0x0, 0x4, 0x1, 0x0, 0x1, 0x80, 0x0, 0x0, 0xff, 0x80, 0x1, 0x0, 0x0, 0xa1, 0x0, 0x0, 0xaa, 0x80, 0x4, 0x0, 0x0, 0x4, 0x2, 0x0, 0x4, 0x80, 0x0, 0x0, 0xff, 0x80, 0x1, 0x0, 0xaa, 0xa0, 0x0, 0x0, 0xaa, 0x80, 0x4, 0x0, 0x0, 0x4, 0x2, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0xff, 0xa0, 0x0, 0x0, 0xaa, 0x80, 0x4, 0x0, 0x0, 0x4, 0x2, 0x0, 0x2, 0x80, 0x0, 0x0, 0x0, 0x80, 0x1, 0x0, 0x55, 0xa1, 0x1, 0x0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x2, 0x2, 0x0, 0x8, 0x80, 0x1, 0x0, 0xff, 0xa0, 0x5, 0x0, 0x0, 0x3, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0x55, 0x80, 0x2, 0x0, 0xe4, 0x80, 0x1, 0x0, 0x0, 0x2, 0x0, 0x8, 0xf, 0x80, 0x0, 0x0, 0xe4, 0x80, 0xff, 0xff, 0x0, 0x0, 0x53, 0x48, 0x44, 0x52, 0x9c, 0x2, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0xa7, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x3, 0x0, 0x60, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x
 58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x2, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x58, 0x18, 0x0, 0x4, 0x0, 0x70, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x55, 0x55, 0x0, 0x0, 0x62, 0x10, 0x0, 0x3, 0x32, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x62, 0x10, 0x0, 0x3, 0xc2, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x3, 0xf2, 0x20, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x2, 0x3, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe6, 0x1a, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x12, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0x38, 0x0, 0x0, 0xa, 0x32, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x10, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x2, 0x40, 0x0, 0x0, 0xd6, 0x90, 
0xc8, 0x3e, 0x87, 0x16, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0xe6, 0x1a, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x42, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x80, 0xbd, 0x32, 0x0, 0x0, 0xa, 0x12, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0xc8, 0x7, 0x95, 0x3f, 0xa, 0x0, 0x10, 0x80, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x0, 0x0, 0x9, 0x42, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0xc8, 0x7, 0x95, 0x3f, 0x1a, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x2, 0x0, 0x0, 0x0, 0xe6, 0x1a, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x2, 0x0, 0x
 0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x22, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x10, 0x0, 0x2, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0x32, 0x0, 0x0, 0xa, 0x22, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1a, 0x0, 0x10, 0x80, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x37, 0x1a, 0x50, 0x3f, 0xa, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x7, 0x12, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x2d, 0x43, 0xcc, 0x3f, 0x32, 0x0, 0x0, 0x9, 0x12, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0xc8, 0x7, 0x95, 0x3f, 0xa, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x7e, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x60, 0x10, 0x0, 0x4, 0x0, 0x0, 0x0, 0x36, 0x0, 0x0, 0x5, 0x82, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0, 0x0, 0x80, 
 0x3f, 0x38, 0x0, 0x0, 0x8, 0xf2, 0x20, 0x10, 0x0, 0x0
, 0x0, 0x0, 0x0, 0x6, 0x0, 0x10, 0x80, 0x81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0xe, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x1, 0x53, 0x54, 0x41, 0x54, 0x74, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x44, 0x45, 0x46, 0x94, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xff, 0x0, 0x1, 0x0, 0x0, 0x6a, 0x1, 0x0, 0x0, 0x1c, 0x1, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x1, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x38, 0x1, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x46, 0x1, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x55, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x5a, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x5f, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x
 4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x2, 0x0, 0
x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x64, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x5f, 0x79, 0x74, 0x65, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x5f, 0x75, 0x74, 0x65, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x5f, 0x76, 0x74, 0x65, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0, 0x79, 0x74, 0x65, 0x78, 0x0, 0x75, 0x74, 0x65, 0x78, 0x0, 0x76, 0x74, 0x65, 0x78, 0x0, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x0, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x0, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x44, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x8, 0x0
 , 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xc, 0x0, 0x0, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x0, 0xab, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x0, 0xab, 0xab},
 		},
 	}
 	shader_cover_vert = backend.ShaderSources{
-- 
2.26.2

Re: [PATCH gio 1/2] gpu: native yuv support

Details
Message ID
<C3ZI0VPSZP2U.7GGXGCLQXVRI@themachine>
In-Reply-To
<159388339974.26803.16846442073837397453-1@git.sr.ht> (view parent)
DKIM signature
pass
Download raw message
> I hope this addresses all the comments except for "YStride check". I
> believe the check is unnecessary because width could be smaller than the
> the stride as a normal case when alignment is needed.

Responded below. I don't think you can avoid verifying the YStride in NewImageOp.

> One thing I am not
> sure is whether `texUnits [3]*gpuTexture` should be updated to 4.

Have you tried drawing a clipped YUV image? I'm not sure you're using all 4
texture units without clipping.

Speaking of which, please add a test to internal/rendertest to make sure the
feature works correctly and won't bit-rot. Don't forget to add a clipped YUV
image test.

On Sat Jul 4, 2020 at 10:08, ~dejadeja9 wrote:
> From: Deja Deja <dejadejade9@outlook.com>
> diff --git a/gpu/gpu.go b/gpu/gpu.go
> index 321b2a8..6a96ad1 100644
> --- a/gpu/gpu.go
> +++ b/gpu/gpu.go
> @@ -383,22 +395,68 @@ func (g *GPU) Profile() string {
>  	return g.profile
>  }
>  
> -func (r *renderer) texHandle(t *texture) backend.Texture {
> -	if t.tex != nil {
> +func (r *renderer) bindTexture(t *texture) {
> +	tex := r.texHandle(t)
> +	for i, t := range tex {
> +		r.ctx.BindTexture(i, t)
> +	}
> +}
> +
> +func (r *renderer) texHandle(t *texture) []backend.Texture {
> +	if len(t.tex) > 0 {
>  		return t.tex
>  	}
> -	tex, err := r.ctx.NewTexture(backend.TextureFormatSRGB, t.src.Bounds().Dx(), t.src.Bounds().Dy(), backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
> -	if err != nil {
> -		panic(err)
> +
> +	w, h := t.src.Bounds().Dx(), t.src.Bounds().Dy()
> +	switch src := t.src.(type) {
> +	case *image.RGBA:
> +		tex, err := r.ctx.NewTexture(backend.TextureFormatSRGB, src.Bounds().Dx(), src.Bounds().Dy(), backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
> +		if err != nil {
> +			panic(err)
> +		}
> +		tex.Upload(src.Pix, src.Bounds().Dx(), src.Bounds().Dy(), 4)
> +		t.tex = append(t.tex, tex)
> +	case *image.YCbCr:
> +		//use YStride instead of Bounds().Dx() as Bounds().Dx() could be smaller than YStride due to padding

I still don't understand why you're not using (Y)Stride in both RGBA and TCbCr
cases, or Dx in both cases. If Dx < YStride the texture will still be wrong, or
at least have an unexpected width.

I'd say you should use Dx in both cases. If there is (unexpected) padding,
NewImageOp should fall back to an image copy. And sure, glTexSubImage or
glPixelStore may be useful to support more strides, but that's a future change.

Another reason to use Dx is that YStride is in bytes, while Dx is in pixels.
That doesn't matter in practice for single-channel textures, but is confusing.

> +		w = src.YStride
> +		ytex, err := r.ctx.NewTexture(backend.TextureFormatLuminance, w, h, backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
> +		if err != nil {
> +			panic(err)
> +		}
> +		ytex.Upload(src.Y, w, h, 1)
> +
> +		wsub, hsub := 1, 1
> +		switch src.SubsampleRatio {
> +		case image.YCbCrSubsampleRatio420:
> +			wsub, hsub = 2, 2
> +		case image.YCbCrSubsampleRatio444:
> +			break
> +		case image.YCbCrSubsampleRatio422:
> +			wsub, hsub = 2, 1
> +		}
> +
> +		utex, err := r.ctx.NewTexture(backend.TextureFormatLuminance, w/wsub, h/hsub, backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
> +		if err != nil {
> +			panic(err)
> +		}
> +		utex.Upload(src.Cb, w/wsub, h/hsub, 1)
> +
> +		vtex, err := r.ctx.NewTexture(backend.TextureFormatLuminance, w/wsub, h/hsub, backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
> +		if err != nil {
> +			panic(err)
> +		}

Are 2-channel textures available in both OpenGL ES and D3D11 (I don't know)?
If so, you can pack the U and V channels into one texture and one shader lookup.

Ok to leave for a future change.

> +		vtex.Upload(src.Cr, w/wsub, h/hsub, 1)
> +		t.tex = append(t.tex, ytex, utex, vtex)
>  	}
> -	tex.Upload(t.src)
> -	t.tex = tex
> +
>  	return t.tex
>  }
>  
> @@ -847,10 +925,10 @@ func (d *drawState) materialFor(cache *resourceCache, rect f32.Rectangle, off f3
>  		m.material = materialColor
>  		m.color = f32color.RGBAFromSRGB(d.color)
>  		m.opaque = m.color.A == 1.0
> -	case materialTexture:
> -		m.material = materialTexture
> +	case materialTexture, materialYCbCr:
> +		m.material = d.matType
>  		dr := boundRectF(rect.Add(off))


> -		sz := d.image.src.Bounds().Size()
> +		var sz image.Point = d.image.src.Bounds().Size()

You forgot to revert this change.

>  		sr := layout.FRect(d.image.rect)
>  		if dx := float32(dr.Dx()); dx != 0 {
>  			// Don't clip 1 px width sources.
> diff --git a/gpu/shaders/cover.frag b/gpu/shaders/cover.frag
> index 5a051f8..8dff3ee 100644
> --- a/gpu/shaders/cover.frag
> +++ b/gpu/shaders/cover.frag
> @@ -11,7 +13,7 @@ precision mediump float;
>  layout(location = 0) in highp vec2 vCoverUV;
>  layout(location = 1) in vec2 vUV;
>  
> -layout(binding = 1) uniform sampler2D cover;
> +layout(binding = 4) uniform sampler2D cover;

I'm not sure why 4 is required, when there are only 3 YUV textures (0, 1, 2).
Why not binding=3?

>  
>  layout(location = 0) out vec4 fragColor;
>  
> diff --git a/op/paint/paint.go b/op/paint/paint.go
> index b4a9a56..c9ad3d5 100644
> --- a/op/paint/paint.go
> +++ b/op/paint/paint.go
> @@ -24,7 +24,7 @@ type ImageOp struct {
>  
>  	uniform bool
>  	color   color.RGBA
> -	src     *image.RGBA
> +	src     image.Image
>  
>  	// handle is a key to uniquely identify this ImageOp
>  	// in a map of cached textures.
> @@ -53,6 +53,8 @@ type PaintOp struct {
>  // ensure that changes to an image is reflected in the display of
>  // it.
>  func NewImageOp(src image.Image) ImageOp {
> +	nodraw := false
> +	bounds := src.Bounds()
>  	switch src := src.(type) {
>  	case *image.Uniform:
>  		col := color.RGBAModel.Convert(src.C).(color.RGBA)
> @@ -61,17 +63,20 @@ func NewImageOp(src image.Image) ImageOp {
>  			color:   col,
>  		}
>  	case *image.RGBA:
> -		bounds := src.Bounds()
> -		if bounds.Min == (image.Point{}) && src.Stride == bounds.Dx()*4 {
> -			return ImageOp{
> -				Rect:   src.Bounds(),
> -				src:    src,
> -				handle: new(int),
> -			}
> +		nodraw = (bounds.Min == image.Point{} && src.Stride == bounds.Dx()*4)
> +	case *image.YCbCr:
> +		nodraw = (bounds.Min == image.Point{})

Why is there no stride check here?

> +	}
> +
> +	if nodraw {
> +		return ImageOp{
> +			Rect:   src.Bounds(),
> +			src:    src,
> +			handle: new(int),
>  		}
>  	}
>  
> -	sz := src.Bounds().Size()
> +	sz := bounds.Size()
>  	// Copy the image into a GPU friendly format.
>  	dst := image.NewRGBA(image.Rectangle{
>  		Max: sz,
> -- 
> 2.26.2

Re: [PATCH gio 2/2] gpu: update shaders.go

Details
Message ID
<C3ZILNFBX87C.2JMHU0QCG6HUV@themachine>
In-Reply-To
<159388339974.26803.16846442073837397453-2@git.sr.ht> (view parent)
DKIM signature
pass
Download raw message
Please squash this change with the other patch. As I understand it,
neither patch works without the other.


On Sat Jul 4, 2020 at 10:12, ~dejadeja9 wrote:
> From: Deja Deja <dejadejade9@outlook.com>
>
> ---
>  gpu/shaders.go | 221 +++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 197 insertions(+), 24 deletions(-)
>
> diff --git a/gpu/shaders.go b/gpu/shaders.go
> index d8e8435..e22dd84 100644
> --- a/gpu/shaders.go
> +++ b/gpu/shaders.go

Re: [PATCH gio 1/2] gpu: native yuv support

Details
Message ID
<DM6PR06MB4123855EFB6A9AF1F2B8AC64E4690@DM6PR06MB4123.namprd06.prod.outlook.com>
In-Reply-To
<C3ZI0VPSZP2U.7GGXGCLQXVRI@themachine> (view parent)
DKIM signature
fail
Download raw message
DKIM signature: fail
I realized when we talked about using YStride v.s. Dx() we were actually talking about two different scenarios: I was referring to the case that Dx() is slightly less than YStride while you might refer to different widths with sharing of the same backing pixels. I wanted to skip the check because I was testing with some YUV jpegs with width=699 while YStride=700. This is because YStride needs to be 2x or 4x of CStride, and this problem doesn't exist for RGBA because it is always 4 bytes aligned. But I added the check in the new patch and we may address this in the future. 

Combining the U & V channels doesn't make sense for a planar layout because we will have to interlacing them by CPU before uploading. FWIW the interlaced semi-planar format is also popularly one used by phone cameras (called NV12 or NV21) and we will support it in the future.

The binding idx 4 in cover.frag is a typo. Thanks for catching it. The new patch is sent.

I'll need more time to work through the tests. I can use a reference jpeg image to compare its RGBA representation with the screenshot but the current transform matrix is for video (i.e., limited range) while the JPEG version is full range so currently the results are not accurately comparable.


From: Elias Naur <mail@eliasnaur.com>
Sent: Monday, July 6, 2020 4:19 AM
To: ~dejadeja9 <dejadejade9@outlook.com>; ~eliasnaur/gio-patches@lists.sr.ht <~eliasnaur/gio-patches@lists.sr.ht>
Subject: Re: [PATCH gio 1/2] gpu: native yuv support 
 

> I hope this addresses all the comments except for "YStride check". I
> believe the check is unnecessary because width could be smaller than the
> the stride as a normal case when alignment is needed.

Responded below. I don't think you can avoid verifying the YStride in NewImageOp.

> One thing I am not
> sure is whether `texUnits [3]*gpuTexture` should be updated to 4.

Have you tried drawing a clipped YUV image? I'm not sure you're using all 4
texture units without clipping.

Speaking of which, please add a test to internal/rendertest to make sure the
feature works correctly and won't bit-rot. Don't forget to add a clipped YUV
image test.

On Sat Jul 4, 2020 at 10:08, ~dejadeja9 wrote:
> From: Deja Deja <dejadejade9@outlook.com>
> diff --git a/gpu/gpu.go b/gpu/gpu.go
> index 321b2a8..6a96ad1 100644
> --- a/gpu/gpu.go
> +++ b/gpu/gpu.go
> @@ -383,22 +395,68 @@ func (g *GPU) Profile() string {
>        return g.profile
>  }

> -func (r *renderer) texHandle(t *texture) backend.Texture {
> -     if t.tex != nil {
> +func (r *renderer) bindTexture(t *texture) {
> +     tex := r.texHandle(t)
> +     for i, t := range tex {
> +             r.ctx.BindTexture(i, t)
> +     }
> +}
> +
> +func (r *renderer) texHandle(t *texture) []backend.Texture {
> +     if len(t.tex) > 0 {
>                return t.tex
>        }
> -     tex, err := r.ctx.NewTexture(backend.TextureFormatSRGB, t.src.Bounds().Dx(), t.src.Bounds().Dy(), backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
> -     if err != nil {
> -             panic(err)
> +
> +     w, h := t.src.Bounds().Dx(), t.src.Bounds().Dy()
> +     switch src := t.src.(type) {
> +     case *image.RGBA:
> +             tex, err := r.ctx.NewTexture(backend.TextureFormatSRGB, src.Bounds().Dx(), src.Bounds().Dy(), backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
> +             if err != nil {
> +                     panic(err)
> +             }
> +             tex.Upload(src.Pix, src.Bounds().Dx(), src.Bounds().Dy(), 4)
> +             t.tex = append(t.tex, tex)
> +     case *image.YCbCr:
> +             //use YStride instead of Bounds().Dx() as Bounds().Dx() could be smaller than YStride due to padding

I still don't understand why you're not using (Y)Stride in both RGBA and TCbCr
cases, or Dx in both cases. If Dx < YStride the texture will still be wrong, or
at least have an unexpected width.

I'd say you should use Dx in both cases. If there is (unexpected) padding,
NewImageOp should fall back to an image copy. And sure, glTexSubImage or
glPixelStore may be useful to support more strides, but that's a future change.

Another reason to use Dx is that YStride is in bytes, while Dx is in pixels.
That doesn't matter in practice for single-channel textures, but is confusing.

> +             w = src.YStride
> +             ytex, err := r.ctx.NewTexture(backend.TextureFormatLuminance, w, h, backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
> +             if err != nil {
> +                     panic(err)
> +             }
> +             ytex.Upload(src.Y, w, h, 1)
> +
> +             wsub, hsub := 1, 1
> +             switch src.SubsampleRatio {
> +             case image.YCbCrSubsampleRatio420:
> +                     wsub, hsub = 2, 2
> +             case image.YCbCrSubsampleRatio444:
> +                     break
> +             case image.YCbCrSubsampleRatio422:
> +                     wsub, hsub = 2, 1
> +             }
> +
> +             utex, err := r.ctx.NewTexture(backend.TextureFormatLuminance, w/wsub, h/hsub, backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
> +             if err != nil {
> +                     panic(err)
> +             }
> +             utex.Upload(src.Cb, w/wsub, h/hsub, 1)
> +
> +             vtex, err := r.ctx.NewTexture(backend.TextureFormatLuminance, w/wsub, h/hsub, backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
> +             if err != nil {
> +                     panic(err)
> +             }

Are 2-channel textures available in both OpenGL ES and D3D11 (I don't know)?
If so, you can pack the U and V channels into one texture and one shader lookup.

Ok to leave for a future change.

> +             vtex.Upload(src.Cr, w/wsub, h/hsub, 1)
> +             t.tex = append(t.tex, ytex, utex, vtex)
>        }
> -     tex.Upload(t.src)
> -     t.tex = tex
> +
>        return t.tex
>  }

> @@ -847,10 +925,10 @@ func (d *drawState) materialFor(cache *resourceCache, rect f32.Rectangle, off f3
>                m.material = materialColor
>                m.color = f32color.RGBAFromSRGB(d.color)
>                m.opaque = m.color.A == 1.0
> -     case materialTexture:
> -             m.material = materialTexture
> +     case materialTexture, materialYCbCr:
> +             m.material = d.matType
>                dr := boundRectF(rect.Add(off))


> -             sz := d.image.src.Bounds().Size()
> +             var sz image.Point = d.image.src.Bounds().Size()

You forgot to revert this change.

>                sr := layout.FRect(d.image.rect)
>                if dx := float32(dr.Dx()); dx != 0 {
>                        // Don't clip 1 px width sources.
> diff --git a/gpu/shaders/cover.frag b/gpu/shaders/cover.frag
> index 5a051f8..8dff3ee 100644
> --- a/gpu/shaders/cover.frag
> +++ b/gpu/shaders/cover.frag
> @@ -11,7 +13,7 @@ precision mediump float;
>  layout(location = 0) in highp vec2 vCoverUV;
>  layout(location = 1) in vec2 vUV;

> -layout(binding = 1) uniform sampler2D cover;
> +layout(binding = 4) uniform sampler2D cover;

I'm not sure why 4 is required, when there are only 3 YUV textures (0, 1, 2).
Why not binding=3?


>  layout(location = 0) out vec4 fragColor;

> diff --git a/op/paint/paint.go b/op/paint/paint.go
> index b4a9a56..c9ad3d5 100644
> --- a/op/paint/paint.go
> +++ b/op/paint/paint.go
> @@ -24,7 +24,7 @@ type ImageOp struct {

>        uniform bool
>        color   color.RGBA
> -     src     *image.RGBA
> +     src     image.Image

>        // handle is a key to uniquely identify this ImageOp
>        // in a map of cached textures.
> @@ -53,6 +53,8 @@ type PaintOp struct {
>  // ensure that changes to an image is reflected in the display of
>  // it.
>  func NewImageOp(src image.Image) ImageOp {
> +     nodraw := false
> +     bounds := src.Bounds()
>        switch src := src.(type) {
>        case *image.Uniform:
>                col := color.RGBAModel.Convert(src.C).(color.RGBA)
> @@ -61,17 +63,20 @@ func NewImageOp(src image.Image) ImageOp {
>                        color:   col,
>                }
>        case *image.RGBA:
> -             bounds := src.Bounds()
> -             if bounds.Min == (image.Point{}) && src.Stride == bounds.Dx()*4 {
> -                     return ImageOp{
> -                             Rect:   src.Bounds(),
> -                             src:    src,
> -                             handle: new(int),
> -                     }
> +             nodraw = (bounds.Min == image.Point{} && src.Stride == bounds.Dx()*4)
> +     case *image.YCbCr:
> +             nodraw = (bounds.Min == image.Point{})

Why is there no stride check here?

> +     }
> +
> +     if nodraw {
> +             return ImageOp{
> +                     Rect:   src.Bounds(),
> +                     src:    src,
> +                     handle: new(int),
>                }
>        }

> -     sz := src.Bounds().Size()
> +     sz := bounds.Size()
>        // Copy the image into a GPU friendly format.
>        dst := image.NewRGBA(image.Rectangle{
>                Max: sz,
> -- 
> 2.26.2
Export thread (mbox)