mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-04 17:24:59 +01:00
GLSL to the max
- Always compile with highest supported GLSL version - Allow indirect shaders to compile with as low as GLSL 420 - Fix GL extension checks for indirect - Explicitly initialize GlCompat as early as possible to avoid invalid initialization off render thread
This commit is contained in:
parent
08476b5779
commit
2ee3944ca6
11 changed files with 251 additions and 166 deletions
|
@ -17,7 +17,7 @@ public final class Backends {
|
|||
*/
|
||||
public static final Backend INSTANCING = SimpleBackend.builder()
|
||||
.engineFactory(level -> new EngineImpl(new InstancedDrawManager(InstancingPrograms.get()), 256))
|
||||
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.supportsInstancing() && InstancingPrograms.allLoaded())
|
||||
.supported(() -> GlCompat.SUPPORTS_INSTANCING && InstancingPrograms.allLoaded() && !ShadersModHandler.isShaderPackInUse())
|
||||
.register(Flywheel.rl("instancing"));
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,7 @@ public final class Backends {
|
|||
public static final Backend INDIRECT = SimpleBackend.builder()
|
||||
.engineFactory(level -> new EngineImpl(new IndirectDrawManager(IndirectPrograms.get()), 256))
|
||||
.fallback(() -> Backends.INSTANCING)
|
||||
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.supportsIndirect() && IndirectPrograms.allLoaded())
|
||||
.supported(() -> GlCompat.SUPPORTS_INDIRECT && IndirectPrograms.allLoaded() && !ShadersModHandler.isShaderPackInUse())
|
||||
.register(Flywheel.rl("indirect"));
|
||||
|
||||
private Backends() {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.jozufozu.flywheel.backend.compile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -33,6 +34,9 @@ public class IndirectPrograms extends AtomicReferenceCounted {
|
|||
private static final Compile<InstanceType<?>> CULL = new Compile<>();
|
||||
private static final Compile<ResourceLocation> UTIL = new Compile<>();
|
||||
|
||||
private static final List<String> EXTENSIONS = getExtensions(GlCompat.MAX_GLSL_VERSION);
|
||||
private static final List<String> COMPUTE_EXTENSIONS = getComputeExtensions(GlCompat.MAX_GLSL_VERSION);
|
||||
|
||||
@Nullable
|
||||
private static IndirectPrograms instance;
|
||||
|
||||
|
@ -48,10 +52,33 @@ public class IndirectPrograms extends AtomicReferenceCounted {
|
|||
this.scatter = scatter;
|
||||
}
|
||||
|
||||
private static List<String> getExtensions(GlslVersion glslVersion) {
|
||||
List<String> extensions = new ArrayList<>();
|
||||
if (glslVersion.compareTo(GlslVersion.V430) < 0) {
|
||||
extensions.add("GL_ARB_shader_storage_buffer_object");
|
||||
}
|
||||
if (glslVersion.compareTo(GlslVersion.V460) < 0) {
|
||||
extensions.add("GL_ARB_shader_draw_parameters");
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
private static List<String> getComputeExtensions(GlslVersion glslVersion) {
|
||||
List<String> extensions = new ArrayList<>();
|
||||
if (glslVersion.compareTo(GlslVersion.V430) < 0) {
|
||||
extensions.add("GL_ARB_compute_shader");
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
static void reload(ShaderSources sources, ImmutableList<PipelineProgramKey> pipelineKeys, List<SourceComponent> vertexComponents, List<SourceComponent> fragmentComponents) {
|
||||
if (!GlCompat.SUPPORTS_INDIRECT) {
|
||||
return;
|
||||
}
|
||||
|
||||
IndirectPrograms newInstance = null;
|
||||
|
||||
var pipelineCompiler = PipelineCompiler.create(sources, Pipelines.INDIRECT, vertexComponents, fragmentComponents);
|
||||
var pipelineCompiler = PipelineCompiler.create(sources, Pipelines.INDIRECT, vertexComponents, fragmentComponents, EXTENSIONS);
|
||||
var cullingCompiler = createCullingCompiler(sources);
|
||||
var applyCompiler = createUtilCompiler(sources);
|
||||
|
||||
|
@ -76,8 +103,10 @@ public class IndirectPrograms extends AtomicReferenceCounted {
|
|||
|
||||
private static CompilationHarness<InstanceType<?>> createCullingCompiler(ShaderSources sources) {
|
||||
return CULL.program()
|
||||
.link(CULL.shader(GlslVersion.V460, ShaderType.COMPUTE)
|
||||
.link(CULL.shader(GlCompat.MAX_GLSL_VERSION, ShaderType.COMPUTE)
|
||||
.nameMapper(instanceType -> "culling/" + ResourceUtil.toDebugFileNameNoExtension(instanceType.cullShader()))
|
||||
.enableExtensions(EXTENSIONS)
|
||||
.enableExtensions(COMPUTE_EXTENSIONS)
|
||||
.define("_FLW_SUBGROUP_SIZE", GlCompat.SUBGROUP_SIZE)
|
||||
.withResource(CULL_SHADER_API_IMPL)
|
||||
.withComponent(InstanceStructComponent::new)
|
||||
|
@ -96,8 +125,10 @@ public class IndirectPrograms extends AtomicReferenceCounted {
|
|||
|
||||
private static CompilationHarness<ResourceLocation> createUtilCompiler(ShaderSources sources) {
|
||||
return UTIL.program()
|
||||
.link(UTIL.shader(GlslVersion.V460, ShaderType.COMPUTE)
|
||||
.link(UTIL.shader(GlCompat.MAX_GLSL_VERSION, ShaderType.COMPUTE)
|
||||
.nameMapper(resourceLocation -> "utilities/" + ResourceUtil.toDebugFileNameNoExtension(resourceLocation))
|
||||
.enableExtensions(EXTENSIONS)
|
||||
.enableExtensions(COMPUTE_EXTENSIONS)
|
||||
.define("_FLW_SUBGROUP_SIZE", GlCompat.SUBGROUP_SIZE)
|
||||
.withResource(s -> s))
|
||||
.harness("utilities", sources);
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||
import com.jozufozu.flywheel.backend.gl.GlCompat;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.backend.glsl.ShaderSources;
|
||||
import com.jozufozu.flywheel.backend.glsl.SourceComponent;
|
||||
|
@ -23,6 +24,10 @@ public class InstancingPrograms extends AtomicReferenceCounted {
|
|||
}
|
||||
|
||||
static void reload(ShaderSources sources, ImmutableList<PipelineProgramKey> pipelineKeys, List<SourceComponent> vertexComponents, List<SourceComponent> fragmentComponents) {
|
||||
if (!GlCompat.SUPPORTS_INSTANCING) {
|
||||
return;
|
||||
}
|
||||
|
||||
InstancingPrograms newInstance = null;
|
||||
|
||||
var pipelineCompiler = PipelineCompiler.create(sources, Pipelines.INSTANCING, vertexComponents, fragmentComponents);
|
||||
|
|
|
@ -8,12 +8,11 @@ import org.jetbrains.annotations.Nullable;
|
|||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.backend.glsl.GlslVersion;
|
||||
import com.jozufozu.flywheel.backend.glsl.SourceComponent;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public record Pipeline(GlslVersion glslVersion, ResourceLocation vertexMain, ResourceLocation fragmentMain,
|
||||
public record Pipeline(ResourceLocation vertexMain, ResourceLocation fragmentMain,
|
||||
InstanceAssembler assembler, String compilerMarker, Consumer<GlProgram> onLink) {
|
||||
|
||||
@FunctionalInterface
|
||||
|
@ -31,8 +30,6 @@ public record Pipeline(GlslVersion glslVersion, ResourceLocation vertexMain, Res
|
|||
}
|
||||
|
||||
public static class Builder {
|
||||
@Nullable
|
||||
private GlslVersion glslVersion;
|
||||
@Nullable
|
||||
private ResourceLocation vertexMain;
|
||||
@Nullable
|
||||
|
@ -44,11 +41,6 @@ public record Pipeline(GlslVersion glslVersion, ResourceLocation vertexMain, Res
|
|||
@Nullable
|
||||
private Consumer<GlProgram> onLink;
|
||||
|
||||
public Builder glslVersion(GlslVersion glslVersion) {
|
||||
this.glslVersion = glslVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder vertexMain(ResourceLocation shader) {
|
||||
this.vertexMain = shader;
|
||||
return this;
|
||||
|
@ -75,13 +67,12 @@ public record Pipeline(GlslVersion glslVersion, ResourceLocation vertexMain, Res
|
|||
}
|
||||
|
||||
public Pipeline build() {
|
||||
Objects.requireNonNull(glslVersion);
|
||||
Objects.requireNonNull(vertexMain);
|
||||
Objects.requireNonNull(fragmentMain);
|
||||
Objects.requireNonNull(assembler);
|
||||
Objects.requireNonNull(compilerMarker);
|
||||
Objects.requireNonNull(onLink);
|
||||
return new Pipeline(glslVersion, vertexMain, fragmentMain, assembler, compilerMarker, onLink);
|
||||
return new Pipeline(vertexMain, fragmentMain, assembler, compilerMarker, onLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.jozufozu.flywheel.backend.compile;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
|
@ -9,6 +11,7 @@ import com.jozufozu.flywheel.backend.compile.component.InstanceStructComponent;
|
|||
import com.jozufozu.flywheel.backend.compile.core.CompilationHarness;
|
||||
import com.jozufozu.flywheel.backend.compile.core.Compile;
|
||||
import com.jozufozu.flywheel.backend.engine.uniform.Uniforms;
|
||||
import com.jozufozu.flywheel.backend.gl.GlCompat;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||
import com.jozufozu.flywheel.backend.glsl.ShaderSources;
|
||||
|
@ -23,9 +26,9 @@ public final class PipelineCompiler {
|
|||
private static final ResourceLocation API_IMPL_VERT = Flywheel.rl("internal/api_impl.vert");
|
||||
private static final ResourceLocation API_IMPL_FRAG = Flywheel.rl("internal/api_impl.frag");
|
||||
|
||||
static CompilationHarness<PipelineProgramKey> create(ShaderSources sources, Pipeline pipeline, List<SourceComponent> vertexComponents, List<SourceComponent> fragmentComponents) {
|
||||
static CompilationHarness<PipelineProgramKey> create(ShaderSources sources, Pipeline pipeline, List<SourceComponent> vertexComponents, List<SourceComponent> fragmentComponents, Collection<String> extensions) {
|
||||
return PIPELINE.program()
|
||||
.link(PIPELINE.shader(pipeline.glslVersion(), ShaderType.VERTEX)
|
||||
.link(PIPELINE.shader(GlCompat.MAX_GLSL_VERSION, ShaderType.VERTEX)
|
||||
.nameMapper(key -> {
|
||||
var instance = ResourceUtil.toDebugFileNameNoExtension(key.instanceType()
|
||||
.vertexShader());
|
||||
|
@ -34,6 +37,7 @@ public final class PipelineCompiler {
|
|||
.nameLowerCase();
|
||||
return "pipeline/" + pipeline.compilerMarker() + "/" + instance + "_" + context;
|
||||
})
|
||||
.enableExtensions(extensions)
|
||||
.onCompile((key, comp) -> key.contextShader()
|
||||
.onCompile(comp))
|
||||
.withResource(API_IMPL_VERT)
|
||||
|
@ -45,12 +49,13 @@ public final class PipelineCompiler {
|
|||
.withComponent(key -> pipeline.assembler()
|
||||
.assemble(key.instanceType()))
|
||||
.withResource(pipeline.vertexMain()))
|
||||
.link(PIPELINE.shader(pipeline.glslVersion(), ShaderType.FRAGMENT)
|
||||
.link(PIPELINE.shader(GlCompat.MAX_GLSL_VERSION, ShaderType.FRAGMENT)
|
||||
.nameMapper(key -> {
|
||||
var context = key.contextShader()
|
||||
.nameLowerCase();
|
||||
return "pipeline/" + pipeline.compilerMarker() + "/" + context;
|
||||
})
|
||||
.enableExtensions(extensions)
|
||||
.enableExtension("GL_ARB_conservative_depth")
|
||||
.onCompile((key, comp) -> key.contextShader()
|
||||
.onCompile(comp))
|
||||
|
@ -86,4 +91,8 @@ public final class PipelineCompiler {
|
|||
})
|
||||
.harness(pipeline.compilerMarker(), sources);
|
||||
}
|
||||
|
||||
static CompilationHarness<PipelineProgramKey> create(ShaderSources sources, Pipeline pipeline, List<SourceComponent> vertexComponents, List<SourceComponent> fragmentComponents) {
|
||||
return create(sources, pipeline, vertexComponents, fragmentComponents, Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,10 @@ import com.jozufozu.flywheel.Flywheel;
|
|||
import com.jozufozu.flywheel.backend.Samplers;
|
||||
import com.jozufozu.flywheel.backend.compile.component.BufferTextureInstanceComponent;
|
||||
import com.jozufozu.flywheel.backend.compile.component.SsboInstanceComponent;
|
||||
import com.jozufozu.flywheel.backend.glsl.GlslVersion;
|
||||
|
||||
public final class Pipelines {
|
||||
public static final Pipeline INSTANCING = Pipeline.builder()
|
||||
.compilerMarker("instancing")
|
||||
.glslVersion(GlslVersion.V330)
|
||||
.vertexMain(Flywheel.rl("internal/instancing/main.vert"))
|
||||
.fragmentMain(Flywheel.rl("internal/instancing/main.frag"))
|
||||
.assembler(BufferTextureInstanceComponent::new)
|
||||
|
@ -18,7 +16,6 @@ public final class Pipelines {
|
|||
|
||||
public static final Pipeline INDIRECT = Pipeline.builder()
|
||||
.compilerMarker("indirect")
|
||||
.glslVersion(GlslVersion.V460)
|
||||
.vertexMain(Flywheel.rl("internal/indirect/main.vert"))
|
||||
.fragmentMain(Flywheel.rl("internal/indirect/main.frag"))
|
||||
.assembler(SsboInstanceComponent::new)
|
||||
|
|
|
@ -40,6 +40,100 @@ public class Compile<K> {
|
|||
return new ProgramStitcher<>();
|
||||
}
|
||||
|
||||
public static class ShaderCompiler<K> {
|
||||
private final GlslVersion glslVersion;
|
||||
private final ShaderType shaderType;
|
||||
private final List<BiFunction<K, SourceLoader, @Nullable SourceComponent>> fetchers = new ArrayList<>();
|
||||
private BiConsumer<K, Compilation> compilationCallbacks = ($, $$) -> {
|
||||
};
|
||||
private Function<K, String> nameMapper = Object::toString;
|
||||
|
||||
public ShaderCompiler(GlslVersion glslVersion, ShaderType shaderType) {
|
||||
this.glslVersion = glslVersion;
|
||||
this.shaderType = shaderType;
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> nameMapper(Function<K, String> nameMapper) {
|
||||
this.nameMapper = nameMapper;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> with(BiFunction<K, SourceLoader, @Nullable SourceComponent> fetch) {
|
||||
fetchers.add(fetch);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> withComponents(Collection<@Nullable SourceComponent> components) {
|
||||
components.forEach(this::withComponent);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> withComponent(@Nullable SourceComponent component) {
|
||||
return withComponent($ -> component);
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> withComponent(Function<K, @Nullable SourceComponent> sourceFetcher) {
|
||||
return with((key, $) -> sourceFetcher.apply(key));
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> withResource(Function<K, ResourceLocation> sourceFetcher) {
|
||||
return with((key, loader) -> loader.find(sourceFetcher.apply(key)));
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> withResource(ResourceLocation resourceLocation) {
|
||||
return withResource($ -> resourceLocation);
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> onCompile(BiConsumer<K, Compilation> cb) {
|
||||
compilationCallbacks = compilationCallbacks.andThen(cb);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> define(String def, int value) {
|
||||
return onCompile(($, ctx) -> ctx.define(def, String.valueOf(value)));
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> enableExtension(String extension) {
|
||||
return onCompile(($, ctx) -> ctx.enableExtension(extension));
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> enableExtensions(String... extensions) {
|
||||
return onCompile(($, ctx) -> {
|
||||
for (String extension : extensions) {
|
||||
ctx.enableExtension(extension);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> enableExtensions(Collection<String> extensions) {
|
||||
return onCompile(($, ctx) -> {
|
||||
for (String extension : extensions) {
|
||||
ctx.enableExtension(extension);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GlShader compile(K key, ShaderCache compiler, SourceLoader loader) {
|
||||
var components = new ArrayList<SourceComponent>();
|
||||
boolean ok = true;
|
||||
for (var fetcher : fetchers) {
|
||||
SourceComponent apply = fetcher.apply(key, loader);
|
||||
if (apply == null) {
|
||||
ok = false;
|
||||
}
|
||||
components.add(apply);
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Consumer<Compilation> cb = ctx -> compilationCallbacks.accept(key, ctx);
|
||||
return compiler.compile(glslVersion, shaderType, nameMapper.apply(key), cb, components);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProgramStitcher<K> implements CompilationHarness.KeyCompiler<K> {
|
||||
private final Map<ShaderType, ShaderCompiler<K>> compilers = new EnumMap<>(ShaderType.class);
|
||||
private BiConsumer<K, GlProgram> postLink = (k, p) -> {
|
||||
|
@ -100,82 +194,4 @@ public class Compile<K> {
|
|||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ShaderCompiler<K> {
|
||||
private final GlslVersion glslVersion;
|
||||
private final ShaderType shaderType;
|
||||
private final List<BiFunction<K, SourceLoader, @Nullable SourceComponent>> fetchers = new ArrayList<>();
|
||||
private BiConsumer<K, Compilation> compilationCallbacks = ($, $$) -> {
|
||||
};
|
||||
private Function<K, String> nameMapper = Object::toString;
|
||||
|
||||
public ShaderCompiler(GlslVersion glslVersion, ShaderType shaderType) {
|
||||
this.glslVersion = glslVersion;
|
||||
this.shaderType = shaderType;
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> nameMapper(Function<K, String> nameMapper) {
|
||||
this.nameMapper = nameMapper;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> with(BiFunction<K, SourceLoader, @Nullable SourceComponent> fetch) {
|
||||
fetchers.add(fetch);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> withComponents(Collection<@Nullable SourceComponent> components) {
|
||||
components.forEach(this::withComponent);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> withComponent(@Nullable SourceComponent component) {
|
||||
return withComponent($ -> component);
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> withComponent(Function<K, @Nullable SourceComponent> sourceFetcher) {
|
||||
return with((key, $) -> sourceFetcher.apply(key));
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> withResource(Function<K, ResourceLocation> sourceFetcher) {
|
||||
return with((key, loader) -> loader.find(sourceFetcher.apply(key)));
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> withResource(ResourceLocation resourceLocation) {
|
||||
return withResource($ -> resourceLocation);
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> onCompile(BiConsumer<K, Compilation> cb) {
|
||||
compilationCallbacks = compilationCallbacks.andThen(cb);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> define(String def, int value) {
|
||||
return onCompile(($, ctx) -> ctx.define(def, String.valueOf(value)));
|
||||
}
|
||||
|
||||
public ShaderCompiler<K> enableExtension(String extension) {
|
||||
return onCompile(($, ctx) -> ctx.enableExtension(extension));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GlShader compile(K key, ShaderCache compiler, SourceLoader loader) {
|
||||
var components = new ArrayList<SourceComponent>();
|
||||
boolean ok = true;
|
||||
for (var fetcher : fetchers) {
|
||||
SourceComponent apply = fetcher.apply(key, loader);
|
||||
if (apply == null) {
|
||||
ok = false;
|
||||
}
|
||||
components.add(apply);
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Consumer<Compilation> cb = ctx -> compilationCallbacks.accept(key, ctx);
|
||||
return compiler.compile(glslVersion, shaderType, nameMapper.apply(key), cb, components);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,78 +10,23 @@ import org.lwjgl.opengl.GLCapabilities;
|
|||
import org.lwjgl.opengl.KHRShaderSubgroup;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
import com.jozufozu.flywheel.backend.glsl.GlslVersion;
|
||||
import com.jozufozu.flywheel.lib.math.MoreMath;
|
||||
|
||||
import net.minecraft.Util;
|
||||
|
||||
/**
|
||||
* An instance of this class stores information about what OpenGL features are available.
|
||||
* <br>
|
||||
* Each field stores an enum variant that provides access to the most appropriate version of a feature for the current
|
||||
* system.
|
||||
*/
|
||||
public final class GlCompat {
|
||||
public static final GLCapabilities CAPABILITIES = GL.createCapabilities();
|
||||
public static final boolean WINDOWS = _decideIfWeAreWindows();
|
||||
public static final GLCapabilities CAPABILITIES = GL.getCapabilities();
|
||||
public static final Driver DRIVER = readVendorString();
|
||||
public static final int SUBGROUP_SIZE = subgroupSize();
|
||||
public static final boolean ALLOW_DSA = true;
|
||||
public static final boolean SUPPORTS_INDIRECT = _decideIfWeSupportIndirect();
|
||||
public static final int SUBGROUP_SIZE = _subgroupSize();
|
||||
public static final Driver DRIVER = _readVendorString();
|
||||
public static final GlslVersion MAX_GLSL_VERSION = maxGlslVersion();
|
||||
|
||||
public static final boolean SUPPORTS_INSTANCING = isInstancingSupported();
|
||||
public static final boolean SUPPORTS_INDIRECT = isIndirectSupported();
|
||||
|
||||
private GlCompat() {
|
||||
}
|
||||
|
||||
public static boolean onAMDWindows() {
|
||||
return DRIVER == Driver.AMD && WINDOWS;
|
||||
}
|
||||
|
||||
public static boolean supportsInstancing() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean supportsIndirect() {
|
||||
return SUPPORTS_INDIRECT;
|
||||
}
|
||||
|
||||
private static Driver _readVendorString() {
|
||||
String vendor = GL20C.glGetString(GL20C.GL_VENDOR);
|
||||
|
||||
if (vendor == null) {
|
||||
return Driver.UNKNOWN;
|
||||
}
|
||||
|
||||
// vendor string I got was "ATI Technologies Inc."
|
||||
if (vendor.contains("ATI") || vendor.contains("AMD")) {
|
||||
return Driver.AMD;
|
||||
} else if (vendor.contains("NVIDIA")) {
|
||||
return Driver.NVIDIA;
|
||||
} else if (vendor.contains("Intel")) {
|
||||
return Driver.INTEL;
|
||||
} else if (vendor.contains("Mesa")) {
|
||||
return Driver.MESA;
|
||||
}
|
||||
|
||||
return Driver.UNKNOWN;
|
||||
}
|
||||
|
||||
private static boolean _decideIfWeAreWindows() {
|
||||
return Util.getPlatform() == Util.OS.WINDOWS;
|
||||
}
|
||||
|
||||
private static boolean _decideIfWeSupportIndirect() {
|
||||
return CAPABILITIES.OpenGL46 || (CAPABILITIES.GL_ARB_compute_shader && CAPABILITIES.GL_ARB_shader_draw_parameters && CAPABILITIES.GL_ARB_base_instance && CAPABILITIES.GL_ARB_multi_draw_indirect && CAPABILITIES.GL_ARB_direct_state_access);
|
||||
}
|
||||
|
||||
private static int _subgroupSize() {
|
||||
if (CAPABILITIES.GL_KHR_shader_subgroup) {
|
||||
return GL31C.glGetInteger(KHRShaderSubgroup.GL_SUBGROUP_SIZE_KHR);
|
||||
}
|
||||
// Try to guess.
|
||||
// Newer (RDNA) AMD cards have 32 threads in a wavefront, older ones have 64.
|
||||
// I assume the newer drivers will implement the above extension, so 64 is a
|
||||
// reasonable guess for AMD hardware. In the worst case we'll just spread
|
||||
// load across multiple SIMDs
|
||||
return DRIVER == Driver.AMD || DRIVER == Driver.MESA ? 64 : 32;
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
public static int getComputeGroupCount(int invocations) {
|
||||
|
@ -108,5 +53,83 @@ public final class GlCompat {
|
|||
GL20C.nglShaderSource(glId, 1, pointers.address0(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Driver readVendorString() {
|
||||
String vendor = GL20C.glGetString(GL20C.GL_VENDOR);
|
||||
|
||||
if (vendor == null) {
|
||||
return Driver.UNKNOWN;
|
||||
}
|
||||
|
||||
// vendor string I got was "ATI Technologies Inc."
|
||||
if (vendor.contains("ATI") || vendor.contains("AMD")) {
|
||||
return Driver.AMD;
|
||||
} else if (vendor.contains("NVIDIA")) {
|
||||
return Driver.NVIDIA;
|
||||
} else if (vendor.contains("Intel")) {
|
||||
return Driver.INTEL;
|
||||
} else if (vendor.contains("Mesa")) {
|
||||
return Driver.MESA;
|
||||
}
|
||||
|
||||
return Driver.UNKNOWN;
|
||||
}
|
||||
|
||||
private static int subgroupSize() {
|
||||
if (CAPABILITIES.GL_KHR_shader_subgroup) {
|
||||
return GL31C.glGetInteger(KHRShaderSubgroup.GL_SUBGROUP_SIZE_KHR);
|
||||
}
|
||||
|
||||
// Try to guess.
|
||||
// Newer (RDNA) AMD cards have 32 threads in a wavefront, older ones have 64.
|
||||
// I assume the newer drivers will implement the above extension, so 64 is a
|
||||
// reasonable guess for AMD hardware. In the worst case we'll just spread
|
||||
// load across multiple SIMDs
|
||||
return DRIVER == Driver.AMD || DRIVER == Driver.MESA ? 64 : 32;
|
||||
}
|
||||
|
||||
private static GlslVersion maxGlslVersion() {
|
||||
if (CAPABILITIES.OpenGL46) {
|
||||
return GlslVersion.V460;
|
||||
} else if (CAPABILITIES.OpenGL45) {
|
||||
return GlslVersion.V450;
|
||||
} else if (CAPABILITIES.OpenGL44) {
|
||||
return GlslVersion.V440;
|
||||
} else if (CAPABILITIES.OpenGL43) {
|
||||
return GlslVersion.V430;
|
||||
} else if (CAPABILITIES.OpenGL42) {
|
||||
return GlslVersion.V420;
|
||||
} else if (CAPABILITIES.OpenGL41) {
|
||||
return GlslVersion.V410;
|
||||
} else if (CAPABILITIES.OpenGL40) {
|
||||
return GlslVersion.V400;
|
||||
} else if (CAPABILITIES.OpenGL33) {
|
||||
return GlslVersion.V330;
|
||||
} else {
|
||||
return GlslVersion.V150;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInstancingSupported() {
|
||||
if (!CAPABILITIES.OpenGL33) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isIndirectSupported() {
|
||||
// The GL requirement cannot be lower because GL_ARB_compute_shader requires at least GL 4.2.
|
||||
if (!CAPABILITIES.OpenGL42) {
|
||||
return false;
|
||||
}
|
||||
if (CAPABILITIES.OpenGL46) {
|
||||
return true;
|
||||
}
|
||||
return CAPABILITIES.GL_ARB_compute_shader
|
||||
&& CAPABILITIES.GL_ARB_direct_state_access
|
||||
&& CAPABILITIES.GL_ARB_multi_bind
|
||||
&& CAPABILITIES.GL_ARB_multi_draw_indirect
|
||||
&& CAPABILITIES.GL_ARB_shader_draw_parameters
|
||||
&& CAPABILITIES.GL_ARB_shader_storage_buffer_object;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,5 +26,4 @@ public enum GlslVersion {
|
|||
public String toString() {
|
||||
return Integer.toString(version);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,10 +6,16 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.jozufozu.flywheel.backend.engine.uniform.Uniforms;
|
||||
import com.jozufozu.flywheel.backend.gl.GlCompat;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
@Mixin(RenderSystem.class)
|
||||
abstract class RenderSystemMixin {
|
||||
@Inject(method = "initRenderer(IZ)V", at = @At("RETURN"))
|
||||
private static void flywheel$onInitRenderer(CallbackInfo ci) {
|
||||
GlCompat.init();
|
||||
}
|
||||
|
||||
@Inject(method = "setShaderFogStart(F)V", at = @At("RETURN"))
|
||||
private static void flywheel$onSetFogStart(CallbackInfo ci) {
|
||||
Uniforms.onFogUpdate();
|
||||
|
|
|
@ -16,7 +16,11 @@ uniform uint _flw_baseDraw;
|
|||
flat out uvec3 _flw_packedMaterial;
|
||||
|
||||
void main() {
|
||||
#if __VERSION__ < 460
|
||||
uint drawIndex = gl_DrawIDARB + _flw_baseDraw;
|
||||
#else
|
||||
uint drawIndex = gl_DrawID + _flw_baseDraw;
|
||||
#endif
|
||||
MeshDrawCommand draw = _flw_drawCommands[drawIndex];
|
||||
|
||||
_flw_uberMaterialVertexIndex = draw.materialVertexIndex;
|
||||
|
@ -24,7 +28,11 @@ void main() {
|
|||
_flw_unpackMaterialProperties(packedMaterialProperties, flw_material);
|
||||
_flw_packedMaterial = uvec3(draw.materialFragmentIndex, draw.packedFogAndCutout, packedMaterialProperties);
|
||||
|
||||
#if __VERSION__ < 460
|
||||
uint instanceIndex = _flw_instanceIndices[gl_BaseInstanceARB + gl_InstanceID];
|
||||
#else
|
||||
uint instanceIndex = _flw_instanceIndices[gl_BaseInstance + gl_InstanceID];
|
||||
#endif
|
||||
FlwInstance instance = _flw_unpackInstance(instanceIndex);
|
||||
|
||||
_flw_main(instance, instanceIndex);
|
||||
|
|
Loading…
Reference in a new issue