Fixed modifying mesh instances

Rather than use a uniform, the code was modified so that the vertex
buffer for the mesh instances was not recreated from scratch. Now each
mesh can be assigned a max number of instances. On each modififcation
the instance data and the number of instances can be passed to the mesh.
This commit is contained in:
FroggyGreen 2024-06-30 08:46:57 -05:00
parent 0c55429241
commit 31e37846b4
4 changed files with 53 additions and 100 deletions

View File

@ -84,6 +84,7 @@ typedef struct mesh
vulkan_buffer instance_buffer;
vulkan_buffer index_buffer;
u64 index_count;
u64 max_instances;
u64 instance_count;
} mesh;
@ -2167,7 +2168,7 @@ static VkDeviceSize get_vertex_input_byte_size(const vertex_input_type t, const
}
}
static u8 load_mesh_geometry(mesh* msh, const mesh_geometry* geometry, vertex_input_type geometry_type)
static u8 init_mesh(mesh* msh, const mesh_geometry* geometry, vertex_input_type geometry_type, u64 max_instances, vertex_input_type instance_type)
{
if (!geometry) return 0;
@ -2180,25 +2181,12 @@ static u8 load_mesh_geometry(mesh* msh, const mesh_geometry* geometry, vertex_in
if (!upload_vulkan_gpu_buffer(&msh->index_buffer, geometry->indices, indices_byte_size)) return 0;
msh->index_count = geometry->index_count;
return 1;
}
if (!max_instances) return 0;
static u8 load_mesh_instance_data(mesh* msh, const mesh_instance_data* instance_data, vertex_input_type instance_type)
{
if (!instance_data) return 0;
const VkDeviceSize byte_size = get_vertex_input_byte_size(instance_type, instance_data->instance_count);
const VkDeviceSize byte_size = get_vertex_input_byte_size(instance_type, max_instances);
if (!init_vulkan_vertex_buffer(&msh->instance_buffer, byte_size)) return 0;
if (!upload_vulkan_gpu_buffer(&msh->instance_buffer, instance_data->instances, byte_size)) return 0;
msh->instance_count = instance_data->instance_count;
return 1;
}
static u8 init_mesh(mesh* msh, const mesh_geometry* geometry, vertex_input_type geometry_type, const mesh_instance_data* instance_data, vertex_input_type instance_type)
{
if (!load_mesh_geometry(msh, geometry, geometry_type)) return 0;
if (!load_mesh_instance_data(msh, instance_data, instance_type)) return 0;
msh->max_instances = max_instances;
msh->instance_count = 0;
return 1;
}
@ -2684,7 +2672,7 @@ u8 change_mesh_pipeline_mode(const char* name, mesh_pipeline_mode mode)
}
}
u8 insert_mesh(const char* pipeline_name, const char* mesh_name, const mesh_geometry* geometry, const mesh_instance_data* instance_data)
u8 insert_mesh(const char* pipeline_name, const char* mesh_name, const mesh_geometry* geometry, const u64 max_instances)
{
mesh_pipeline* pipeline = hash_table_lookup(&context.mesh_pipelines, pipeline_name);
if (!pipeline)
@ -2694,7 +2682,7 @@ u8 insert_mesh(const char* pipeline_name, const char* mesh_name, const mesh_geom
}
mesh msh;
if (!init_mesh(&msh, geometry, pipeline->geometry_type, instance_data, pipeline->instance_type)) return 0;
if (!init_mesh(&msh, geometry, pipeline->geometry_type, max_instances, pipeline->instance_type)) return 0;
if (!hash_table_insert(&pipeline->meshes, mesh_name, &msh))
{
shutdown_mesh(&msh);
@ -2724,50 +2712,32 @@ u8 remove_mesh(const char* pipeline_name, const char* mesh_name)
return hash_table_remove(&pipeline->meshes, mesh_name, NULL);
}
u8 reload_mesh_geometry(const char* pipeline_name, const char* mesh_name, const mesh_geometry* geometry)
u8 load_mesh_instance_data(const char* pipeline_name, const char* mesh_name, const mesh_instance_data* instance_data)
{
mesh_pipeline* pipeline = hash_table_lookup(&context.mesh_pipelines, pipeline_name);
if (!pipeline)
{
trace_log(LOG_ERROR, "Failed to reload geometry for mesh '%s'; mesh pipeline '%s' lookup failed.", mesh_name, pipeline_name);
trace_log(LOG_ERROR, "Failed to load instance data for mesh '%s'; mesh pipeline '%s' lookup failed.", mesh_name, pipeline_name);
return 0;
}
mesh* msh = hash_table_lookup(&pipeline->meshes, mesh_name);
if (!msh)
{
trace_log(LOG_ERROR, "Failed to reload geometry for mesh '%s'; lookup failed.", mesh_name);
trace_log(LOG_ERROR, "Failed to load instance data geometry for mesh '%s'; lookup failed.", mesh_name);
return 0;
}
if (instance_data->instance_count > msh->max_instances)
{
trace_log(LOG_ERROR, "Failed to load instance data geometry for mesh '%s'; instance count '%d' would exceed the max allowed", mesh_name, instance_data->instance_count);
return 0;
}
shutdown_vulkan_buffer(&msh->index_buffer);
shutdown_vulkan_buffer(&msh->vertex_buffer);
if (!load_mesh_geometry(msh, geometry, pipeline->geometry_type)) return 0;
return 1;
}
u8 reload_mesh_instance_data(const char* pipeline_name, const char* mesh_name, const mesh_instance_data* instance_data)
{
mesh_pipeline* pipeline = hash_table_lookup(&context.mesh_pipelines, pipeline_name);
if (!pipeline)
{
trace_log(LOG_ERROR, "Failed to reload instance data for mesh '%s'; mesh pipeline '%s' lookup failed.", mesh_name, pipeline_name);
return 0;
}
mesh* msh = hash_table_lookup(&pipeline->meshes, mesh_name);
if (!msh)
{
trace_log(LOG_ERROR, "Failed to instance data geometry for mesh '%s'; lookup failed.", mesh_name);
return 0;
}
const VkDeviceSize byte_size = get_vertex_input_byte_size(pipeline->instance_type, instance_data->instance_count);
if (!upload_vulkan_gpu_buffer(&msh->instance_buffer, instance_data->instances, byte_size)) return 0;
msh->instance_count = instance_data->instance_count;
shutdown_vulkan_buffer(&msh->instance_buffer);
if (!load_mesh_instance_data(msh, instance_data, pipeline->instance_type)) return 0;
return 1;
}

View File

@ -133,10 +133,9 @@ u8 draw_mesh_pipeline(const char* name);
u8 insert_mesh_pipeline(const char* name, vertex_input_type geometry_type, vertex_input_type instance_type, const char* texture_name);
u8 remove_mesh_pipeline(const char* name);
u8 change_mesh_pipeline_mode(const char* name, mesh_pipeline_mode mode);
u8 insert_mesh(const char* pipeline_name, const char* mesh_name, const mesh_geometry* geometry, const mesh_instance_data* instance_data);
u8 insert_mesh(const char* pipeline_name, const char* mesh_name, const mesh_geometry* geometry, const u64 max_instances);
u8 remove_mesh(const char* pipeline_name, const char* mesh_name);
u8 reload_mesh_geometry(const char* pipeline_name, const char* mesh_name, const mesh_geometry* geometry);
u8 reload_mesh_instance_data(const char* pipeline_name, const char* mesh_name, const mesh_instance_data* instance_data);
u8 load_mesh_instance_data(const char* pipeline_name, const char* mesh_name, const mesh_instance_data* instance_data);
u8 init_vulkan();
void shutdown_vulkan();

View File

@ -242,16 +242,13 @@
(%change-mesh-pipeline-mode name (mesh-pipeline-mode mode))))
(define insert-mesh
(foreign-procedure "insert_mesh" (string string (* mesh-geometry) (* mesh-instance-data)) boolean))
(foreign-procedure "insert_mesh" (string string (* mesh-geometry) unsigned-64) boolean))
(define remove-mesh
(foreign-procedure "remove_mesh" (string string) boolean))
(define reload-mesh-geometry
(foreign-procedure "reload_mesh_geometry" (string string (* mesh-geometry)) boolean))
(define reload-mesh-instance-data
(foreign-procedure "reload_mesh_instance_data" (string string (* mesh-instance-data)) boolean))
(define load-mesh-instance-data
(foreign-procedure "load_mesh_instance_data" (string string (* mesh-instance-data)) boolean))
(define %init-vulkan
(foreign-procedure "init_vulkan" () boolean))

