Ginger3D/src/main/java/com/github/hydos/ginger/engine/vulkan/misc/ShaderSPIRVUtils.java

90 lines
2.7 KiB
Java

package com.github.hydos.ginger.engine.vulkan.misc;
import org.lwjgl.system.NativeResource;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;
import static java.lang.ClassLoader.getSystemClassLoader;
import static org.lwjgl.system.MemoryUtil.NULL;
import static org.lwjgl.util.shaderc.Shaderc.*;
public class ShaderSPIRVUtils {
public static SPIRV compileShaderFile(String shaderFile, ShaderKind shaderKind) {
return compileShaderAbsoluteFile(getSystemClassLoader().getResource(shaderFile).toExternalForm(), shaderKind);
}
public static SPIRV compileShaderAbsoluteFile(String shaderFile, ShaderKind shaderKind) {
try {
String source = new String(Files.readAllBytes(Paths.get(new URI(shaderFile))));
return compileShader(shaderFile, source, shaderKind);
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
return null;
}
public static SPIRV compileShader(String filename, String source, ShaderKind shaderKind) {
long compiler = shaderc_compiler_initialize();
if(compiler == NULL) {
throw new RuntimeException("Failed to create shader compiler");
}
long result = shaderc_compile_into_spv(compiler, source, shaderKind.kind, filename, "main", NULL);
if(result == NULL) {
throw new RuntimeException("Failed to compile shader " + filename + " into SPIR-V");
}
if(shaderc_result_get_compilation_status(result) != shaderc_compilation_status_success) {
throw new RuntimeException("Failed to compile shader " + filename + "into SPIR-V:\n " + shaderc_result_get_error_message(result));
}
shaderc_compiler_release(compiler);
return new SPIRV(result, shaderc_result_get_bytes(result));
}
public enum ShaderKind {
VERTEX_SHADER(shaderc_glsl_vertex_shader),
GEOMETRY_SHADER(shaderc_glsl_geometry_shader),
FRAGMENT_SHADER(shaderc_glsl_fragment_shader);
private final int kind;
ShaderKind(int kind) {
this.kind = kind;
}
}
public static final class SPIRV implements NativeResource {
private final long handle;
private ByteBuffer bytecode;
public SPIRV(long handle, ByteBuffer bytecode) {
this.handle = handle;
this.bytecode = bytecode;
}
public ByteBuffer bytecode() {
return bytecode;
}
@Override
public void free() {
shaderc_result_release(handle);
bytecode = null; // Help the GC
}
}
}