~eliasnaur/gio-patches

gio: internal/cmd/convertshaders: add support for compute shaders v1 PROPOSED

Elias Naur: 1
 internal/cmd/convertshaders: add support for compute shaders

 2 files changed, 153 insertions(+), 105 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~eliasnaur/gio-patches/patches/11985/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH gio] internal/cmd/convertshaders: add support for compute shaders Export this patch

Testing builds.sr.ht integration.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
---
 gpu/backend/backend.go              |   1 +
 internal/cmd/convertshaders/main.go | 257 ++++++++++++++++------------
 2 files changed, 153 insertions(+), 105 deletions(-)

diff --git gpu/backend/backend.go gpu/backend/backend.go
index 871eea4..924e5b4 100644
--- gpu/backend/backend.go
@@ -48,6 +48,7 @@ type Device interface {
type ShaderSources struct {
	GLSL100ES string
	GLSL300ES string
	GLSL310ES string
	GLSL130   string
	GLSL150   string
	HLSL      []byte
diff --git internal/cmd/convertshaders/main.go internal/cmd/convertshaders/main.go
index 250137e..211c38a 100644
--- internal/cmd/convertshaders/main.go
@@ -7,6 +7,7 @@ import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
@@ -67,125 +68,168 @@ func generate() error {
	out.WriteString("var (\n")

	for _, shader := range shaders {
		if ext := filepath.Ext(shader); ext != ".vert" && ext != ".frag" {
		var err error
		switch filepath.Ext(shader) {
		case ".vert", ".frag":
			err = generateShader(glslcc, tmp, &out, shader)
		case ".comp":
			err = generateComputeShader(glslcc, tmp, &out, shader)
		default:
			continue
		}
		const nvariants = 2
		var variants [nvariants]struct {
			backend.ShaderSources
			hlslSrc string
		if err != nil {
			return err
		}
		args := [nvariants]shaderArgs{
			{
				FetchColorExpr: `_color`,
				Header:         `layout(binding=0) uniform Color { vec4 _color; };`,
			},
			{
				FetchColorExpr: `texture(tex, vUV)`,
				Header:         `layout(binding=0) uniform sampler2D tex;`,
			},
	}
	out.WriteString(")")
	if err := ioutil.WriteFile("shaders.go", out.Bytes(), 0644); err != nil {
		return err
	}
	cmd := exec.Command("gofmt", "-s", "-w", "shaders.go")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func generateComputeShader(glslcc, tmp string, out io.Writer, shader string) error {
	var src backend.ShaderSources
	glsl310es, reflect, err := convertShader(tmp, glslcc, shader, "gles", "310", nil, false)
	if err != nil {
		return err
	}
	if err := parseReflection(reflect, &src); err != nil {
		return err
	}
	src.GLSL310ES = glsl310es
	name := filepath.Base(shader)
	name = strings.ReplaceAll(name, ".", "_")
	fmt.Fprintf(out, "\tshader_%s = ", name)
	fmt.Fprintf(out, "backend.ShaderSources{\n")
	if len(src.Inputs) > 0 {
		fmt.Fprintf(out, "Inputs: %#v,\n", src.Inputs)
	}
	if u := src.Uniforms; len(u.Blocks) > 0 {
		fmt.Fprintf(out, "Uniforms: backend.UniformsReflection{\n")
		fmt.Fprintf(out, "Blocks: %#v,\n", u.Blocks)
		fmt.Fprintf(out, "Locations: %#v,\n", u.Locations)
		fmt.Fprintf(out, "Size: %d,\n", u.Size)
		fmt.Fprintf(out, "},\n")
	}
	fmt.Fprintf(out, "GLSL310ES: %#v,\n", src.GLSL310ES)
	fmt.Fprintf(out, "}")
	fmt.Fprintf(out, "\n")
	return nil
}

func generateShader(glslcc, tmp string, out io.Writer, shader string) error {
	const nvariants = 2
	var variants [nvariants]struct {
		backend.ShaderSources
		hlslSrc string
	}
	args := [nvariants]shaderArgs{
		{
			FetchColorExpr: `_color`,
			Header:         `layout(binding=0) uniform Color { vec4 _color; };`,
		},
		{
			FetchColorExpr: `texture(tex, vUV)`,
			Header:         `layout(binding=0) uniform sampler2D tex;`,
		},
	}
	for i := range args {
		glsl100es, reflect, err := convertShader(tmp, glslcc, shader, "gles", "100", &args[i], false)
		if err != nil {
			return err
		}
		for i := range args {
			glsl100es, reflect, err := convertShader(tmp, glslcc, shader, "gles", "100", &args[i], false)
			if err != nil {
				return err
			}
			if err := parseReflection(reflect, &variants[i].ShaderSources); err != nil {
				return err
			}
			glsl300es, _, err := convertShader(tmp, glslcc, shader, "gles", "300", &args[i], false)
			if err != nil {
				return err
			}
			glsl130, _, err := convertShader(tmp, glslcc, shader, "glsl", "130", &args[i], false)
			if err != nil {
				return err
			}
			hlsl, _, err := convertShader(tmp, glslcc, shader, "hlsl", "40", &args[i], false)
		if err := parseReflection(reflect, &variants[i].ShaderSources); err != nil {
			return err
		}
		glsl300es, _, err := convertShader(tmp, glslcc, shader, "gles", "300", &args[i], false)
		if err != nil {
			return err
		}
		glsl130, _, err := convertShader(tmp, glslcc, shader, "glsl", "130", &args[i], false)
		if err != nil {
			return err
		}
		hlsl, _, err := convertShader(tmp, glslcc, shader, "hlsl", "40", &args[i], false)
		if err != nil {
			return err
		}
		var hlslProf string
		switch filepath.Ext(shader) {
		case ".frag":
			hlslProf = "ps"
		case ".vert":
			hlslProf = "vs"
		default:
			return fmt.Errorf("unrecognized shader type %s", shader)
		}
		var hlslc []byte
		hlslc, err = compileHLSL(hlsl, "main", hlslProf+"_4_0_level_9_1")
		if err != nil {
			// Attempt shader model 4.0. Only the app/headless
			// test shaders use features not supported by level
			// 9.1.
			hlslc, err = compileHLSL(hlsl, "main", hlslProf+"_4_0")
			if err != nil {
				return err
			}
			var hlslProf string
			switch filepath.Ext(shader) {
			case ".frag":
				hlslProf = "ps"
			case ".vert":
				hlslProf = "vs"
			default:
				return fmt.Errorf("unrecognized shader type %s", shader)
			}
			var hlslc []byte
			hlslc, err = compileHLSL(hlsl, "main", hlslProf+"_4_0_level_9_1")
			if err != nil {
				// Attempt shader model 4.0. Only the app/headless
				// test shaders use features not supported by level
				// 9.1.
				hlslc, err = compileHLSL(hlsl, "main", hlslProf+"_4_0")
				if err != nil {
					return err
				}
			}
			// OpenGL 3.2 Core only accepts GLSL version 1.50, but is
			// otherwise compatible with version 1.30.
			glsl150 := strings.Replace(glsl130, "#version 130", "#version 150", 1)
			variants[i].GLSL100ES = glsl100es
			variants[i].GLSL300ES = glsl300es
			variants[i].GLSL130 = glsl130
			variants[i].GLSL150 = glsl150
			variants[i].hlslSrc = hlsl
			variants[i].HLSL = hlslc
		}
		name := filepath.Base(shader)
		name = strings.ReplaceAll(name, ".", "_")
		fmt.Fprintf(&out, "\tshader_%s = ", name)
		// If the shader don't use the variant arguments, output
		// only a single version.
		multiVariant := variants[0].GLSL100ES != variants[1].GLSL100ES
		if multiVariant {
			fmt.Fprintf(&out, "[...]backend.ShaderSources{\n")
		// OpenGL 3.2 Core only accepts GLSL version 1.50, but is
		// otherwise compatible with version 1.30.
		glsl150 := strings.Replace(glsl130, "#version 130", "#version 150", 1)
		variants[i].GLSL100ES = glsl100es
		variants[i].GLSL300ES = glsl300es
		variants[i].GLSL130 = glsl130
		variants[i].GLSL150 = glsl150
		variants[i].hlslSrc = hlsl
		variants[i].HLSL = hlslc
	}
	name := filepath.Base(shader)
	name = strings.ReplaceAll(name, ".", "_")
	fmt.Fprintf(out, "\tshader_%s = ", name)
	// If the shader don't use the variant arguments, output
	// only a single version.
	multiVariant := variants[0].GLSL100ES != variants[1].GLSL100ES
	if multiVariant {
		fmt.Fprintf(out, "[...]backend.ShaderSources{\n")
	}
	for _, src := range variants {
		fmt.Fprintf(out, "backend.ShaderSources{\n")
		if len(src.Inputs) > 0 {
			fmt.Fprintf(out, "Inputs: %#v,\n", src.Inputs)
		}
		for _, src := range variants {
			fmt.Fprintf(&out, "backend.ShaderSources{\n")
			if len(src.Inputs) > 0 {
				fmt.Fprintf(&out, "Inputs: %#v,\n", src.Inputs)
			}
			if u := src.Uniforms; len(u.Blocks) > 0 {
				fmt.Fprintf(&out, "Uniforms: backend.UniformsReflection{\n")
				fmt.Fprintf(&out, "Blocks: %#v,\n", u.Blocks)
				fmt.Fprintf(&out, "Locations: %#v,\n", u.Locations)
				fmt.Fprintf(&out, "Size: %d,\n", u.Size)
				fmt.Fprintf(&out, "},\n")
			}
			if len(src.Textures) > 0 {
				fmt.Fprintf(&out, "Textures: %#v,\n", src.Textures)
			}
			fmt.Fprintf(&out, "GLSL100ES: %#v,\n", src.GLSL100ES)
			fmt.Fprintf(&out, "GLSL300ES: %#v,\n", src.GLSL300ES)
			fmt.Fprintf(&out, "GLSL130: %#v,\n", src.GLSL130)
			fmt.Fprintf(&out, "GLSL150: %#v,\n", src.GLSL150)
			fmt.Fprintf(&out, "/*\n%s\n*/\n", src.hlslSrc)
			fmt.Fprintf(&out, "HLSL: %#v,\n", src.HLSL)
			fmt.Fprintf(&out, "}")
			if multiVariant {
				fmt.Fprintf(&out, ",")
			}
			fmt.Fprintf(&out, "\n")
			if !multiVariant {
				break
			}
		if u := src.Uniforms; len(u.Blocks) > 0 {
			fmt.Fprintf(out, "Uniforms: backend.UniformsReflection{\n")
			fmt.Fprintf(out, "Blocks: %#v,\n", u.Blocks)
			fmt.Fprintf(out, "Locations: %#v,\n", u.Locations)
			fmt.Fprintf(out, "Size: %d,\n", u.Size)
			fmt.Fprintf(out, "},\n")
		}
		if len(src.Textures) > 0 {
			fmt.Fprintf(out, "Textures: %#v,\n", src.Textures)
		}
		fmt.Fprintf(out, "GLSL100ES: %#v,\n", src.GLSL100ES)
		fmt.Fprintf(out, "GLSL300ES: %#v,\n", src.GLSL300ES)
		fmt.Fprintf(out, "GLSL130: %#v,\n", src.GLSL130)
		fmt.Fprintf(out, "GLSL150: %#v,\n", src.GLSL150)
		fmt.Fprintf(out, "/*\n%s\n*/\n", src.hlslSrc)
		fmt.Fprintf(out, "HLSL: %#v,\n", src.HLSL)
		fmt.Fprintf(out, "}")
		if multiVariant {
			fmt.Fprintf(&out, "}\n")
			fmt.Fprintf(out, ",")
		}
		fmt.Fprintf(out, "\n")
		if !multiVariant {
			break
		}
	}
	out.WriteString(")")
	if err := ioutil.WriteFile("shaders.go", out.Bytes(), 0644); err != nil {
		return err
	if multiVariant {
		fmt.Fprintf(out, "}\n")
	}
	cmd := exec.Command("gofmt", "-s", "-w", "shaders.go")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
	return nil
}

func parseReflection(jsonData []byte, info *backend.ShaderSources) error {
@@ -335,6 +379,9 @@ func convertShader(tmp, glslcc, path, lang, profile string, args *shaderArgs, fl
	case ".frag":
		progFlag = "--frag"
		progSuffix = "fs"
	case ".comp":
		progFlag = "--compute"
		progSuffix = "cs"
	default:
		return "", nil, fmt.Errorf("unrecognized shader type: %s", path)
	}
-- 
2.26.2