diff --git a/src/main/java/me/cortex/voxy/client/core/gl/Capabilities.java b/src/main/java/me/cortex/voxy/client/core/gl/Capabilities.java index 8a24377c..5e695eee 100644 --- a/src/main/java/me/cortex/voxy/client/core/gl/Capabilities.java +++ b/src/main/java/me/cortex/voxy/client/core/gl/Capabilities.java @@ -2,11 +2,27 @@ package me.cortex.voxy.client.core.gl; import me.cortex.voxy.client.core.gl.shader.ShaderType; import org.lwjgl.opengl.GL; +import org.lwjgl.opengl.GL11C; import org.lwjgl.opengl.GL20C; +import org.lwjgl.opengl.GL30; +import org.lwjgl.system.MemoryUtil; -import static org.lwjgl.opengl.GL11.*; +import java.util.Random; + +import static org.lwjgl.opengl.GL11.GL_NEAREST; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL15.glDeleteBuffers; +import static org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL; +import static org.lwjgl.opengl.GL30C.GL_MAP_READ_BIT; import static org.lwjgl.opengl.GL32.glGetInteger64; import static org.lwjgl.opengl.GL43C.GL_MAX_SHADER_STORAGE_BLOCK_SIZE; +import static org.lwjgl.opengl.GL44.GL_DYNAMIC_STORAGE_BIT; +import static org.lwjgl.opengl.GL44.GL_MAP_COHERENT_BIT; +import static org.lwjgl.opengl.GL45.glClearNamedFramebufferfi; +import static org.lwjgl.opengl.GL45C.*; +import static org.lwjgl.opengl.GL45C.glCreateFramebuffers; import static org.lwjgl.opengl.NVXGPUMemoryInfo.*; public class Capabilities { @@ -27,7 +43,9 @@ public class Capabilities { public final boolean subgroup; public final boolean sparseBuffer; public final boolean isNvidia; + public final boolean isAmd; public final boolean nvBarryCoords; + public final boolean hasBrokenDepthSampler; public Capabilities() { var cap = GL.getCapabilities(); @@ -64,8 +82,10 @@ public class Capabilities { this.ssboMaxSize = glGetInteger64(GL_MAX_SHADER_STORAGE_BLOCK_SIZE); this.isMesa = glGetString(GL_VERSION).toLowerCase().contains("mesa"); - this.isIntel = glGetString(GL_VENDOR).toLowerCase().contains("intel"); - this.isNvidia = glGetString(GL_VENDOR).toLowerCase().contains("nvidia"); + var vendor = glGetString(GL_VENDOR).toLowerCase(); + this.isIntel = vendor.contains("intel"); + this.isNvidia = vendor.contains("nvidia"); + this.isAmd = vendor.contains("amd")||vendor.contains("radeon"); if (this.canQueryGpuMemory) { this.totalDedicatedMemory = glGetInteger64(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX)*1024;//Since its in Kb @@ -76,11 +96,91 @@ public class Capabilities { } this.nvBarryCoords = cap.GL_NV_fragment_shader_barycentric; + + if (this.compute&&this.isAmd) { + this.hasBrokenDepthSampler = testDepthSampler(); + if (this.hasBrokenDepthSampler) { + //throw new IllegalStateException("it bork, amd is bork"); + } + } else { + this.hasBrokenDepthSampler = false; + } } public static void init() { } + private static boolean testDepthSampler() { + String src = """ + #version 460 core + layout(local_size_x=1) in; + + layout(binding = 0) uniform sampler2D depthSampler; + layout(binding = 1) buffer OutData { + float[] outData; + }; + + void main() { + outData[0] = texelFetch(depthSampler, ivec2(1, 1), 0).r; + } + """; + int program = GL20C.glCreateProgram(); + { + int shader = GL20C.glCreateShader(ShaderType.COMPUTE.gl); + GL20C.glShaderSource(shader, src); + GL20C.glCompileShader(shader); + if (GL20C.glGetShaderi(shader, GL20C.GL_COMPILE_STATUS) != 1) { + GL20C.glDeleteShader(shader); + throw new IllegalStateException("Shader compile fail"); + } + GL20C.glAttachShader(program, shader); + GL20C.glLinkProgram(program); + glDeleteShader(shader); + } + + int buffer = glCreateBuffers(); + glNamedBufferStorage(buffer, 4096, GL_DYNAMIC_STORAGE_BIT|GL_MAP_READ_BIT); + + int tex = glCreateTextures(GL_TEXTURE_2D); + glTextureStorage2D(tex, 1, GL_DEPTH24_STENCIL8, 3, 3); + glTextureParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTextureParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + int fb = glCreateFramebuffers(); + glNamedFramebufferTexture(fb, GL_DEPTH_STENCIL_ATTACHMENT, tex, 0); + + boolean isCorrect = true; + for (int i = 0; i <= 10; i++) { + float value = (float) (i/10.0); + + nglClearNamedBufferSubData(buffer, GL_R32F, 0, 4096, GL_RED, GL_FLOAT, 0);//Zero the buffer + glClearNamedFramebufferfi(fb, GL_DEPTH_STENCIL, 0, value, 1);//Set the depth texture + + glUseProgram(program); + glBindTextureUnit(0, tex); + GL30.glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer); + + glDispatchCompute(1,1,1); + glFinish(); + + long ptr = nglMapNamedBuffer(buffer, GL_READ_ONLY); + float gottenValue = MemoryUtil.memGetFloat(ptr); + glUnmapNamedBuffer(buffer); + + glUseProgram(0); + glBindTextureUnit(0,0); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + isCorrect &= Math.abs(value - gottenValue)<0.0000001f; + } + + glDeleteFramebuffers(fb); + glDeleteTextures(tex); + glDeleteBuffers(buffer); + glDeleteProgram(program); + return !isCorrect; + } + private static boolean testShaderCompilesOk(ShaderType type, String src) { int shader = GL20C.glCreateShader(type.gl); GL20C.glShaderSource(shader, src);