View File

@ -86,6 +86,28 @@
(define grid-selector-shift-x #f)
(define grid-selector-shift-y #f)
(define load-grid-selector-position
(lambda (position)
(let ([sel-instances (make-ftype-pointer pos3-pos3-color4 (foreign-alloc (ftype-sizeof pos3-pos3-color4)))]
[instance-data (make-ftype-pointer mesh-instance-data (foreign-alloc (ftype-sizeof mesh-instance-data)))])
(fvec3-copy-c!
(ftype-&ref pos3-pos3-color4 (posa) sel-instances 0)
position)
(fvec3-copy-c!
(ftype-&ref pos3-pos3-color4 (posb) sel-instances 0)
(fvec 1 1 1))
(fvec3-copy-c!
(ftype-&ref pos3-pos3-color4 (color) sel-instances 0)
(fvec 1 1 1 1))
(ftype-set! mesh-instance-data (instances) instance-data (ftype-pointer-address sel-instances))
(ftype-set! mesh-instance-data (instance-count) instance-data 1)
(load-mesh-instance-data "grid-selector" "quad" instance-data)
(foreign-free (ftype-pointer-address sel-instances))
(foreign-free (ftype-pointer-address instance-data)))))
(define init-grid-selector
(lambda ()
@ -98,9 +120,7 @@
(let ([sel-vertices (make-ftype-pointer pos2 (foreign-alloc (* 4 (ftype-sizeof pos2))))]
[sel-indices (make-ftype-pointer unsigned-32 (foreign-alloc (* 6 (ftype-sizeof unsigned-32))))]
[geometry (make-ftype-pointer mesh-geometry (foreign-alloc (ftype-sizeof mesh-geometry)))]
[sel-instances (make-ftype-pointer pos3-pos3-color4 (foreign-alloc (ftype-sizeof pos3-pos3-color4)))]
[instance-data (make-ftype-pointer mesh-instance-data (foreign-alloc (ftype-sizeof mesh-instance-data)))])
[geometry (make-ftype-pointer mesh-geometry (foreign-alloc (ftype-sizeof mesh-geometry)))])
(fvec2-copy-c!
(ftype-&ref pos2 (pos) sel-vertices 0)
@ -127,25 +147,12 @@
(ftype-set! mesh-geometry (indices) geometry (ftype-pointer-address sel-indices))
(ftype-set! mesh-geometry (index-count) geometry 6)
(fvec3-copy-c!
(ftype-&ref pos3-pos3-color4 (posa) sel-instances 0)
(fvec 0 0 0))
(fvec3-copy-c!
(ftype-&ref pos3-pos3-color4 (posb) sel-instances 0)
(fvec 1 1 1))
(fvec3-copy-c!
(ftype-&ref pos3-pos3-color4 (color) sel-instances 0)
(fvec 1 1 1 1))
(ftype-set! mesh-instance-data (instances) instance-data (ftype-pointer-address sel-instances))
(ftype-set! mesh-instance-data (instance-count) instance-data 1)
(insert-mesh "grid-selector" "quad" geometry instance-data)
(insert-mesh "grid-selector" "quad" geometry 1)
(foreign-free (ftype-pointer-address sel-vertices))
(foreign-free (ftype-pointer-address sel-indices))
(foreign-free (ftype-pointer-address geometry))
(foreign-free (ftype-pointer-address sel-instances))
(foreign-free (ftype-pointer-address instance-data)))))
(foreign-free (ftype-pointer-address geometry)))
(load-grid-selector-position (fvec 0 0 0))))
(define shutdown-grid-selector
(lambda ()
@ -181,30 +188,10 @@
(define update-grid-selector!
(lambda ()
(unless (and (zero? grid-selector-shift-x) (zero? grid-selector-shift-y))
(set! grid-selector-grid-coord (tile-shift-grid-coord grid-selector-grid-coord grid-selector-shift-x grid-selector-shift-y))
(set! grid-selector-shift-x 0)
(set! grid-selector-shift-y 0)
(let ([sel-instances (make-ftype-pointer pos3-pos3-color4 (foreign-alloc (ftype-sizeof pos3-pos3-color4)))]
[instance-data (make-ftype-pointer mesh-instance-data (foreign-alloc (ftype-sizeof mesh-instance-data)))])
(fvec3-copy-c!
(ftype-&ref pos3-pos3-color4 (posa) sel-instances 0)
(grid-coords->world-displacement grid-coord-origin grid-selector-grid-coord))
(fvec3-copy-c!
(ftype-&ref pos3-pos3-color4 (posb) sel-instances 0)
(fvec 1 1 1))
(fvec3-copy-c!
(ftype-&ref pos3-pos3-color4 (color) sel-instances 0)
(fvec 1 1 1 1))
(ftype-set! mesh-instance-data (instances) instance-data (ftype-pointer-address sel-instances))
(ftype-set! mesh-instance-data (instance-count) instance-data 1)
(reload-mesh-instance-data "grid-selector" "quad" instance-data)
(foreign-free (ftype-pointer-address sel-instances))
(foreign-free (ftype-pointer-address instance-data))))))
(load-grid-selector-position (grid-coords->world-displacement grid-coord-origin grid-selector-grid-coord)))))
(define render-grid-selector
(lambda ()