Skip to content

Commit

Permalink
glsl compat: Convert to highest GLSL version accepted by the target d…
Browse files Browse the repository at this point in the history
…river

With many more apps using GLES 3.1+, we're now hitting the case where
GLSL 330 is not sufficient. Unfortunately GLSL 420+ is not supported on
mac (which has been stranded at 410), so forcing output to anything
above 410 will completely break mac.

The only sensible option here is to give up with the GLSL compat and
either use a ref-rast, a 3rd party library to convert to metal, or require
on-device replay. All of these options are substantial work, so for now
generate code at the highest supported shader level for the given host
device driver. This means shaders using GLSL 420+ features should
now work on decent Windows / Linux drivers, but will (continue) to
fail on mac.
  • Loading branch information
ben-clayton committed Apr 13, 2018
1 parent 766c03a commit 2ce48b3
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 31 deletions.
1 change: 1 addition & 0 deletions gapis/api/gles/compat.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ func compat(ctx context.Context, device *device.Instance, onError onCompatError)
ShaderType: st,
Relaxed: true, // find_issues will still report bad GLSL.
StripOptimizations: true,
TargetGLSLVersion: version.MaxGLSL().AsInt(),
}

// Trim any prefix whitespace / newlines.
Expand Down
1 change: 1 addition & 0 deletions gapis/api/gles/find_issues.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ func (t *findIssues) Transform(ctx context.Context, id api.CmdID, cmd api.Cmd, o
ShaderType: st,
CheckAfterChanges: true,
Disassemble: true,
TargetGLSLVersion: 430,
}

