~eliasnaur/gio

8cec7e04eb71783caf03a8ac0e272d78491ec14b — Elias Naur 5 days ago d8f8740 main
gpu,gpu/shaders: [compute] decode sRGB texels in shader when EXT_sRGB is missing

This change avoids the hard dependency on GPU support for sRGB encoded
textures in the compute renderer.

With this change and the previously added CPU fallback, Gio no longer
rely on any GPU functionality outside the OpenGL ES 2.0 level.

Fixes gio#49
Fixes gio#154
Fixes gio#97
Fixes gio#36
Fixes gio#172

Signed-off-by: Elias Naur <mail@eliasnaur.com>
4 files changed, 107 insertions(+), 32 deletions(-)

M gpu/compute.go
M gpu/gpu.go
M gpu/shaders.go
M gpu/shaders/material.frag
M gpu/compute.go => gpu/compute.go +41 -11
@@ 42,6 42,7 @@ type compute struct {
	texOps        []textureOp
	viewport      image.Point
	maxTextureDim int
	srgb          bool

	programs struct {
		elements   computeProgram


@@ 98,8 99,14 @@ type compute struct {

		buffer sizedBuffer

		uniforms *materialUniforms
		uniBuf   driver.Buffer
		vert struct {
			uniforms *materialVertUniforms
			buf      driver.Buffer
		}

		frag struct {
			buf driver.Buffer
		}

		// CPU fields
		cpuTex cpu.ImageDescriptor


@@ 154,11 161,16 @@ type copyUniforms struct {
	_       [8]byte // Pad to 16 bytes.
}

type materialUniforms struct {
type materialVertUniforms struct {
	scale [2]float32
	pos   [2]float32
}

type materialFragUniforms struct {
	emulateSRGB float32
	_           [12]byte // Pad to 16 bytes
}

type collector struct {
	hasher     maphash.Hash
	profile    bool


@@ 372,6 384,7 @@ func newCompute(ctx driver.Device) (*compute, error) {
	g := &compute{
		ctx:           ctx,
		maxTextureDim: maxDim,
		srgb:          caps.Features.Has(driver.FeatureSRGB),
		conf:          new(config),
		memHeader:     new(memoryHeader),
	}


@@ 447,15 460,27 @@ func newCompute(ctx driver.Device) (*compute, error) {
		return nil, err
	}
	g.materials.layout = progLayout
	g.materials.uniforms = new(materialUniforms)
	g.materials.vert.uniforms = new(materialVertUniforms)

	buf, err = ctx.NewBuffer(driver.BufferBindingUniforms, int(unsafe.Sizeof(*g.materials.uniforms)))
	buf, err = ctx.NewBuffer(driver.BufferBindingUniforms, int(unsafe.Sizeof(*g.materials.vert.uniforms)))
	if err != nil {
		g.Release()
		return nil, err
	}
	g.materials.uniBuf = buf
	g.materials.vert.buf = buf
	g.materials.prog.SetVertexUniforms(buf)
	var emulateSRGB materialFragUniforms
	if !g.srgb {
		emulateSRGB.emulateSRGB = 1.0
	}
	buf, err = ctx.NewBuffer(driver.BufferBindingUniforms, int(unsafe.Sizeof(emulateSRGB)))
	if err != nil {
		g.Release()
		return nil, err
	}
	buf.Upload(byteslice.Struct(&emulateSRGB))
	g.materials.frag.buf = buf
	g.materials.prog.SetFragmentUniforms(buf)

	for _, shader := range shaders {
		if !g.useCPU {


@@ 875,9 900,9 @@ restart:
		}
	}
	// Transform to clip space: [-1, -1] - [1, 1].
	g.materials.uniforms.scale = [2]float32{2 / float32(texSize), 2 / float32(texSize)}
	g.materials.uniforms.pos = [2]float32{-1, -1}
	g.materials.uniBuf.Upload(byteslice.Struct(g.materials.uniforms))
	g.materials.vert.uniforms.scale = [2]float32{2 / float32(texSize), 2 / float32(texSize)}
	g.materials.vert.uniforms.pos = [2]float32{-1, -1}
	g.materials.vert.buf.Upload(byteslice.Struct(g.materials.vert.uniforms))
	vertexData := byteslice.Slice(m.quads)
	n := pow2Ceil(len(vertexData))
	m.buffer.ensureCapacity(false, g.ctx, driver.BufferBindingVertices, n)


@@ 952,7 977,11 @@ restart:
			a.tex = nil
		}
		sz := a.packer.maxDim
		handle, err := g.ctx.NewTexture(driver.TextureFormatSRGBA, sz, sz, driver.FilterLinear, driver.FilterLinear, driver.BufferBindingTexture)
		format := driver.TextureFormatSRGBA
		if !g.srgb {
			format = driver.TextureFormatRGBA8
		}
		handle, err := g.ctx.NewTexture(format, sz, sz, driver.FilterLinear, driver.FilterLinear, driver.BufferBindingTexture)
		if err != nil {
			return fmt.Errorf("compute: failed to create image atlas: %v", err)
		}


@@ 1316,7 1345,8 @@ func (g *compute) Release() {
		g.materials.fbo,
		g.materials.tex,
		&g.materials.buffer,
		g.materials.uniBuf,
		g.materials.vert.buf,
		g.materials.frag.buf,
		g.timers.t,
	}
	g.materials.cpuTex.Free()

M gpu/gpu.go => gpu/gpu.go +1 -5
@@ 9,7 9,6 @@ package gpu

import (
	"encoding/binary"
	"errors"
	"fmt"
	"image"
	"image/color"


@@ 361,11 360,8 @@ func New(api API) (GPU, error) {
	defer d.EndFrame()
	forceCompute := os.Getenv("GIORENDERER") == "forcecompute"
	feats := d.Caps().Features
	if !feats.Has(driver.FeatureSRGB) {
		return nil, errors.New("gpu: no sRGB texture formats found")
	}
	switch {
	case !forceCompute && feats.Has(driver.FeatureFloatRenderTargets):
	case !forceCompute && feats.Has(driver.FeatureFloatRenderTargets) && feats.Has(driver.FeatureSRGB):
		return newGPU(d)
	}
	return newCompute(d)

M gpu/shaders.go => gpu/shaders.go +56 -15
@@ 5073,13 5073,25 @@ void main()
		Hash: "e72e482d7f40b2949426017cb5aeb4d391fcfc0e9d42e73bffb5a1e5576e906d",
	}
	shader_material_frag = driver.ShaderSources{
		Name:     "material.frag",
		Inputs:   []driver.InputLocation{{Name: "vUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}},
		Name:   "material.frag",
		Inputs: []driver.InputLocation{{Name: "vUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}},
		Uniforms: driver.UniformsReflection{
			Blocks:    []driver.UniformBlock{{Name: "Color", Binding: 0}},
			Locations: []driver.UniformLocation{{Name: "_color.emulateSRGB", Type: 0x0, Size: 1, Offset: 0}},
			Size:      4,
		},
		Textures: []driver.TextureBinding{{Name: "tex", Binding: 0}},
		GLSL100ES: `#version 100
precision mediump float;
precision highp int;

struct Color
{
    float emulateSRGB;
};

uniform Color _58;

uniform mediump sampler2D tex;

varying vec2 vUV;


@@ 5095,9 5107,12 @@ vec3 RGBtosRGB(vec3 rgb)
void main()
{
    vec4 texel = texture2D(tex, vUV);
    vec3 param = texel.xyz;
    vec3 _59 = RGBtosRGB(param);
    texel = vec4(_59.x, _59.y, _59.z, texel.w);
    if (_58.emulateSRGB == 0.0)
    {
        vec3 param = texel.xyz;
        vec3 _71 = RGBtosRGB(param);
        texel = vec4(_71.x, _71.y, _71.z, texel.w);
    }
    gl_FragData[0] = texel;
}



@@ 5106,6 5121,11 @@ void main()
precision mediump float;
precision highp int;

layout(std140) uniform Color
{
    float emulateSRGB;
} _58;

uniform mediump sampler2D tex;

in vec2 vUV;


@@ 5122,15 5142,25 @@ vec3 RGBtosRGB(vec3 rgb)
void main()
{
    vec4 texel = texture(tex, vUV);
    vec3 param = texel.xyz;
    vec3 _59 = RGBtosRGB(param);
    texel = vec4(_59.x, _59.y, _59.z, texel.w);
    if (_58.emulateSRGB == 0.0)
    {
        vec3 param = texel.xyz;
        vec3 _71 = RGBtosRGB(param);
        texel = vec4(_71.x, _71.y, _71.z, texel.w);
    }
    fragColor = texel;
}

`,
		GLSL130: `#version 130

struct Color
{
    float emulateSRGB;
};

uniform Color _58;

uniform sampler2D tex;

in vec2 vUV;


@@ 5147,15 5177,23 @@ vec3 RGBtosRGB(vec3 rgb)
void main()
{
    vec4 texel = texture(tex, vUV);
    vec3 param = texel.xyz;
    vec3 _59 = RGBtosRGB(param);
    texel = vec4(_59.x, _59.y, _59.z, texel.w);
    if (_58.emulateSRGB == 0.0)
    {
        vec3 param = texel.xyz;
        vec3 _71 = RGBtosRGB(param);
        texel = vec4(_71.x, _71.y, _71.z, texel.w);
    }
    fragColor = texel;
}

`,
		GLSL150: `#version 150

layout(std140) uniform Color
{
    float emulateSRGB;
} _58;

uniform sampler2D tex;

in vec2 vUV;


@@ 5172,14 5210,17 @@ vec3 RGBtosRGB(vec3 rgb)
void main()
{
    vec4 texel = texture(tex, vUV);
    vec3 param = texel.xyz;
    vec3 _59 = RGBtosRGB(param);
    texel = vec4(_59.x, _59.y, _59.z, texel.w);
    if (_58.emulateSRGB == 0.0)
    {
        vec3 param = texel.xyz;
        vec3 _71 = RGBtosRGB(param);
        texel = vec4(_71.x, _71.y, _71.z, texel.w);
    }
    fragColor = texel;
}

`,
		HLSL: "DXBC\x9e\x87LD\xf3\x17\n\x06\\\xb7\x98\x94\xa9PKe\x01\x00\x00\x00\xc8\x04\x00\x00\x06\x00\x00\x008\x00\x00\x00\xbc\x01\x00\x00D\x03\x00\x00\xc0\x03\x00\x00`\x04\x00\x00\x94\x04\x00\x00Aon9|\x01\x00\x00|\x01\x00\x00\x00\x02\xff\xffT\x01\x00\x00(\x00\x00\x00\x00\x00(\x00\x00\x00(\x00\x00\x00(\x00\x01\x00$\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x02\xff\xffQ\x00\x00\x05\x00\x00\x0f\xa0=\n\x87?\xaeGa\xbd\x00\x00\x00\x00\x00\x00\x00\x00Q\x00\x00\x05\x01\x00\x0f\xa0\x1c.M\xbbR\xb8NAvT\xd5>\x00\x00\x00\x00\x1f\x00\x00\x02\x00\x00\x00\x80\x00\x00\x03\xb0\x1f\x00\x00\x02\x00\x00\x00\x90\x00\b\x0f\xa0B\x00\x00\x03\x00\x00\x0f\x80\x00\x00\xe4\xb0\x00\b\xe4\xa0\x0f\x00\x00\x02\x01\x00\x01\x80\x00\x00\x00\x80\x0f\x00\x00\x02\x01\x00\x02\x80\x00\x00U\x80\x0f\x00\x00\x02\x01\x00\x04\x80\x00\x00\xaa\x80\x05\x00\x00\x03\x01\x00\a\x80\x01\x00\xe4\x80\x01\x00\xaa\xa0\x0e\x00\x00\x02\x02\x00\x01\x80\x01\x00\x00\x80\x0e\x00\x00\x02\x02\x00\x02\x80\x01\x00U\x80\x0e\x00\x00\x02\x02\x00\x04\x80\x01\x00\xaa\x80\x04\x00\x00\x04\x01\x00\a\x80\x02\x00\xe4\x80\x00\x00\x00\xa0\x00\x00U\xa0\x02\x00\x00\x03\x01\x00\b\x80\x00\x00\x00\x80\x01\x00\x00\xa0\x05\x00\x00\x03\x02\x00\a\x80\x00\x00\xe4\x80\x01\x00U\xa0X\x00\x00\x04\x00\x00\x01\x80\x01\x00\xff\x80\x01\x00\x00\x80\x02\x00\x00\x80\x02\x00\x00\x03\x01\x00\x01\x80\x00\x00U\x80\x01\x00\x00\xa0X\x00\x00\x04\x00\x00\x02\x80\x01\x00\x00\x80\x01\x00U\x80\x02\x00U\x80\x02\x00\x00\x03\x01\x00\x01\x80\x00\x00\xaa\x80\x01\x00\x00\xa0X\x00\x00\x04\x00\x00\x04\x80\x01\x00\x00\x80\x01\x00\xaa\x80\x02\x00\xaa\x80\x01\x00\x00\x02\x00\b\x0f\x80\x00\x00\xe4\x80\xff\xff\x00\x00SHDR\x80\x01\x00\x00@\x00\x00\x00`\x00\x00\x00Z\x00\x00\x03\x00`\x10\x00\x00\x00\x00\x00X\x18\x00\x04\x00p\x10\x00\x00\x00\x00\x00UU\x00\x00b\x10\x00\x032\x10\x10\x00\x00\x00\x00\x00e\x00\x00\x03\xf2 \x10\x00\x00\x00\x00\x00h\x00\x00\x02\x03\x00\x00\x00E\x00\x00\t\xf2\x00\x10\x00\x00\x00\x00\x00F\x10\x10\x00\x00\x00\x00\x00F~\x10\x00\x00\x00\x00\x00\x00`\x10\x00\x00\x00\x00\x00/\x00\x00\x05r\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x008\x00\x00\nr\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00\x02@\x00\x00vT\xd5>vT\xd5>vT\xd5>\x00\x00\x00\x00\x19\x00\x00\x05r\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x002\x00\x00\x0fr\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00\x02@\x00\x00=\n\x87?=\n\x87?=\n\x87?\x00\x00\x00\x00\x02@\x00\x00\xaeGa\xbd\xaeGa\xbd\xaeGa\xbd\x00\x00\x00\x00\x1d\x00\x00\nr\x00\x10\x00\x02\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x00\x02@\x00\x00\x1c.M;\x1c.M;\x1c.M;\x00\x00\x00\x008\x00\x00\nr\x00\x10\x00\x00\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x00\x02@\x00\x00R\xb8NAR\xb8NAR\xb8NA\x00\x00\x00\x006\x00\x00\x05\x82 \x10\x00\x00\x00\x00\x00:\x00\x10\x00\x00\x00\x00\x007\x00\x00\tr \x10\x00\x00\x00\x00\x00F\x02\x10\x00\x02\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x00>\x00\x00\x01STATt\x00\x00\x00\n\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00RDEF\x98\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1c\x00\x00\x00\x00\x04\xff\xff\x00\x01\x00\x00m\x00\x00\x00\\\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00i\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00_tex_sampler\x00tex\x00Microsoft (R) HLSL Shader Compiler 10.1\x00\xab\xab\xabISGN,\x00\x00\x00\x01\x00\x00\x00\b\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x03\x03\x00\x00TEXCOORD\x00\xab\xab\xabOSGN,\x00\x00\x00\x01\x00\x00\x00\b\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00SV_Target\x00\xab\xab",
		HLSL: "DXBC`l\xc5\r\xe5m\xb2n{\xec\x1c^\xe6\xcao\x04\x01\x00\x00\x00\xc0\x05\x00\x00\x06\x00\x00\x008\x00\x00\x00\xec\x01\x00\x00\xc8\x03\x00\x00D\x04\x00\x00X\x05\x00\x00\x8c\x05\x00\x00Aon9\xac\x01\x00\x00\xac\x01\x00\x00\x00\x02\xff\xffx\x01\x00\x004\x00\x00\x00\x01\x00(\x00\x00\x004\x00\x00\x004\x00\x01\x00$\x00\x00\x004\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02\xff\xffQ\x00\x00\x05\x01\x00\x0f\xa0=\n\x87?\xaeGa\xbd\x00\x00\x00\x00\x00\x00\x00\x00Q\x00\x00\x05\x02\x00\x0f\xa0\x1c.M\xbbR\xb8NAvT\xd5>\x00\x00\x00\x00\x1f\x00\x00\x02\x00\x00\x00\x80\x00\x00\x03\xb0\x1f\x00\x00\x02\x00\x00\x00\x90\x00\b\x0f\xa0B\x00\x00\x03\x00\x00\x0f\x80\x00\x00\xe4\xb0\x00\b\xe4\xa0\x05\x00\x00\x03\x01\x00\b\x80\x00\x00\x00\xa0\x00\x00\x00\xa0\x0f\x00\x00\x02\x01\x00\x01\x80\x00\x00\x00\x80\x0f\x00\x00\x02\x01\x00\x02\x80\x00\x00U\x80\x0f\x00\x00\x02\x01\x00\x04\x80\x00\x00\xaa\x80\x05\x00\x00\x03\x01\x00\a\x80\x01\x00\xe4\x80\x02\x00\xaa\xa0\x0e\x00\x00\x02\x02\x00\x01\x80\x01\x00\x00\x80\x0e\x00\x00\x02\x02\x00\x02\x80\x01\x00U\x80\x0e\x00\x00\x02\x02\x00\x04\x80\x01\x00\xaa\x80\x04\x00\x00\x04\x01\x00\a\x80\x02\x00\xe4\x80\x01\x00\x00\xa0\x01\x00U\xa0\x02\x00\x00\x03\x02\x00\x01\x80\x00\x00\x00\x80\x02\x00\x00\xa0\x05\x00\x00\x03\x02\x00\x0e\x80\x00\x00\x1b\x80\x02\x00U\xa0X\x00\x00\x04\x03\x00\x01\x80\x02\x00\x00\x80\x01\x00\x00\x80\x02\x00\xff\x80\x02\x00\x00\x03\x03\x00\b\x80\x00\x00U\x80\x02\x00\x00\xa0X\x00\x00\x04\x03\x00\x02\x80\x03\x00\xff\x80\x01\x00U\x80\x02\x00\xaa\x80\x02\x00\x00\x03\x03\x00\b\x80\x00\x00\xaa\x80\x02\x00\x00\xa0X\x00\x00\x04\x03\x00\x04\x80\x03\x00\xff\x80\x01\x00\xaa\x80\x02\x00U\x80X\x00\x00\x04\x00\x00\a\x80\x01\x00\xff\x81\x03\x00\xe4\x80\x00\x00\xe4\x80\x01\x00\x00\x02\x00\b\x0f\x80\x00\x00\xe4\x80\xff\xff\x00\x00SHDR\xd4\x01\x00\x00@\x00\x00\x00u\x00\x00\x00Y\x00\x00\x04F\x8e \x00\x00\x00\x00\x00\x01\x00\x00\x00Z\x00\x00\x03\x00`\x10\x00\x00\x00\x00\x00X\x18\x00\x04\x00p\x10\x00\x00\x00\x00\x00UU\x00\x00b\x10\x00\x032\x10\x10\x00\x00\x00\x00\x00e\x00\x00\x03\xf2 \x10\x00\x00\x00\x00\x00h\x00\x00\x02\x04\x00\x00\x00E\x00\x00\t\xf2\x00\x10\x00\x00\x00\x00\x00F\x10\x10\x00\x00\x00\x00\x00F~\x10\x00\x00\x00\x00\x00\x00`\x10\x00\x00\x00\x00\x00/\x00\x00\x05r\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x008\x00\x00\nr\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00\x02@\x00\x00vT\xd5>vT\xd5>vT\xd5>\x00\x00\x00\x00\x19\x00\x00\x05r\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x002\x00\x00\x0fr\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00\x02@\x00\x00=\n\x87?=\n\x87?=\n\x87?\x00\x00\x00\x00\x02@\x00\x00\xaeGa\xbd\xaeGa\xbd\xaeGa\xbd\x00\x00\x00\x00\x1d\x00\x00\nr\x00\x10\x00\x02\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x00\x02@\x00\x00\x1c.M;\x1c.M;\x1c.M;\x00\x00\x00\x008\x00\x00\nr\x00\x10\x00\x03\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x00\x02@\x00\x00R\xb8NAR\xb8NAR\xb8NA\x00\x00\x00\x007\x00\x00\tr\x00\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x02\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x03\x00\x00\x00\x18\x00\x00\b\x82\x00\x10\x00\x01\x00\x00\x00\x01@\x00\x00\x00\x00\x00\x00\n\x80 \x00\x00\x00\x00\x00\x00\x00\x00\x007\x00\x00\tr \x10\x00\x00\x00\x00\x00\xf6\x0f\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x01\x00\x00\x00F\x02\x10\x00\x00\x00\x00\x006\x00\x00\x05\x82 \x10\x00\x00\x00\x00\x00:\x00\x10\x00\x00\x00\x00\x00>\x00\x00\x01STATt\x00\x00\x00\f\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00RDEF\f\x01\x00\x00\x01\x00\x00\x00\x94\x00\x00\x00\x03\x00\x00\x00\x1c\x00\x00\x00\x00\x04\xff\xff\x00\x01\x00\x00\xe4\x00\x00\x00|\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x89\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\x8d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00_tex_sampler\x00tex\x00Color\x00\xab\x8d\x00\x00\x00\x01\x00\x00\x00\xac\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc4\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\xd4\x00\x00\x00\x00\x00\x00\x00_58_emulateSRGB\x00\x00\x00\x03\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00Microsoft (R) HLSL Shader Compiler 10.1\x00ISGN,\x00\x00\x00\x01\x00\x00\x00\b\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x03\x03\x00\x00TEXCOORD\x00\xab\xab\xabOSGN,\x00\x00\x00\x01\x00\x00\x00\b\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00SV_Target\x00\xab\xab",
	}
	shader_material_vert = driver.ShaderSources{
		Name:   "material.vert",

M gpu/shaders/material.frag => gpu/shaders/material.frag +9 -1
@@ 10,6 10,12 @@ layout(location = 0) in vec2 vUV;

layout(location = 0) out vec4 fragColor;

layout(binding=0) uniform Color {
	// If emulateSRGB is set (!= 0), the input texels are sRGB encoded. We save the
	// conversion step below, at the cost of texture filtering in sRGB space.
	float emulateSRGB;
};

vec3 RGBtosRGB(vec3 rgb) {
	bvec3 cutoff = greaterThanEqual(rgb, vec3(0.0031308));
	vec3 below = vec3(12.92)*rgb;


@@ 19,6 25,8 @@ vec3 RGBtosRGB(vec3 rgb) {

void main() {
	vec4 texel = texture(tex, vUV);
	texel.rgb = RGBtosRGB(texel.rgb);
	if (emulateSRGB == 0.0) {
		texel.rgb = RGBtosRGB(texel.rgb);
	}
	fragColor = texel;
}