Files
armorpaint/base/sources/ts/iron/shader_data.ts
T
luboslenco d48bdfbb31 Use kong
2025-04-10 18:09:06 +02:00

399 lines
11 KiB
TypeScript

function shader_data_create(raw: shader_data_t): shader_data_t {
raw._ = {};
raw._.contexts = [];
for (let i: i32 = 0; i < raw.contexts.length; ++i) {
let c: shader_context_t = raw.contexts[i];
let con: shader_context_t = shader_context_create(c);
array_push(raw._.contexts, con);
}
return raw;
}
function shader_data_ext(): string {
///if arm_vulkan
return ".spirv";
///elseif arm_metal
return ".metal";
///else
return ".d3d11";
///end
}
function shader_data_parse(file: string, name: string): shader_data_t {
let format: scene_t = data_get_scene_raw(file);
let raw: shader_data_t = shader_data_get_raw_by_name(format.shader_datas, name);
if (raw == null) {
iron_log("Shader data '" + name + "' not found!");
return null;
}
return shader_data_create(raw);
}
function shader_data_get_raw_by_name(datas: shader_data_t[], name: string): shader_data_t {
if (name == "") {
return datas[0];
}
for (let i: i32 = 0; i < datas.length; ++i) {
if (datas[i].name == name) {
return datas[i];
}
}
return null;
}
function shader_data_delete(raw: shader_data_t) {
for (let i: i32 = 0; i < raw._.contexts.length; ++i) {
let c: shader_context_t = raw._.contexts[i];
shader_context_delete(c);
}
}
function shader_data_get_context(raw: shader_data_t, name: string): shader_context_t {
for (let i: i32 = 0; i < raw._.contexts.length; ++i) {
let c: shader_context_t = raw._.contexts[i];
if (c.name == name) {
return c;
}
}
return null;
}
function shader_context_create(raw: shader_context_t): shader_context_t {
raw._ = {};
shader_context_parse_vertex_struct(raw);
return shader_context_compile(raw);
}
function shader_context_compile(raw: shader_context_t): shader_context_t {
if (raw._.pipe_state != null) {
gpu_delete_pipeline(raw._.pipe_state);
}
raw._.pipe_state = gpu_create_pipeline();
raw._.constants = [];
raw._.tex_units = [];
raw._.pipe_state.input_layout = raw._.structure;
// Depth
raw._.pipe_state.depth_write = raw.depth_write;
raw._.pipe_state.depth_mode = shader_context_get_compare_mode(raw.compare_mode);
// Cull
raw._.pipe_state.cull_mode = shader_context_get_cull_mode(raw.cull_mode);
// Blending
if (raw.blend_source != null) {
raw._.pipe_state.blend_source = shader_context_get_blend_fac(raw.blend_source);
}
if (raw.blend_destination != null) {
raw._.pipe_state.blend_destination = shader_context_get_blend_fac(raw.blend_destination);
}
if (raw.alpha_blend_source != null) {
raw._.pipe_state.alpha_blend_source = shader_context_get_blend_fac(raw.alpha_blend_source);
}
if (raw.alpha_blend_destination != null) {
raw._.pipe_state.alpha_blend_destination = shader_context_get_blend_fac(raw.alpha_blend_destination);
}
// Per-target color write mask
if (raw.color_writes_red != null) {
for (let i: i32 = 0; i < raw.color_writes_red.length; ++i) {
ARRAY_ACCESS(raw._.pipe_state.color_write_mask_red, i) = raw.color_writes_red[i];
}
}
if (raw.color_writes_green != null) {
for (let i: i32 = 0; i < raw.color_writes_green.length; ++i) {
ARRAY_ACCESS(raw._.pipe_state.color_write_mask_green, i) = raw.color_writes_green[i];
}
}
if (raw.color_writes_blue != null) {
for (let i: i32 = 0; i < raw.color_writes_blue.length; ++i) {
ARRAY_ACCESS(raw._.pipe_state.color_write_mask_blue, i) = raw.color_writes_blue[i];
}
}
if (raw.color_writes_alpha != null) {
for (let i: i32 = 0; i < raw.color_writes_alpha.length; ++i) {
ARRAY_ACCESS(raw._.pipe_state.color_write_mask_alpha, i) = raw.color_writes_alpha[i];
}
}
// Color attachment format
if (raw.color_attachments != null) {
raw._.pipe_state.color_attachment_count = raw.color_attachments.length;
for (let i: i32 = 0; i < raw.color_attachments.length; ++i) {
ARRAY_ACCESS(raw._.pipe_state.color_attachment, i) = shader_context_get_tex_format(raw.color_attachments[i]);
}
}
// Depth attachment format
if (raw.depth_attachment != null) {
raw._.pipe_state.depth_attachment_bits = raw.depth_attachment == "NONE" ? 0 : 24;
}
// Shaders
if (raw.shader_from_source) {
raw._.pipe_state.vertex_shader = gpu_create_shader_from_source(raw.vertex_shader, shader_type_t.VERTEX);
raw._.pipe_state.fragment_shader = gpu_create_shader_from_source(raw.fragment_shader, shader_type_t.FRAGMENT);
// Shader compile error
if (raw._.pipe_state.vertex_shader == null || raw._.pipe_state.fragment_shader == null) {
return null;
}
}
else {
///if arm_embed
raw._.pipe_state.fragment_shader = sys_get_shader(raw.fragment_shader);
raw._.pipe_state.vertex_shader = sys_get_shader(raw.vertex_shader);
///else // Load shaders manually
let vs_buffer: buffer_t = data_get_blob(raw.vertex_shader + shader_data_ext());
raw._.pipe_state.vertex_shader = gpu_create_shader(vs_buffer, shader_type_t.VERTEX);
let fs_buffer: buffer_t = data_get_blob(raw.fragment_shader + shader_data_ext());
raw._.pipe_state.fragment_shader = gpu_create_shader(fs_buffer, shader_type_t.FRAGMENT);
///end
}
return shader_context_finish_compile(raw);
}
function shader_context_type_size(t: string): i32 {
if (t == "int") return 4;
if (t == "float") return 4;
if (t == "vec2") return 8;
if (t == "vec3") return 12;
if (t == "vec4") return 16;
if (t == "mat3") return 48;
if (t == "mat4") return 64;
}
function shader_context_type_pad(offset: i32, size: i32): i32 {
let r: i32 = offset % 16;
if (r == 0) {
return 0;
}
if (size >= 16 || r + size > 16) {
return 16 - r;
}
return 0;
}
function shader_context_finish_compile(raw: shader_context_t): shader_context_t {
gpu_compile_pipeline(raw._.pipe_state);
if (raw.constants != null) {
let offset: i32 = 0;
for (let i: i32 = 0; i < raw.constants.length; ++i) {
let c: shader_const_t = raw.constants[i];
let size: i32 = shader_context_type_size(c.type);
offset += shader_context_type_pad(offset, size);
shader_context_add_const(raw, c, offset);
offset += size;
}
}
if (raw.texture_units != null) {
for (let i: i32 = 0; i < raw.texture_units.length; ++i) {
let tu: tex_unit_t = raw.texture_units[i];
shader_context_add_tex(raw, tu, i);
}
}
return raw;
}
function shader_context_parse_data(data: string): vertex_data_t {
if (data == "float1") {
return vertex_data_t.F32_1X;
}
else if (data == "float2") {
return vertex_data_t.F32_2X;
}
else if (data == "float3") {
return vertex_data_t.F32_3X;
}
else if (data == "float4") {
return vertex_data_t.F32_4X;
}
else if (data == "short2norm") {
return vertex_data_t.I16_2X_NORM;
}
else if (data == "short4norm") {
return vertex_data_t.I16_4X_NORM;
}
return vertex_data_t.F32_1X;
}
function shader_context_parse_vertex_struct(raw: shader_context_t) {
raw._.structure = gpu_vertex_struct_create();
for (let i: i32 = 0; i < raw.vertex_elements.length; ++i) {
let elem: vertex_element_t = raw.vertex_elements[i];
gpu_vertex_struct_add(raw._.structure, elem.name, shader_context_parse_data(elem.data));
}
}
function shader_context_delete(raw: shader_context_t) {
if (raw._.pipe_state.fragment_shader != null) {
iron_gpu_shader_destroy(raw._.pipe_state.fragment_shader);
}
if (raw._.pipe_state.vertex_shader != null) {
iron_gpu_shader_destroy(raw._.pipe_state.vertex_shader);
}
gpu_delete_pipeline(raw._.pipe_state);
}
function shader_context_get_compare_mode(s: string): compare_mode_t {
if (s == "always") {
return compare_mode_t.ALWAYS;
}
if (s == "never") {
return compare_mode_t.NEVER;
}
if (s == "less") {
return compare_mode_t.LESS;
}
if (s == "less_equal") {
return compare_mode_t.LESS_EQUAL;
}
if (s == "greater") {
return compare_mode_t.GREATER;
}
if (s == "greater_equal") {
return compare_mode_t.GREATER_EQUAL;
}
if (s == "equal") {
return compare_mode_t.EQUAL;
}
if (s == "not_equal") {
return compare_mode_t.NOT_EQUAL;
}
return compare_mode_t.LESS;
}
function shader_context_get_cull_mode(s: string): cull_mode_t {
if (s == "none") {
return cull_mode_t.NONE;
}
if (s == "clockwise") {
return cull_mode_t.CLOCKWISE;
}
return cull_mode_t.COUNTER_CLOCKWISE;
}
function shader_context_get_blend_fac(s: string): blend_factor_t {
if (s == "blend_one") {
return blend_factor_t.BLEND_ONE;
}
if (s == "blend_zero") {
return blend_factor_t.BLEND_ZERO;
}
if (s == "source_alpha") {
return blend_factor_t.SOURCE_ALPHA;
}
if (s == "destination_alpha") {
return blend_factor_t.DEST_ALPHA;
}
if (s == "inverse_source_alpha") {
return blend_factor_t.INV_SOURCE_ALPHA;
}
if (s == "inverse_destination_alpha") {
return blend_factor_t.INV_DEST_ALPHA;
}
if (s == "source_color") {
return blend_factor_t.SOURCE_COLOR;
}
if (s == "destination_color") {
return blend_factor_t.DEST_COLOR;
}
if (s == "inverse_source_color") {
return blend_factor_t.INV_SOURCE_COLOR;
}
if (s == "inverse_destination_color") {
return blend_factor_t.INV_DEST_COLOR;
}
return blend_factor_t.BLEND_ONE;
}
function shader_context_get_tex_addresing(s: string): tex_addressing_t {
if (s == "repeat") {
return tex_addressing_t.REPEAT;
}
if (s == "mirror") {
return tex_addressing_t.MIRROR;
}
return tex_addressing_t.CLAMP;
}
function shader_context_get_tex_filter(s: string): tex_filter_t {
if (s == "point") {
return tex_filter_t.POINT;
}
if (s == "linear") {
return tex_filter_t.LINEAR;
}
return tex_filter_t.ANISOTROPIC;
}
function shader_context_get_mipmap_filter(s: string): mip_map_filter_t {
if (s == "no") {
return mip_map_filter_t.NONE;
}
if (s == "point") {
return mip_map_filter_t.POINT;
}
return mip_map_filter_t.LINEAR;
}
function shader_context_get_tex_format(s: string): tex_format_t {
if (s == "RGBA32") {
return tex_format_t.RGBA32;
}
if (s == "RGBA64") {
return tex_format_t.RGBA64;
}
if (s == "RGBA128") {
return tex_format_t.RGBA128;
}
if (s == "R32") {
return tex_format_t.R32;
}
if (s == "R16") {
return tex_format_t.R16;
}
if (s == "R8") {
return tex_format_t.R8;
}
return tex_format_t.RGBA32;
}
function shader_context_add_const(raw: shader_context_t, c: shader_const_t, offset: i32) {
let cl: iron_gpu_constant_location_t = gpu_get_constant_location(raw._.pipe_state, c.name);
let ptr: gpu_constant_location_impl_t = ADDRESS(cl.impl);
ptr.vertexOffset = offset;
ptr.fragmentOffset = offset;
array_push(raw._.constants, cl);
}
function shader_context_add_tex(raw: shader_context_t, tu: tex_unit_t, i: i32) {
let unit: iron_gpu_texture_unit_t = gpu_get_texture_unit(raw._.pipe_state, tu.name);
ARRAY_ACCESS(unit.stages, IRON_GPU_SHADER_TYPE_FRAGMENT) = i;
array_push(raw._.tex_units, unit);
}
function shader_context_set_tex_params(raw: shader_context_t, unit_index: i32, tex: bind_tex_t) {
// This function is called for samplers set using material context
let unit: any = raw._.tex_units[unit_index];
gpu_set_texture_parameters(unit,
tex.u_addressing == null ? tex_addressing_t.REPEAT : shader_context_get_tex_addresing(tex.u_addressing),
tex.v_addressing == null ? tex_addressing_t.REPEAT : shader_context_get_tex_addresing(tex.v_addressing),
tex.min_filter == null ? tex_filter_t.LINEAR : shader_context_get_tex_filter(tex.min_filter),
tex.mag_filter == null ? tex_filter_t.LINEAR : shader_context_get_tex_filter(tex.mag_filter),
tex.mipmap_filter == null ? mip_map_filter_t.NONE : shader_context_get_mipmap_filter(tex.mipmap_filter));
}