package shaderkit import "core:log" import "core:os" import gpu ".." import shader "../shader" Options :: struct { entry: string, opt_level: shader.Opt_Level, debug: bool, include_dirs: []string, file_reader: shader.File_Reader, } compile_target :: proc() -> shader.Target { when gpu.REQUIRED_SHADER_FORMAT == .SPIRV { return .SPIR_V } else when gpu.REQUIRED_SHADER_FORMAT == .HLSL { return .HLSL_SM6 } else when gpu.REQUIRED_SHADER_FORMAT == .GLSL { return .GLSL_450_OPENGL } else { #assert(false, "unsupported REQUIRED_SHADER_FORMAT") } } compile_options :: proc(stage: gpu.Shader_Stage, options: Options) -> shader.Compile_Options { return { target = compile_target(), opt_level = options.opt_level, stage = shader_stage(stage), entry = options.entry, debug = options.debug, include_dirs = options.include_dirs, file_reader = options.file_reader, hlsl_cbuffer_push_constants = true, hlsl_push_constant_slot = 13, hlsl_omit_register_spaces = true, } } compile_shader_source :: proc(name: string, stage: gpu.Shader_Stage, source: string, options: Options = {}, allocator := context.allocator) -> shader.Compile_Result { return shader.compile(source, compile_options(stage, options), name, allocator) } create_shader_from_source :: proc(name: string, stage: gpu.Shader_Stage, source: string, options: Options = {}) -> (gpu.Shader_Handle, bool) { result := compile_shader_source(name, stage, source, options) defer shader.destroy_compile_result(&result) if !result.success { log_compile_diagnostics(name, source, result.diagnostics) return {}, false } entry := options.entry if entry == "" do entry = "main" handle, ok := gpu.create_shader_module({ stage = stage, format = gpu.REQUIRED_SHADER_FORMAT, name = name, entry = entry, data = result.output, }) if !ok { log.errorf("gpu/shaderkit: failed to create shader module %s", name) return {}, false } return handle, true } create_shader_from_file :: proc(path: string, stage: gpu.Shader_Stage, options: Options = {}) -> (gpu.Shader_Handle, bool) { source, err := os.read_entire_file(path, context.allocator) if err != nil { log.errorf("gpu/shaderkit: failed to read shader source %s", path) return {}, false } defer delete(source) return create_shader_from_source(path, stage, string(source), options) } load_compute_shader_from_source :: proc(name: string, source: string, num_buffers: u32 = 4, push_constant_size: u32 = 0, options: Options = {}) -> gpu.Compute_Shader { result := compile_shader_source(name, .Compute, source, options) defer shader.destroy_compile_result(&result) if !result.success { log_compile_diagnostics(name, source, result.diagnostics) return {} } return gpu.load_compute_shader_from_bytes( name, result.output, gpu.REQUIRED_SHADER_FORMAT, num_buffers, push_constant_size, ) } log_compile_diagnostics :: proc(name, source: string, diagnostics: []shader.Diagnostic) { for d in diagnostics { msg := shader.format_diagnostic_with_source(d, source) log.errorf("gpu/shaderkit: %s: %s", name, msg) delete(msg) } } shader_stage :: proc(stage: gpu.Shader_Stage) -> shader.Shader_Stage { switch stage { case .Vertex: return .Vertex case .Fragment: return .Fragment case .Compute: return .Compute } return .None }