Files
armorpaint/base/sources/libs/kong/analyzer.c
T

937 lines
27 KiB
C

#include "analyzer.h"
#include "array.h"
#include "errors.h"
#include <string.h>
static render_pipelines all_render_pipelines;
// a pipeline group is a collection of pipelines that share shaders
static render_pipeline_groups all_render_pipeline_groups;
static compute_shaders all_compute_shaders;
static raytracing_pipelines all_raytracing_pipelines;
// a pipeline group is a collection of pipelines that share shaders
static raytracing_pipeline_groups all_raytracing_pipeline_groups;
static void find_referenced_global_for_var(variable v, global_array *globals, bool read, bool write) {
for (global_id j = 0; get_global(j) != NULL && get_global(j)->type != NO_TYPE; ++j) {
global *g = get_global(j);
if (v.index == g->var_index) {
bool found = false;
for (size_t k = 0; k < globals->size; ++k) {
if (globals->globals[k] == j) {
found = true;
if (read) {
globals->readable[k] = true;
}
if (write) {
globals->writable[k] = true;
}
break;
}
}
if (!found) {
globals->globals[globals->size] = j;
globals->readable[globals->size] = read;
globals->writable[globals->size] = write;
globals->size += 1;
}
return;
}
}
}
void find_referenced_globals(function *f, global_array *globals) {
if (f->block == NULL) {
// built-in
return;
}
function *functions[256];
size_t functions_size = 0;
functions[functions_size] = f;
functions_size += 1;
find_referenced_functions(f, functions, &functions_size);
for (size_t l = 0; l < functions_size; ++l) {
uint8_t *data = functions[l]->code.o;
size_t size = functions[l]->code.size;
size_t index = 0;
while (index < size) {
opcode *o = (opcode *)&data[index];
switch (o->type) {
case OPCODE_MULTIPLY:
case OPCODE_DIVIDE:
case OPCODE_ADD:
case OPCODE_SUB:
case OPCODE_EQUALS:
case OPCODE_NOT_EQUALS:
case OPCODE_GREATER:
case OPCODE_GREATER_EQUAL:
case OPCODE_LESS:
case OPCODE_LESS_EQUAL: {
find_referenced_global_for_var(o->op_binary.left, globals, false, false);
find_referenced_global_for_var(o->op_binary.right, globals, false, false);
break;
}
case OPCODE_LOAD_ACCESS_LIST: {
find_referenced_global_for_var(o->op_load_access_list.from, globals, true, false);
break;
}
case OPCODE_STORE_ACCESS_LIST:
case OPCODE_SUB_AND_STORE_ACCESS_LIST:
case OPCODE_ADD_AND_STORE_ACCESS_LIST:
case OPCODE_DIVIDE_AND_STORE_ACCESS_LIST:
case OPCODE_MULTIPLY_AND_STORE_ACCESS_LIST: {
find_referenced_global_for_var(o->op_store_access_list.to, globals, false, true);
break;
}
case OPCODE_CALL: {
for (uint8_t i = 0; i < o->op_call.parameters_size; ++i) {
find_referenced_global_for_var(o->op_call.parameters[i], globals, false, false);
}
break;
}
default:
break;
}
index += o->size;
}
}
}
void find_referenced_functions(function *f, function **functions, size_t *functions_size) {
if (f->block == NULL) {
// built-in
return;
}
uint8_t *data = f->code.o;
size_t size = f->code.size;
size_t index = 0;
while (index < size) {
opcode *o = (opcode *)&data[index];
switch (o->type) {
case OPCODE_CALL: {
for (function_id i = 0; get_function(i) != NULL; ++i) {
function *f = get_function(i);
if (f->name == o->op_call.func) {
if (f->block == NULL) {
// built-in
break;
}
bool found = false;
for (size_t j = 0; j < *functions_size; ++j) {
if (functions[j]->name == o->op_call.func) {
found = true;
break;
}
}
if (!found) {
functions[*functions_size] = f;
*functions_size += 1;
find_referenced_functions(f, functions, functions_size);
}
break;
}
}
break;
}
default:
break;
}
index += o->size;
}
}
void find_used_builtins(function *f) {
if (f->block == NULL) {
// built-in
return;
}
if (f->used_builtins.builtins_analyzed) {
return;
}
f->used_builtins.builtins_analyzed = true;
uint8_t *data = f->code.o;
size_t size = f->code.size;
size_t index = 0;
while (index < size) {
opcode *o = (opcode *)&data[index];
switch (o->type) {
case OPCODE_CALL: {
name_id func = o->op_call.func;
if (func == add_name("dispatch_thread_id")) {
f->used_builtins.dispatch_thread_id = true;
}
if (func == add_name("group_thread_id")) {
f->used_builtins.group_thread_id = true;
}
if (func == add_name("group_id")) {
f->used_builtins.group_id = true;
}
if (func == add_name("vertex_id")) {
f->used_builtins.vertex_id = true;
}
for (function_id i = 0; get_function(i) != NULL; ++i) {
function *called = get_function(i);
if (called->name == o->op_call.func) {
find_used_builtins(f);
f->used_builtins.dispatch_thread_id |= called->used_builtins.dispatch_thread_id;
f->used_builtins.group_thread_id |= called->used_builtins.group_thread_id;
f->used_builtins.group_id |= called->used_builtins.group_id;
f->used_builtins.vertex_id |= called->used_builtins.vertex_id;
break;
}
}
break;
}
default:
break;
}
index += o->size;
}
}
static global *find_global_by_var(variable var) {
for (global_id global_index = 0; get_global(global_index) != NULL && get_global(global_index)->type != NO_TYPE; ++global_index) {
if (var.index == get_global(global_index)->var_index) {
return get_global(global_index);
}
}
return NULL;
}
void find_used_capabilities(function *f) {
if (f->block == NULL) {
// built-in
return;
}
if (f->used_capabilities.capabilities_analyzed) {
return;
}
f->used_capabilities.capabilities_analyzed = true;
uint8_t *data = f->code.o;
size_t size = f->code.size;
size_t index = 0;
variable last_base_texture_from = {0};
variable last_base_texture_to = {0};
while (index < size) {
opcode *o = (opcode *)&data[index];
switch (o->type) {
case OPCODE_STORE_ACCESS_LIST: {
variable to = o->op_store_access_list.to;
type_id to_type = to.type.type;
if (is_texture(to_type)) {
assert(get_type(to_type)->array_size == 0);
f->used_capabilities.image_write = true;
global *g = find_global_by_var(to);
assert(g != NULL);
g->usage |= GLOBAL_USAGE_TEXTURE_WRITE;
}
break;
}
case OPCODE_LOAD_ACCESS_LIST: {
variable from = o->op_load_access_list.from;
type_id from_type = from.type.type;
if (is_texture(from_type)) {
f->used_capabilities.image_read = true;
if (get_type(from_type)->array_size > 0) {
last_base_texture_from = from;
last_base_texture_to = o->op_load_access_list.to;
}
else {
global *g = find_global_by_var(from);
assert(g != NULL);
g->usage |= GLOBAL_USAGE_TEXTURE_READ;
}
}
break;
}
case OPCODE_CALL: {
name_id func_name = o->op_call.func;
if (func_name == add_name("sample") || func_name == add_name("sample_lod")) {
variable tex_parameter = o->op_call.parameters[0];
global *g = NULL;
if (tex_parameter.kind == VARIABLE_INTERNAL) {
assert(last_base_texture_to.index == tex_parameter.index);
g = find_global_by_var(last_base_texture_from);
}
else {
g = find_global_by_var(tex_parameter);
}
assert(g != NULL);
g->usage |= GLOBAL_USAGE_TEXTURE_SAMPLE;
}
for (function_id i = 0; get_function(i) != NULL; ++i) {
function *called = get_function(i);
if (called->name == func_name) {
find_used_capabilities(f);
f->used_capabilities.image_read |= called->used_capabilities.image_read;
f->used_capabilities.image_write |= called->used_capabilities.image_write;
break;
}
}
break;
}
default:
break;
}
index += o->size;
}
}
static void add_found_type(type_id t, type_id *types, size_t *types_size) {
for (size_t i = 0; i < *types_size; ++i) {
if (types[i] == t) {
return;
}
}
types[*types_size] = t;
*types_size += 1;
}
void find_referenced_types(function *f, type_id *types, size_t *types_size) {
if (f->block == NULL) {
// built-in
return;
}
function *functions[256];
size_t functions_size = 0;
functions[functions_size] = f;
functions_size += 1;
find_referenced_functions(f, functions, &functions_size);
for (size_t function_index = 0; function_index < functions_size; ++function_index) {
function *func = functions[function_index];
debug_context context = {0};
for (uint8_t parameter_index = 0; parameter_index < func->parameters_size; ++parameter_index) {
check(func->parameter_types[parameter_index].type != NO_TYPE, context, "Function parameter type not found");
add_found_type(func->parameter_types[parameter_index].type, types, types_size);
}
check(func->return_type.type != NO_TYPE, context, "Function return type missing");
add_found_type(func->return_type.type, types, types_size);
uint8_t *data = functions[function_index]->code.o;
size_t size = functions[function_index]->code.size;
size_t index = 0;
while (index < size) {
opcode *o = (opcode *)&data[index];
switch (o->type) {
case OPCODE_VAR:
add_found_type(o->op_var.var.type.type, types, types_size);
break;
default:
break;
}
index += o->size;
}
}
}
static bool has_set(descriptor_sets *sets, descriptor_set *set) {
for (size_t set_index = 0; set_index < sets->size; ++set_index) {
if (sets->values[set_index] == set) {
return true;
}
}
return false;
}
static void add_set(descriptor_sets *sets, descriptor_set *set) {
if (has_set(sets, set)) {
return;
}
static_array_push_p(sets, set);
}
static void find_referenced_sets(global_array *globals, descriptor_sets *sets) {
for (size_t global_index = 0; global_index < globals->size; ++global_index) {
global *g = get_global(globals->globals[global_index]);
if (g->sets_count == 0) {
continue;
}
if (g->sets_count == 1) {
add_set(sets, g->sets[0]);
continue;
}
}
for (size_t global_index = 0; global_index < globals->size; ++global_index) {
global *g = get_global(globals->globals[global_index]);
if (g->sets_count < 2) {
continue;
}
bool found = false;
for (size_t set_index = 0; set_index < g->sets_count; ++set_index) {
descriptor_set *set = g->sets[set_index];
if (has_set(sets, set)) {
found = true;
break;
}
}
if (!found) {
debug_context context = {0};
error(context, "Global %s could be used from multiple descriptor sets.", get_name(g->name));
}
}
}
static render_pipeline extract_render_pipeline_from_type(type *t) {
name_id vertex_shader_name = NO_NAME;
name_id amplification_shader_name = NO_NAME;
name_id mesh_shader_name = NO_NAME;
name_id fragment_shader_name = NO_NAME;
for (size_t j = 0; j < t->members.size; ++j) {
if (t->members.m[j].name == add_name("vertex")) {
vertex_shader_name = t->members.m[j].value.identifier;
}
else if (t->members.m[j].name == add_name("amplification")) {
amplification_shader_name = t->members.m[j].value.identifier;
}
else if (t->members.m[j].name == add_name("mesh")) {
mesh_shader_name = t->members.m[j].value.identifier;
}
else if (t->members.m[j].name == add_name("fragment")) {
fragment_shader_name = t->members.m[j].value.identifier;
}
}
debug_context context = {0};
check(vertex_shader_name != NO_NAME || mesh_shader_name != NO_NAME, context, "vertex or mesh shader missing");
check(fragment_shader_name != NO_NAME, context, "fragment shader missing");
render_pipeline pipeline = {0};
for (function_id i = 0; get_function(i) != NULL; ++i) {
function *f = get_function(i);
if (vertex_shader_name != NO_NAME && f->name == vertex_shader_name) {
pipeline.vertex_shader = f;
}
if (amplification_shader_name != NO_NAME && f->name == amplification_shader_name) {
pipeline.amplification_shader = f;
}
if (mesh_shader_name != NO_NAME && f->name == mesh_shader_name) {
pipeline.mesh_shader = f;
}
if (f->name == fragment_shader_name) {
pipeline.fragment_shader = f;
}
}
return pipeline;
}
static void find_all_render_pipelines(void) {
static_array_init(all_render_pipelines);
for (type_id i = 0; get_type(i) != NULL; ++i) {
type *t = get_type(i);
if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) {
static_array_push(all_render_pipelines, extract_render_pipeline_from_type(t));
}
}
}
static bool same_shader(function *a, function *b) {
if (a == NULL && b == NULL) {
return false;
}
return a == b;
}
static void find_render_pipeline_groups(void) {
static_array_init(all_render_pipeline_groups);
render_pipeline_indices remaining_pipelines;
static_array_init(remaining_pipelines);
for (uint32_t index = 0; index < all_render_pipelines.size; ++index) {
static_array_push(remaining_pipelines, index);
}
while (remaining_pipelines.size > 0) {
render_pipeline_indices next_remaining_pipelines;
static_array_init(next_remaining_pipelines);
render_pipeline_group group;
static_array_init(group);
static_array_push(group, remaining_pipelines.values[0]);
for (size_t index = 1; index < remaining_pipelines.size; ++index) {
uint32_t pipeline_index = remaining_pipelines.values[index];
render_pipeline *pipeline = &all_render_pipelines.values[pipeline_index];
bool found = false;
for (size_t index_in_bucket = 0; index_in_bucket < group.size; ++index_in_bucket) {
render_pipeline *pipeline_in_group = &all_render_pipelines.values[group.values[index_in_bucket]];
if (same_shader(pipeline->vertex_shader, pipeline_in_group->vertex_shader) ||
same_shader(pipeline->amplification_shader, pipeline_in_group->amplification_shader) ||
same_shader(pipeline->mesh_shader, pipeline_in_group->mesh_shader) ||
same_shader(pipeline->fragment_shader, pipeline_in_group->fragment_shader)) {
found = true;
break;
}
}
if (found) {
static_array_push(group, pipeline_index);
}
else {
static_array_push(next_remaining_pipelines, pipeline_index);
}
}
remaining_pipelines = next_remaining_pipelines;
static_array_push(all_render_pipeline_groups, group);
}
}
static void find_all_compute_shaders(void) {
static_array_init(all_compute_shaders);
for (function_id i = 0; get_function(i) != NULL; ++i) {
function *f = get_function(i);
if (has_attribute(&f->attributes, add_name("compute"))) {
static_array_push(all_compute_shaders, f);
}
}
}
static raytracing_pipeline extract_raytracing_pipeline_from_type(type *t) {
name_id gen_shader_name = NO_NAME;
name_id miss_shader_name = NO_NAME;
name_id closest_shader_name = NO_NAME;
name_id intersection_shader_name = NO_NAME;
name_id any_shader_name = NO_NAME;
for (size_t j = 0; j < t->members.size; ++j) {
if (t->members.m[j].name == add_name("gen")) {
gen_shader_name = t->members.m[j].value.identifier;
}
else if (t->members.m[j].name == add_name("miss")) {
miss_shader_name = t->members.m[j].value.identifier;
}
else if (t->members.m[j].name == add_name("closest")) {
closest_shader_name = t->members.m[j].value.identifier;
}
else if (t->members.m[j].name == add_name("intersection")) {
intersection_shader_name = t->members.m[j].value.identifier;
}
else if (t->members.m[j].name == add_name("any")) {
any_shader_name = t->members.m[j].value.identifier;
}
}
raytracing_pipeline pipeline = {0};
for (function_id i = 0; get_function(i) != NULL; ++i) {
function *f = get_function(i);
if (gen_shader_name != NO_NAME && f->name == gen_shader_name) {
pipeline.gen_shader = f;
}
if (miss_shader_name != NO_NAME && f->name == miss_shader_name) {
pipeline.miss_shader = f;
}
if (closest_shader_name != NO_NAME && f->name == closest_shader_name) {
pipeline.closest_shader = f;
}
if (intersection_shader_name != NO_NAME && f->name == intersection_shader_name) {
pipeline.intersection_shader = f;
}
if (any_shader_name != NO_NAME && f->name == any_shader_name) {
pipeline.any_shader = f;
}
}
return pipeline;
}
static void find_all_raytracing_pipelines(void) {
static_array_init(all_raytracing_pipelines);
for (type_id i = 0; get_type(i) != NULL; ++i) {
type *t = get_type(i);
if (!t->built_in && has_attribute(&t->attributes, add_name("raypipe"))) {
static_array_push(all_raytracing_pipelines, extract_raytracing_pipeline_from_type(t));
}
}
}
static void find_raytracing_pipeline_groups(void) {
static_array_init(all_raytracing_pipeline_groups);
raytracing_pipeline_indices remaining_pipelines;
static_array_init(remaining_pipelines);
for (uint32_t index = 0; index < all_raytracing_pipelines.size; ++index) {
static_array_push(remaining_pipelines, index);
}
while (remaining_pipelines.size > 0) {
raytracing_pipeline_indices next_remaining_pipelines;
static_array_init(next_remaining_pipelines);
raytracing_pipeline_group group;
static_array_init(group);
static_array_push(group, remaining_pipelines.values[0]);
for (size_t index = 1; index < remaining_pipelines.size; ++index) {
uint32_t pipeline_index = remaining_pipelines.values[index];
raytracing_pipeline *pipeline = &all_raytracing_pipelines.values[pipeline_index];
bool found = false;
for (size_t index_in_bucket = 0; index_in_bucket < group.size; ++index_in_bucket) {
raytracing_pipeline *pipeline_in_group = &all_raytracing_pipelines.values[group.values[index_in_bucket]];
if (pipeline->gen_shader == pipeline_in_group->gen_shader || pipeline->miss_shader == pipeline_in_group->miss_shader ||
pipeline->closest_shader == pipeline_in_group->closest_shader || pipeline->intersection_shader == pipeline_in_group->intersection_shader ||
pipeline->any_shader == pipeline_in_group->any_shader) {
found = true;
break;
}
}
if (found) {
static_array_push(group, pipeline_index);
}
else {
static_array_push(next_remaining_pipelines, pipeline_index);
}
}
remaining_pipelines = next_remaining_pipelines;
static_array_push(all_raytracing_pipeline_groups, group);
}
}
static void check_globals_in_descriptor_set_group(descriptor_set_group *group) {
static_array(global_id, globals, 256);
globals set_globals;
static_array_init(set_globals);
for (size_t set_index = 0; set_index < group->size; ++set_index) {
descriptor_set *set = group->values[set_index];
for (size_t global_index = 0; global_index < set->globals.size; ++global_index) {
global_id g = set->globals.globals[global_index];
for (size_t global_index2 = 0; global_index2 < set_globals.size; ++global_index2) {
if (set_globals.values[global_index2] == g) {
debug_context context = {0};
error(context, "Global used from more than one descriptor set in one descriptor set group");
}
}
static_array_push(set_globals, g);
}
}
}
static void update_globals_in_descriptor_set_group(descriptor_set_group *group, global_array *globals) {
for (size_t set_index = 0; set_index < group->size; ++set_index) {
descriptor_set *set = group->values[set_index];
for (size_t global_index = 0; global_index < set->globals.size; ++global_index) {
global_id g = set->globals.globals[global_index];
for (size_t global_index2 = 0; global_index2 < globals->size; ++global_index2) {
if (globals->globals[global_index2] == g) {
if (globals->readable[global_index2]) {
set->globals.readable[global_index] = true;
}
if (globals->writable[global_index2]) {
set->globals.writable[global_index] = true;
}
}
}
}
}
}
static descriptor_set_groups all_descriptor_set_groups;
descriptor_set_group *get_descriptor_set_group(uint32_t descriptor_set_group_index) {
assert(descriptor_set_group_index < all_descriptor_set_groups.size);
return &all_descriptor_set_groups.values[descriptor_set_group_index];
}
static void assign_descriptor_set_group_index(function *f, uint32_t descriptor_set_group_index) {
assert(f->descriptor_set_group_index == UINT32_MAX || f->descriptor_set_group_index == descriptor_set_group_index);
f->descriptor_set_group_index = descriptor_set_group_index;
}
static void find_descriptor_set_groups(void) {
static_array_init(all_descriptor_set_groups);
for (size_t pipeline_group_index = 0; pipeline_group_index < all_render_pipeline_groups.size; ++pipeline_group_index) {
descriptor_set_group group;
static_array_init(group);
global_array function_globals = {0};
render_pipeline_group *pipeline_group = &all_render_pipeline_groups.values[pipeline_group_index];
for (size_t pipeline_index = 0; pipeline_index < pipeline_group->size; ++pipeline_index) {
render_pipeline *pipeline = &all_render_pipelines.values[pipeline_group->values[pipeline_index]];
if (pipeline->vertex_shader != NULL) {
find_referenced_globals(pipeline->vertex_shader, &function_globals);
}
if (pipeline->amplification_shader != NULL) {
find_referenced_globals(pipeline->amplification_shader, &function_globals);
}
if (pipeline->mesh_shader != NULL) {
find_referenced_globals(pipeline->mesh_shader, &function_globals);
}
if (pipeline->fragment_shader != NULL) {
find_referenced_globals(pipeline->fragment_shader, &function_globals);
}
}
find_referenced_sets(&function_globals, &group);
check_globals_in_descriptor_set_group(&group);
update_globals_in_descriptor_set_group(&group, &function_globals);
uint32_t descriptor_set_group_index = (uint32_t)all_descriptor_set_groups.size;
static_array_push(all_descriptor_set_groups, group);
for (size_t pipeline_index = 0; pipeline_index < pipeline_group->size; ++pipeline_index) {
render_pipeline *pipeline = &all_render_pipelines.values[pipeline_group->values[pipeline_index]];
if (pipeline->vertex_shader != NULL) {
assign_descriptor_set_group_index(pipeline->vertex_shader, descriptor_set_group_index);
}
if (pipeline->amplification_shader != NULL) {
assign_descriptor_set_group_index(pipeline->amplification_shader, descriptor_set_group_index);
}
if (pipeline->mesh_shader != NULL) {
assign_descriptor_set_group_index(pipeline->mesh_shader, descriptor_set_group_index);
}
if (pipeline->fragment_shader != NULL) {
assign_descriptor_set_group_index(pipeline->fragment_shader, descriptor_set_group_index);
}
}
}
for (size_t compute_shader_index = 0; compute_shader_index < all_compute_shaders.size; ++compute_shader_index) {
descriptor_set_group group;
static_array_init(group);
global_array function_globals = {0};
find_referenced_globals(all_compute_shaders.values[compute_shader_index], &function_globals);
find_referenced_sets(&function_globals, &group);
check_globals_in_descriptor_set_group(&group);
update_globals_in_descriptor_set_group(&group, &function_globals);
uint32_t descriptor_set_group_index = (uint32_t)all_descriptor_set_groups.size;
static_array_push(all_descriptor_set_groups, group);
for (size_t compute_shader_index = 0; compute_shader_index < all_compute_shaders.size; ++compute_shader_index) {
assign_descriptor_set_group_index(all_compute_shaders.values[compute_shader_index], descriptor_set_group_index);
}
}
for (size_t pipeline_group_index = 0; pipeline_group_index < all_raytracing_pipeline_groups.size; ++pipeline_group_index) {
descriptor_set_group group;
static_array_init(group);
global_array function_globals = {0};
raytracing_pipeline_group *pipeline_group = &all_raytracing_pipeline_groups.values[pipeline_group_index];
for (size_t pipeline_index = 0; pipeline_index < pipeline_group->size; ++pipeline_index) {
raytracing_pipeline *pipeline = &all_raytracing_pipelines.values[pipeline_group->values[pipeline_index]];
if (pipeline->gen_shader != NULL) {
find_referenced_globals(pipeline->gen_shader, &function_globals);
}
if (pipeline->miss_shader != NULL) {
find_referenced_globals(pipeline->miss_shader, &function_globals);
}
if (pipeline->closest_shader != NULL) {
find_referenced_globals(pipeline->closest_shader, &function_globals);
}
if (pipeline->intersection_shader != NULL) {
find_referenced_globals(pipeline->intersection_shader, &function_globals);
}
if (pipeline->any_shader != NULL) {
find_referenced_globals(pipeline->any_shader, &function_globals);
}
}
find_referenced_sets(&function_globals, &group);
check_globals_in_descriptor_set_group(&group);
update_globals_in_descriptor_set_group(&group, &function_globals);
uint32_t descriptor_set_group_index = (uint32_t)all_descriptor_set_groups.size;
static_array_push(all_descriptor_set_groups, group);
for (size_t pipeline_index = 0; pipeline_index < pipeline_group->size; ++pipeline_index) {
raytracing_pipeline *pipeline = &all_raytracing_pipelines.values[pipeline_group->values[pipeline_index]];
if (pipeline->gen_shader != NULL) {
assign_descriptor_set_group_index(pipeline->gen_shader, descriptor_set_group_index);
}
if (pipeline->miss_shader != NULL) {
assign_descriptor_set_group_index(pipeline->miss_shader, descriptor_set_group_index);
}
if (pipeline->closest_shader != NULL) {
assign_descriptor_set_group_index(pipeline->closest_shader, descriptor_set_group_index);
}
if (pipeline->intersection_shader != NULL) {
assign_descriptor_set_group_index(pipeline->intersection_shader, descriptor_set_group_index);
}
if (pipeline->any_shader != NULL) {
assign_descriptor_set_group_index(pipeline->any_shader, descriptor_set_group_index);
}
}
}
}
descriptor_set_group *find_descriptor_set_group_for_pipe_type(type *t) {
if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) {
render_pipeline pipeline = extract_render_pipeline_from_type(t);
if (pipeline.vertex_shader->descriptor_set_group_index != UINT32_MAX) {
return &all_descriptor_set_groups.values[pipeline.vertex_shader->descriptor_set_group_index];
}
if (pipeline.amplification_shader->descriptor_set_group_index != UINT32_MAX) {
return &all_descriptor_set_groups.values[pipeline.amplification_shader->descriptor_set_group_index];
}
if (pipeline.mesh_shader->descriptor_set_group_index != UINT32_MAX) {
return &all_descriptor_set_groups.values[pipeline.mesh_shader->descriptor_set_group_index];
}
if (pipeline.fragment_shader->descriptor_set_group_index != UINT32_MAX) {
return &all_descriptor_set_groups.values[pipeline.fragment_shader->descriptor_set_group_index];
}
return NULL;
}
if (!t->built_in && has_attribute(&t->attributes, add_name("raypipe"))) {
raytracing_pipeline pipeline = extract_raytracing_pipeline_from_type(t);
if (pipeline.gen_shader->descriptor_set_group_index != UINT32_MAX) {
return &all_descriptor_set_groups.values[pipeline.gen_shader->descriptor_set_group_index];
}
if (pipeline.miss_shader->descriptor_set_group_index != UINT32_MAX) {
return &all_descriptor_set_groups.values[pipeline.miss_shader->descriptor_set_group_index];
}
if (pipeline.closest_shader->descriptor_set_group_index != UINT32_MAX) {
return &all_descriptor_set_groups.values[pipeline.closest_shader->descriptor_set_group_index];
}
if (pipeline.intersection_shader->descriptor_set_group_index != UINT32_MAX) {
return &all_descriptor_set_groups.values[pipeline.intersection_shader->descriptor_set_group_index];
}
if (pipeline.any_shader->descriptor_set_group_index != UINT32_MAX) {
return &all_descriptor_set_groups.values[pipeline.any_shader->descriptor_set_group_index];
}
return NULL;
}
return NULL;
}
descriptor_set_group *find_descriptor_set_group_for_function(function *f) {
if (f->descriptor_set_group_index != UINT32_MAX) {
return &all_descriptor_set_groups.values[f->descriptor_set_group_index];
}
else {
return NULL;
}
}
void analyze(void) {
find_all_render_pipelines();
find_render_pipeline_groups();
find_all_compute_shaders();
find_all_raytracing_pipelines();
find_raytracing_pipeline_groups();
find_descriptor_set_groups();
}