if _, err := shadertools.ConvertGlsl(shader.Source, &opts); err != nil {
Expand Down
56 changes: 29 additions & 27 deletions gapis/api/gles/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,44 +51,46 @@ func (v Version) AtLeastGL(major, minor int) bool {
return !v.IsES && v.AtLeast(major, minor)
}

var versionRe = regexp.MustCompile(`^(OpenGL ES.*? )?(\d+)\.(\d+).*`)

// ParseVersion parses the GL version major, minor and flavour from the output of glGetString(GL_VERSION).
func ParseVersion(str string) (*Version, error) {
if match := versionRe.FindStringSubmatch(str); match != nil {
isES := len(match[1]) > 0 // Desktop GL doesn't have a flavour prefix.
major, _ := strconv.Atoi(match[2])
minor, _ := strconv.Atoi(match[3])
return &Version{IsES: isES, Major: major, Minor: minor}, nil
}
return nil, fmt.Errorf("Unknown GL_VERSION format: %s", str)
}

// GLSLVersion returns the highest supported GLSL version for the given GL version.
func GLSLVersion(glVersion string) (Version, error) {
v, err := ParseVersion(glVersion)
if err != nil {
return Version{}, err
}
// MaxGLSL returns the highest supported GLSL version for the given GL version.
func (v Version) MaxGLSL() Version {
major, minor, isES := v.Major, v.Minor, v.IsES
switch {
case major == 2 && isES:
return Version{Major: 1, Minor: 0}, nil
return Version{Major: 1, Minor: 0}
case major == 3 && isES:
return Version{Major: 3, Minor: 0}, nil
return Version{Major: 3, Minor: 0}

case major == 2 && minor == 0 && !isES:
return Version{Major: 1, Minor: 1}, nil
return Version{Major: 1, Minor: 1}
case major == 2 && minor == 1 && !isES:
return Version{Major: 1, Minor: 2}, nil
return Version{Major: 1, Minor: 2}
case major == 3 && minor == 0 && !isES:
return Version{Major: 1, Minor: 3}, nil
return Version{Major: 1, Minor: 3}
case major == 3 && minor == 1 && !isES:
return Version{Major: 1, Minor: 4}, nil
return Version{Major: 1, Minor: 4}
case major == 3 && minor == 2 && !isES:
return Version{Major: 1, Minor: 5}, nil
return Version{Major: 1, Minor: 5}

default:
return Version{Major: major, Minor: minor}, nil
return Version{Major: major, Minor: minor}
}
}

// AsInt returns the version in the form Mmm, where M is the major version and
// m is the minor version.
func (v Version) AsInt() int {
return v.Major*100 + v.Minor*10
}

var versionRe = regexp.MustCompile(`^(OpenGL ES.*? )?(\d+)\.(\d+).*`)

// ParseVersion parses the GL version major, minor and flavour from the output of glGetString(GL_VERSION).
func ParseVersion(str string) (*Version, error) {
if match := versionRe.FindStringSubmatch(str); match != nil {
isES := len(match[1]) > 0 // Desktop GL doesn't have a flavour prefix.
major, _ := strconv.Atoi(match[2])
minor, _ := strconv.Atoi(match[3])
return &Version{IsES: isES, Major: major, Minor: minor}, nil
}
return nil, fmt.Errorf("Unknown GL_VERSION format: %s", str)
}
3 changes: 2 additions & 1 deletion gapis/shadertools/cc/libmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ code_with_debug_info_t* convertGlsl(const char* input, size_t length, const conv
strcpy(result->disassembly_string, tmp.c_str());
}

std::string source = spirv2glsl(std::move(spirv_new), options->strip_optimizations);
std::string source = spirv2glsl(std::move(spirv_new),
options->target_glsl_version, options->strip_optimizations);

result->source_code = new char[source.length() + 1];
strcpy(result->source_code, source.c_str());
Expand Down
1 change: 1 addition & 0 deletions gapis/shadertools/cc/libmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ typedef struct convert_options_t {
bool disassemble;
bool relaxed;
bool strip_optimizations;
int target_glsl_version;
} convert_options_t;

typedef struct compile_options_t {
Expand Down
4 changes: 2 additions & 2 deletions gapis/shadertools/cc/spirv2glsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
// so it is important we never include both at the same time.
#include "third_party/SPIRV-Cross/spirv_glsl.hpp"

std::string spirv2glsl(std::vector<uint32_t> spirv, bool strip_optimizations) {
std::string spirv2glsl(std::vector<uint32_t> spirv, int glsl_version, bool strip_optimizations) {
spirv_cross::CompilerGLSL glsl(std::move(spirv));
spirv_cross::CompilerGLSL::Options cross_options;
cross_options.version = 330;
cross_options.version = glsl_version == 0 ? 330 : glsl_version;
cross_options.es = false;
cross_options.force_temporary = false;
cross_options.vertex.fixup_clipspace = false;
Expand Down
2 changes: 1 addition & 1 deletion gapis/shadertools/cc/spirv2glsl.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
#include <string>
#include <vector>

std::string spirv2glsl(std::vector<uint32_t> spirv, bool strip_optimizations);
std::string spirv2glsl(std::vector<uint32_t> spirv, int glsl_version, bool strip_optimizations);
3 changes: 3 additions & 0 deletions gapis/shadertools/shadertools.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ func (t ShaderType) String() string {
type ConvertOptions struct {
// The type of shader.
ShaderType ShaderType
// The target GLSL version (default 330).
TargetGLSLVersion int
// Shader source preamble.
Preamble string
// Whether to add prefix to all non-builtin symbols.
Expand Down Expand Up @@ -175,6 +177,7 @@ func ConvertGlsl(source string, o *ConvertOptions) (CodeWithDebugInfo, error) {
disassemble: C.bool(o.Disassemble),
relaxed: C.bool(o.Relaxed),
strip_optimizations: C.bool(o.StripOptimizations),
target_glsl_version: C.int(o.TargetGLSLVersion),
}
result := C.convertGlsl(cstr(source), C.size_t(len(source)), &opts)
defer C.deleteGlslCodeWithDebug(result)
Expand Down
1 change: 1 addition & 0 deletions gapis/shadertools/shadertools_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ void main()
ShaderType: shadertools.TypeFragment,
CheckAfterChanges: true,
StripOptimizations: true,
TargetGLSLVersion: 330,
},
`#version 310 es
layout(early_fragment_tests) in;
Expand Down

0 comments on commit 2ce48b3

Please sign in to comment.