Instancing
The renderer now allows instancing. The way this works is by having to vertex buffers. One contains the normal vertex geometry data, the other contains per-instance data.
This commit is contained in:
parent
583a6e67b3
commit
1ec76f56c8
@ -1,9 +0,0 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 fragColor;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(fragColor, 1.0);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#version 460
|
||||
|
||||
layout(location = 0) in vec2 inPos;
|
||||
layout(location = 1) in vec3 inColor;
|
||||
|
||||
layout(location = 0) out vec3 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(inPos, 0.0, 1.0);
|
||||
fragColor = inColor;
|
||||
}
|
10
renderer/shaders/ui-pane.frag
Normal file
10
renderer/shaders/ui-pane.frag
Normal file
@ -0,0 +1,10 @@
|
||||
#version 460
|
||||
|
||||
layout(location = 0) in vec4 fragColor;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
outColor = fragColor;
|
||||
}
|
18
renderer/shaders/ui-pane.vert
Normal file
18
renderer/shaders/ui-pane.vert
Normal file
@ -0,0 +1,18 @@
|
||||
#version 460
|
||||
|
||||
// vertex geometry data
|
||||
layout(location = 0) in vec2 inPos;
|
||||
|
||||
// instance data
|
||||
layout(location = 1) in vec2 inInstancePos;
|
||||
layout(location = 2) in vec2 inInstanceScale;
|
||||
layout(location = 3) in vec4 inInstanceColor;
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pos = inPos * inInstanceScale + inInstancePos;
|
||||
gl_Position = vec4(pos, 0.0, 1.0);
|
||||
fragColor = inInstanceColor;
|
||||
}
|
@ -46,20 +46,25 @@ typedef struct vulkan_buffer
|
||||
typedef struct mesh
|
||||
{
|
||||
vulkan_buffer vertex_buffer;
|
||||
vulkan_buffer instance_buffer;
|
||||
vulkan_buffer index_buffer;
|
||||
u64 index_count;
|
||||
u64 instance_count;
|
||||
|
||||
} mesh;
|
||||
|
||||
typedef struct graphics_pipeline
|
||||
typedef struct mesh_pipeline
|
||||
{
|
||||
VkPipelineLayout layout;
|
||||
VkPipeline handle;
|
||||
VkPipeline main;
|
||||
VkPipeline wireframe;
|
||||
|
||||
vertex_input_type geometry_type;
|
||||
vertex_input_type instance_type;
|
||||
hash_table meshes;
|
||||
|
||||
} graphics_pipeline;
|
||||
} mesh_pipeline;
|
||||
|
||||
|
||||
#define MAX_FRAMES_IN_FLIGHT 2 // must be a power of two!
|
||||
@ -110,7 +115,7 @@ typedef struct vulkan_context
|
||||
|
||||
} single_submit_context;
|
||||
|
||||
hash_table graphics_pipelines;
|
||||
hash_table mesh_pipelines;
|
||||
|
||||
} vulkan_context;
|
||||
|
||||
@ -140,16 +145,6 @@ static const char* validation_layers[] = { "VK_LAYER_KHRONOS_validation" };
|
||||
#endif
|
||||
static const char* device_extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
|
||||
|
||||
static VkVertexInputBindingDescription pos2_color3_vertex_input_binding =
|
||||
{
|
||||
.binding = 0, .stride = sizeof(pos2_color3_vertex), .inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||
};
|
||||
static VkVertexInputAttributeDescription pos2_color3_vertex_input_attributes[] =
|
||||
{
|
||||
(VkVertexInputAttributeDescription){ .location = 0, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(pos2_color3_vertex, pos) },
|
||||
(VkVertexInputAttributeDescription){ .location = 1, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(pos2_color3_vertex, color) }
|
||||
};
|
||||
|
||||
//
|
||||
// Window
|
||||
//
|
||||
@ -1119,7 +1114,7 @@ static void shutdown_frame_data()
|
||||
|
||||
static u8 init_frame_data()
|
||||
{
|
||||
trace_log(LOG_INFO, "Initializing Vulkan frame data ...");
|
||||
trace_log(LOG_DEBUG, "Initializing Vulkan frame data ...");
|
||||
|
||||
VkCommandBuffer command_buffers[MAX_FRAMES_IN_FLIGHT];
|
||||
if (!allocate_command_buffers(context.command_pool, command_buffers, MAX_FRAMES_IN_FLIGHT)) return 0;
|
||||
@ -1189,7 +1184,7 @@ u8 init_single_submit_context()
|
||||
return 0;
|
||||
}
|
||||
|
||||
trace_log(LOG_DEBUG, "Vulkan upload single-submit successfully created.");
|
||||
trace_log(LOG_DEBUG, "Vulkan single-submit context successfully created.");
|
||||
signal_for_shutdown(shutdown_single_submit_context);
|
||||
|
||||
return 1;
|
||||
@ -1219,7 +1214,7 @@ static u8 end_single_submit_command_recording(VkCommandBuffer command_buffer)
|
||||
};
|
||||
if (vkQueueSubmit(context.device.graphics_queue, 1, &submit_info, context.single_submit_context.fence) != VK_SUCCESS)
|
||||
{
|
||||
trace_log(LOG_ERROR, "vkQueueSubmit call failed in end_upload.");
|
||||
trace_log(LOG_ERROR, "vkQueueSubmit call failed in end_single_submit_command_recording.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1294,6 +1289,14 @@ static u8 init_vulkan_staging_buffer(vulkan_buffer* buffer, VkDeviceSize byte_si
|
||||
return init_vulkan_buffer(buffer, byte_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
}
|
||||
|
||||
// uniform buffer, CPU accessible memory
|
||||
/*
|
||||
static u8 init_vulkan_uniform_buffer(vulkan_buffer* buffer, VkDeviceSize byte_size)
|
||||
{
|
||||
return init_vulkan_buffer(buffer, byte_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
}
|
||||
*/
|
||||
|
||||
// vertex buffer, device memory
|
||||
static u8 init_vulkan_vertex_buffer(vulkan_buffer* buffer, VkDeviceSize byte_size)
|
||||
{
|
||||
@ -1340,7 +1343,7 @@ static u8 load_vulkan_buffer(vulkan_buffer* buffer, VkDeviceSize offset, VkDevic
|
||||
return 1;
|
||||
}
|
||||
|
||||
u8 copy_vulkan_buffer(vulkan_buffer* dst, vulkan_buffer* src, VkDeviceSize dst_offset, VkDeviceSize src_offset, VkDeviceSize byte_size)
|
||||
static u8 copy_vulkan_buffer(vulkan_buffer* dst, vulkan_buffer* src, VkDeviceSize dst_offset, VkDeviceSize src_offset, VkDeviceSize byte_size)
|
||||
{
|
||||
VkCommandBuffer command_buffer;
|
||||
if (!allocate_command_buffers(context.single_submit_context.command_pool, &command_buffer, 1)) return 0;
|
||||
@ -1361,29 +1364,64 @@ u8 copy_vulkan_buffer(vulkan_buffer* dst, vulkan_buffer* src, VkDeviceSize dst_o
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u8 init_mesh(mesh* msh, const mesh_geometry* geometry)
|
||||
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)
|
||||
{
|
||||
VkDeviceSize vertices_byte_size = 0;
|
||||
switch (geometry->vert_type)
|
||||
VkDeviceSize geometry_vertices_byte_size = 0, instance_data_byte_size = 0;
|
||||
for (u8 i = 0; i < 2; i++)
|
||||
{
|
||||
case VERTEX_TYPE_POS2_COLOR3:
|
||||
vertices_byte_size = geometry->vertex_count * sizeof(pos2_color3_vertex);
|
||||
break;
|
||||
default:
|
||||
trace_log(LOG_ERROR, "Failed to create Vulkan mesh; invalid vertex type.");
|
||||
return 0;
|
||||
vertex_input_type t;
|
||||
VkDeviceSize* ds;
|
||||
u64 count;
|
||||
if (i < 1)
|
||||
{
|
||||
t = geometry_type;
|
||||
ds = &geometry_vertices_byte_size;
|
||||
count = geometry->vertex_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = instance_type;
|
||||
ds = &instance_data_byte_size;
|
||||
count = instance_data->instance_count;
|
||||
}
|
||||
|
||||
switch (t)
|
||||
{
|
||||
case VERTEX_INPUT_TYPE_POS2:
|
||||
*ds = count * sizeof(pos2);
|
||||
break;
|
||||
case VERTEX_INPUT_TYPE_POS2_POS2_COLOR4:
|
||||
*ds = count * sizeof(pos2_pos2_color4);
|
||||
break;
|
||||
default:
|
||||
trace_log(LOG_ERROR, "Failed to create mesh; invalid vertex type (binding = %d).", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
VkDeviceSize indices_byte_size = geometry->index_count * sizeof(u32);
|
||||
|
||||
if (geometry->vertex_count && geometry->vertices)
|
||||
{
|
||||
vulkan_buffer staging_buffer;
|
||||
if (!init_vulkan_staging_buffer(&staging_buffer, vertices_byte_size)) return 0;
|
||||
if (!load_vulkan_buffer(&staging_buffer, 0, vertices_byte_size, 0, geometry->vertices)) return 0;
|
||||
if (!init_vulkan_vertex_buffer(&msh->vertex_buffer, vertices_byte_size)) return 0;
|
||||
if (!copy_vulkan_buffer(&msh->vertex_buffer, &staging_buffer, 0, 0, vertices_byte_size)) return 0;
|
||||
if (!init_vulkan_staging_buffer(&staging_buffer, geometry_vertices_byte_size)) return 0;
|
||||
if (!load_vulkan_buffer(&staging_buffer, 0, geometry_vertices_byte_size, 0, geometry->vertices)) return 0;
|
||||
if (!init_vulkan_vertex_buffer(&msh->vertex_buffer, geometry_vertices_byte_size)) return 0;
|
||||
if (!copy_vulkan_buffer(&msh->vertex_buffer, &staging_buffer, 0, 0, geometry_vertices_byte_size)) return 0;
|
||||
shutdown_vulkan_buffer(&staging_buffer);
|
||||
}
|
||||
|
||||
if (instance_data->instance_count && instance_data)
|
||||
{
|
||||
vulkan_buffer staging_buffer;
|
||||
if (!init_vulkan_staging_buffer(&staging_buffer, instance_data_byte_size)) return 0;
|
||||
if (!load_vulkan_buffer(&staging_buffer, 0, instance_data_byte_size, 0, instance_data->instances)) return 0;
|
||||
if (!init_vulkan_vertex_buffer(&msh->instance_buffer, instance_data_byte_size)) return 0;
|
||||
if (!copy_vulkan_buffer(&msh->instance_buffer, &staging_buffer, 0, 0, instance_data_byte_size)) return 0;
|
||||
shutdown_vulkan_buffer(&staging_buffer);
|
||||
}
|
||||
msh->instance_count = instance_data->instance_count;
|
||||
|
||||
if (geometry->index_count && geometry->indices)
|
||||
{
|
||||
vulkan_buffer staging_buffer;
|
||||
if (!init_vulkan_staging_buffer(&staging_buffer, indices_byte_size)) return 0;
|
||||
@ -1400,6 +1438,7 @@ static u8 init_mesh(mesh* msh, const mesh_geometry* geometry)
|
||||
static void shutdown_mesh(mesh* msh)
|
||||
{
|
||||
shutdown_vulkan_buffer(&msh->index_buffer);
|
||||
shutdown_vulkan_buffer(&msh->instance_buffer);
|
||||
shutdown_vulkan_buffer(&msh->vertex_buffer);
|
||||
}
|
||||
|
||||
@ -1443,7 +1482,7 @@ static void shutdown_shader_module(VkShaderModule module)
|
||||
vkDestroyShaderModule(context.device.logical, module, context.allocator);
|
||||
}
|
||||
|
||||
static u8 init_graphics_pipeline(graphics_pipeline* pipeline, const graphics_pipeline_template* template)
|
||||
static u8 init_mesh_pipeline(mesh_pipeline* pipeline, const mesh_pipeline_template* template)
|
||||
{
|
||||
// device features
|
||||
VkPhysicalDeviceFeatures device_features;
|
||||
@ -1454,10 +1493,8 @@ static u8 init_graphics_pipeline(graphics_pipeline* pipeline, const graphics_pip
|
||||
VkShaderModule modules[2];
|
||||
const VkShaderStageFlagBits stage_flag_bits[2] = { VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT };
|
||||
const char* stage_names[2] = { "vert", "frag" };
|
||||
const u8 is_stage[2] = { template->is_vertex, template->is_fragment };
|
||||
for (u8 i = 0; i < 2; i++)
|
||||
{
|
||||
if (!is_stage[i]) continue;
|
||||
char path[512];
|
||||
snprintf(path, 512, "renderer/shaders/%s.%s.spv", template->name, stage_names[i]);
|
||||
if (!init_shader_module(modules + i, path)) return 0;
|
||||
@ -1474,31 +1511,60 @@ static u8 init_graphics_pipeline(graphics_pipeline* pipeline, const graphics_pip
|
||||
|
||||
stage_infos = darray_pushback(stage_infos, &stage_info, 1);
|
||||
}
|
||||
|
||||
|
||||
// vertex input
|
||||
VkPipelineVertexInputStateCreateInfo vertex_input_info =
|
||||
VkVertexInputBindingDescription* binding_descriptions = create_darray(2, sizeof(VkVertexInputBindingDescription));
|
||||
VkVertexInputAttributeDescription* attribute_descriptions = create_darray(8, sizeof(VkVertexInputAttributeDescription));
|
||||
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
|
||||
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
for (u8 i = 0; i < 2; i++)
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
.vertexBindingDescriptionCount = 0,
|
||||
.pVertexBindingDescriptions = NULL,
|
||||
.vertexAttributeDescriptionCount = 0,
|
||||
.pVertexAttributeDescriptions = NULL,
|
||||
.flags = 0,
|
||||
.pNext = NULL
|
||||
};
|
||||
switch (template->vert_type)
|
||||
{
|
||||
case VERTEX_TYPE_POS2_COLOR3:
|
||||
vertex_input_info.vertexBindingDescriptionCount = 1;
|
||||
vertex_input_info.pVertexBindingDescriptions = &pos2_color3_vertex_input_binding;
|
||||
vertex_input_info.vertexAttributeDescriptionCount = 2;
|
||||
vertex_input_info.pVertexAttributeDescriptions = pos2_color3_vertex_input_attributes;
|
||||
break;
|
||||
vertex_input_type t = i < 1 ? template->geometry_type : template->instance_type;
|
||||
VkVertexInputRate input_rate = i < 1 ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||
const u8 idx = get_darray_size(attribute_descriptions);
|
||||
switch (t)
|
||||
{
|
||||
case VERTEX_INPUT_TYPE_POS2:
|
||||
{
|
||||
u8 idx = get_darray_size(attribute_descriptions);
|
||||
const VkVertexInputBindingDescription binding =
|
||||
{
|
||||
.binding = i, .stride = sizeof(pos2), .inputRate = input_rate
|
||||
};
|
||||
const VkVertexInputAttributeDescription attributes[] =
|
||||
{
|
||||
(VkVertexInputAttributeDescription){ .location = idx, .binding = i, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(pos2, pos) }
|
||||
};
|
||||
binding_descriptions = darray_pushback(binding_descriptions, &binding, 1);
|
||||
attribute_descriptions = darray_pushback(attribute_descriptions, attributes, 1);
|
||||
}
|
||||
break;
|
||||
case VERTEX_INPUT_TYPE_POS2_POS2_COLOR4:
|
||||
{
|
||||
const VkVertexInputBindingDescription binding =
|
||||
{
|
||||
.binding = i, .stride = sizeof(pos2_pos2_color4), .inputRate = input_rate
|
||||
};
|
||||
const VkVertexInputAttributeDescription attributes[] =
|
||||
{
|
||||
(VkVertexInputAttributeDescription){ .location = idx, .binding = i, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(pos2_pos2_color4, posa) },
|
||||
(VkVertexInputAttributeDescription){ .location = idx + 1, .binding = i, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(pos2_pos2_color4, posb) },
|
||||
(VkVertexInputAttributeDescription){ .location = idx + 2, .binding = i, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(pos2_pos2_color4, color) }
|
||||
};
|
||||
binding_descriptions = darray_pushback(binding_descriptions, &binding, 1);
|
||||
attribute_descriptions = darray_pushback(attribute_descriptions, attributes, 3);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
trace_log(LOG_ERROR, "Failed to receive a valid vertex type for graphics pipeline '%s'.", template->name);
|
||||
return 0;
|
||||
default:
|
||||
trace_log(LOG_ERROR, "Failed to receive a valid vertex input type (binding = %d) for mesh pipeline '%s'.", i, template->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
vertex_input_info.vertexBindingDescriptionCount = get_darray_size(binding_descriptions);
|
||||
vertex_input_info.pVertexBindingDescriptions = binding_descriptions;
|
||||
vertex_input_info.vertexAttributeDescriptionCount = get_darray_size(attribute_descriptions);
|
||||
vertex_input_info.pVertexAttributeDescriptions = attribute_descriptions;
|
||||
|
||||
// input assembly
|
||||
const VkPipelineInputAssemblyStateCreateInfo input_assembly_info =
|
||||
@ -1602,7 +1668,7 @@ static u8 init_graphics_pipeline(graphics_pipeline* pipeline, const graphics_pip
|
||||
};
|
||||
if (vkCreatePipelineLayout(context.device.logical, &layout_info, context.allocator, &pipeline->layout) != VK_SUCCESS)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to create layout for graphics pipeline '%s'", template->name);
|
||||
trace_log(LOG_ERROR, "Failed to create layout for mesh pipeline '%s'", template->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1631,7 +1697,7 @@ static u8 init_graphics_pipeline(graphics_pipeline* pipeline, const graphics_pip
|
||||
};
|
||||
if (vkCreateGraphicsPipelines(context.device.logical, VK_NULL_HANDLE, 1, &pipeline_info, context.allocator, &pipeline->main) != VK_SUCCESS)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to create main handle graphics pipeline '%s'.", template->name);
|
||||
trace_log(LOG_ERROR, "Failed to create main handle for mesh pipeline '%s'.", template->name);
|
||||
return 0;
|
||||
}
|
||||
if (device_features.fillModeNonSolid == VK_TRUE)
|
||||
@ -1645,26 +1711,29 @@ static u8 init_graphics_pipeline(graphics_pipeline* pipeline, const graphics_pip
|
||||
|
||||
if (vkCreateGraphicsPipelines(context.device.logical, VK_NULL_HANDLE, 1, &wireframe_create_info, context.allocator, &pipeline->wireframe) != VK_SUCCESS)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to create wireframe handle for graphics pipeline '%s'.", template->name);
|
||||
trace_log(LOG_ERROR, "Failed to create wireframe handle for mesh pipeline '%s'.", template->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else pipeline->wireframe = VK_NULL_HANDLE;
|
||||
pipeline->handle = pipeline->main;
|
||||
trace_log(LOG_DEBUG, "Successfully created graphics pipeline '%s'.", template->name);
|
||||
trace_log(LOG_DEBUG, "Successfully created mesh pipeline '%s'.", template->name);
|
||||
|
||||
// clean up
|
||||
destroy_darray(binding_descriptions);
|
||||
destroy_darray(attribute_descriptions);
|
||||
destroy_darray(stage_infos);
|
||||
for (u8 i = 0; i < 2; i++)
|
||||
if (is_stage[i]) shutdown_shader_module(modules[i]);
|
||||
for (u8 i = 0; i < 2; i++) shutdown_shader_module(modules[i]);
|
||||
|
||||
// mesh hashtable
|
||||
// meshes
|
||||
pipeline->geometry_type = template->geometry_type;
|
||||
pipeline->instance_type = template->instance_type;
|
||||
init_hash_table(&pipeline->meshes, 8, sizeof(mesh), basic_hash);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void shutdown_graphics_pipeline(graphics_pipeline* pipeline)
|
||||
static void shutdown_mesh_pipeline(mesh_pipeline* pipeline)
|
||||
{
|
||||
// clean up meshes
|
||||
for (u32 i = 0; i < pipeline->meshes.slot_count; i++)
|
||||
@ -1680,13 +1749,12 @@ static void shutdown_graphics_pipeline(graphics_pipeline* pipeline)
|
||||
vkDestroyPipelineLayout(context.device.logical, pipeline->layout, context.allocator);
|
||||
}
|
||||
|
||||
// TO DO: instanced rendering, for now just draw every mesh belonging to a pipeline once
|
||||
u8 draw_graphics_pipeline(const char* name)
|
||||
u8 draw_mesh_pipeline(const char* name)
|
||||
{
|
||||
graphics_pipeline* pipeline = hash_table_lookup(&context.graphics_pipelines, name);
|
||||
mesh_pipeline* pipeline = hash_table_lookup(&context.mesh_pipelines, name);
|
||||
if (!pipeline)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to draw graphics pipeline '%s'; lookup failed." , name);
|
||||
trace_log(LOG_ERROR, "Failed to draw mesh pipeline '%s'; lookup failed." , name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1698,60 +1766,62 @@ u8 draw_graphics_pipeline(const char* name)
|
||||
{
|
||||
mesh* msh = entry->data;
|
||||
|
||||
// bind vertex and index buffer
|
||||
const VkDeviceSize vertex_offsets[] = { 0 };
|
||||
// bind vertex, instance, and index buffers
|
||||
const VkDeviceSize offsets[] = { 0 };
|
||||
const VkBuffer vertex_buffers[] = { msh->vertex_buffer.handle };
|
||||
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, vertex_offsets);
|
||||
const VkBuffer instance_buffers[] = { msh->instance_buffer.handle };
|
||||
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
|
||||
vkCmdBindVertexBuffers(command_buffer, 1, 1, instance_buffers, offsets);
|
||||
vkCmdBindIndexBuffer(command_buffer, msh->index_buffer.handle, 0, VK_INDEX_TYPE_UINT32);
|
||||
|
||||
|
||||
// draw
|
||||
vkCmdDrawIndexed(command_buffer, msh->index_count, 1, 0, 0, 0);
|
||||
vkCmdDrawIndexed(command_buffer, msh->index_count, msh->instance_count, 0, 0, 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
u8 insert_graphics_pipeline(const graphics_pipeline_template* template)
|
||||
u8 insert_mesh_pipeline(const mesh_pipeline_template* template)
|
||||
{
|
||||
graphics_pipeline pipeline;
|
||||
if (!init_graphics_pipeline(&pipeline, template)) return 0;
|
||||
if (!hash_table_insert(&context.graphics_pipelines, template->name, &pipeline))
|
||||
mesh_pipeline pipeline;
|
||||
if (!init_mesh_pipeline(&pipeline, template)) return 0;
|
||||
if (!hash_table_insert(&context.mesh_pipelines, template->name, &pipeline))
|
||||
{
|
||||
shutdown_graphics_pipeline(&pipeline);
|
||||
shutdown_mesh_pipeline(&pipeline);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
u8 remove_graphics_pipeline(const char* name)
|
||||
u8 remove_mesh_pipeline(const char* name)
|
||||
{
|
||||
graphics_pipeline* pipeline = hash_table_lookup(&context.graphics_pipelines, name);
|
||||
mesh_pipeline* pipeline = hash_table_lookup(&context.mesh_pipelines, name);
|
||||
if (!pipeline)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to remove graphics pipeline '%s'; lookup failed.");
|
||||
trace_log(LOG_ERROR, "Failed to remove mesh pipeline '%s'; lookup failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
shutdown_graphics_pipeline(pipeline);
|
||||
return hash_table_remove(&context.graphics_pipelines, name, NULL);
|
||||
shutdown_mesh_pipeline(pipeline);
|
||||
return hash_table_remove(&context.mesh_pipelines, name, NULL);
|
||||
}
|
||||
|
||||
u8 change_graphics_pipeline_mode(const char* name, graphics_pipeline_mode mode)
|
||||
u8 change_mesh_pipeline_mode(const char* name, mesh_pipeline_mode mode)
|
||||
{
|
||||
graphics_pipeline* pipeline = hash_table_lookup(&context.graphics_pipelines, name);
|
||||
mesh_pipeline* pipeline = hash_table_lookup(&context.mesh_pipelines, name);
|
||||
if (!pipeline)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to change mode of graphics pipeline '%s'; lookup failed.");
|
||||
trace_log(LOG_ERROR, "Failed to change mode of mesh pipeline '%s'; lookup failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case GRAPHICS_PIPELINE_MODE_MAIN:
|
||||
case MESH_PIPELINE_MODE_MAIN:
|
||||
pipeline->handle = pipeline->main;
|
||||
return 1;
|
||||
case GRAPHICS_PIPELINE_MODE_WIREFRAME:
|
||||
case MESH_PIPELINE_MODE_WIREFRAME:
|
||||
if (pipeline->wireframe != VK_NULL_HANDLE)
|
||||
{
|
||||
pipeline->handle = pipeline->wireframe;
|
||||
@ -1759,24 +1829,24 @@ u8 change_graphics_pipeline_mode(const char* name, graphics_pipeline_mode mode)
|
||||
}
|
||||
else
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to change mode of graphics pipeline '%s'; wireframe mode not supported on this device");
|
||||
trace_log(LOG_ERROR, "Failed to change mode of mesh pipeline '%s'; wireframe mode not supported on this device");
|
||||
return 0;
|
||||
}
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u8 insert_mesh(const char* pipeline_name, const char* mesh_name, const mesh_geometry* geometry)
|
||||
u8 insert_mesh(const char* pipeline_name, const char* mesh_name, const mesh_geometry* geometry, const mesh_instance_data* instance_data)
|
||||
{
|
||||
graphics_pipeline* pipeline = hash_table_lookup(&context.graphics_pipelines, pipeline_name);
|
||||
mesh_pipeline* pipeline = hash_table_lookup(&context.mesh_pipelines, pipeline_name);
|
||||
if (!pipeline)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to insert mesh '%s'; graphics pipeline '%s' lookup failed.", mesh_name, pipeline_name);
|
||||
trace_log(LOG_ERROR, "Failed to insert mesh '%s'; mesh pipeline '%s' lookup failed.", mesh_name, pipeline_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mesh msh;
|
||||
if (!init_mesh(&msh, geometry)) return 0;
|
||||
if (!init_mesh(&msh, geometry, pipeline->geometry_type, instance_data, pipeline->instance_type)) return 0;
|
||||
if (!hash_table_insert(&pipeline->meshes, mesh_name, &msh))
|
||||
{
|
||||
shutdown_mesh(&msh);
|
||||
@ -1788,13 +1858,12 @@ u8 insert_mesh(const char* pipeline_name, const char* mesh_name, const mesh_geom
|
||||
|
||||
u8 remove_mesh(const char* pipeline_name, const char* mesh_name)
|
||||
{
|
||||
graphics_pipeline* pipeline = hash_table_lookup(&context.graphics_pipelines, pipeline_name);
|
||||
mesh_pipeline* pipeline = hash_table_lookup(&context.mesh_pipelines, pipeline_name);
|
||||
if (!pipeline)
|
||||
{
|
||||
trace_log(LOG_ERROR, "Failed to remove mesh '%s'; graphics pipeline '%s' lookup failed.", mesh_name, pipeline_name);
|
||||
trace_log(LOG_ERROR, "Failed to remove mesh '%s'; mesh pipeline '%s' lookup failed.", mesh_name, pipeline_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
mesh* msh = hash_table_lookup(&pipeline->meshes, mesh_name);
|
||||
if (!msh)
|
||||
@ -1823,7 +1892,7 @@ u8 init_vulkan()
|
||||
if (!init_frame_data()) return 0;
|
||||
if (!init_single_submit_context()) return 0;
|
||||
|
||||
init_hash_table(&context.graphics_pipelines, 8, sizeof(graphics_pipeline), basic_hash);
|
||||
init_hash_table(&context.mesh_pipelines, 8, sizeof(mesh_pipeline), basic_hash);
|
||||
|
||||
context.image_index = 0;
|
||||
context.current_frame = 0;
|
||||
@ -1836,13 +1905,13 @@ void shutdown_vulkan()
|
||||
{
|
||||
vkDeviceWaitIdle(context.device.logical);
|
||||
|
||||
for (u32 i = 0; i < context.graphics_pipelines.slot_count; i++)
|
||||
for (hash_table_entry* entry = context.graphics_pipelines.entries[i]; entry != NULL; entry = entry->next)
|
||||
for (u32 i = 0; i < context.mesh_pipelines.slot_count; i++)
|
||||
for (hash_table_entry* entry = context.mesh_pipelines.entries[i]; entry != NULL; entry = entry->next)
|
||||
{
|
||||
graphics_pipeline* pipeline = entry->data;
|
||||
shutdown_graphics_pipeline(pipeline);
|
||||
mesh_pipeline* pipeline = entry->data;
|
||||
shutdown_mesh_pipeline(pipeline);
|
||||
}
|
||||
shutdown_hash_table(&context.graphics_pipelines);
|
||||
shutdown_hash_table(&context.mesh_pipelines);
|
||||
|
||||
typedef void (*fn_ptr)();
|
||||
while (context.deletion_stack.head != NULL)
|
||||
|
@ -17,43 +17,55 @@
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VERTEX_TYPE_NONE,
|
||||
VERTEX_TYPE_POS2_COLOR3
|
||||
VERTEX_INPUT_TYPE_POS2,
|
||||
VERTEX_INPUT_TYPE_POS2_POS2_COLOR4
|
||||
|
||||
} vertex_type;
|
||||
} vertex_input_type;
|
||||
|
||||
typedef struct pos2_color3_vertex
|
||||
typedef struct pos2
|
||||
{
|
||||
f32 pos[2];
|
||||
f32 color[3];
|
||||
|
||||
} pos2_color3_vertex;
|
||||
} pos2;
|
||||
|
||||
typedef struct pos2_pos2_color4
|
||||
{
|
||||
f32 posa[2];
|
||||
f32 posb[2];
|
||||
f32 color[4];
|
||||
|
||||
} pos2_pos2_color4;
|
||||
|
||||
typedef struct mesh_geometry
|
||||
{
|
||||
const void* vertices;
|
||||
vertex_type vert_type;
|
||||
u64 vertex_count;
|
||||
const u32* indices;
|
||||
u64 index_count;
|
||||
|
||||
} mesh_geometry;
|
||||
|
||||
typedef struct graphics_pipeline_template
|
||||
typedef struct mesh_instance_data
|
||||
{
|
||||
const void* instances;
|
||||
u64 instance_count;
|
||||
|
||||
} mesh_instance_data;
|
||||
|
||||
typedef struct mesh_pipeline_template
|
||||
{
|
||||
const char* name;
|
||||
u8 is_vertex;
|
||||
u8 is_fragment;
|
||||
vertex_type vert_type;
|
||||
vertex_input_type geometry_type;
|
||||
vertex_input_type instance_type;
|
||||
|
||||
} graphics_pipeline_template;
|
||||
} mesh_pipeline_template;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GRAPHICS_PIPELINE_MODE_MAIN,
|
||||
GRAPHICS_PIPELINE_MODE_WIREFRAME
|
||||
MESH_PIPELINE_MODE_MAIN,
|
||||
MESH_PIPELINE_MODE_WIREFRAME
|
||||
|
||||
} graphics_pipeline_mode;
|
||||
} mesh_pipeline_mode;
|
||||
|
||||
//
|
||||
//
|
||||
@ -66,11 +78,11 @@ void shutdown_window();
|
||||
u8 is_window_open();
|
||||
void poll_window_input();
|
||||
|
||||
u8 draw_graphics_pipeline(const char* name);
|
||||
u8 insert_graphics_pipeline(const graphics_pipeline_template* template);
|
||||
u8 remove_graphics_pipeline(const char* name);
|
||||
u8 change_graphics_pipeline_mode(const char* name, graphics_pipeline_mode mode);
|
||||
u8 insert_mesh(const char* pipeline_name, const char* mesh_name, const mesh_geometry* geometry);
|
||||
u8 draw_mesh_pipeline(const char* name);
|
||||
u8 insert_mesh_pipeline(const mesh_pipeline_template* template);
|
||||
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 remove_mesh(const char* pipeline_name, const char* mesh_name);
|
||||
|
||||
u8 init_vulkan();
|
||||
|
248
src/main.lisp
248
src/main.lisp
@ -28,108 +28,150 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
|
||||
(unless (cffi:foreign-library-loaded-p 'libsofrenderer) (cffi:use-foreign-library libsofrenderer))
|
||||
|
||||
(cffi:defcenum vertex-type
|
||||
:vertex-type-none
|
||||
:vertex-type-pos2-color3)
|
||||
(cffi:defcenum vertex-input-type
|
||||
:vertex-input-type-pos2
|
||||
:vertex-input-type-pos2-pos2-color4)
|
||||
|
||||
(cffi:defcstruct (%pos2-color3-vertex :class c-pos2-color3-vertex)
|
||||
(pos :float :count 2)
|
||||
(color :float :count 3))
|
||||
(cffi:defcstruct (%pos2 :class c-pos2)
|
||||
(pos :float :count 2))
|
||||
|
||||
(defstruct pos2-color3-vertex
|
||||
(pos (vector 0.0 0.0))
|
||||
(color (vector 0.0 0.0 0.0)))
|
||||
(defstruct pos2
|
||||
(pos (vector 0.0 0.0)))
|
||||
|
||||
(defmethod cffi:translate-from-foreign (ptr (type c-pos2-color3-vertex))
|
||||
(cffi:with-foreign-slots ((pos color) ptr (:struct %pos2-color3-vertex))
|
||||
(make-pos2-color3-vertex
|
||||
(defmethod cffi:translate-from-foreign (ptr (type c-pos2))
|
||||
(cffi:with-foreign-slots ((pos) ptr (:struct %pos2))
|
||||
(make-pos2
|
||||
:pos (vector (cffi:mem-aref pos :float 0)
|
||||
(cffi:mem-aref pos :float 1))
|
||||
(cffi:mem-aref pos :float 1)))))
|
||||
|
||||
(defmethod cffi:expand-from-foreign (ptr (type c-pos2))
|
||||
`(cffi:with-foreign-slots ((pos) ,ptr (:struct %pos2))
|
||||
(make-pos2
|
||||
:pos (vector (cffi:mem-aref pos :float 0)
|
||||
(cffi:mem-aref pos :float 1)))))
|
||||
|
||||
(defmethod cffi:translate-into-foreign-memory (value (type c-pos2) ptr)
|
||||
(cffi:with-foreign-slots ((pos) ptr (:struct %pos2))
|
||||
(setf
|
||||
(cffi:mem-aref pos :float 0) (aref (pos2-pos value) 0)
|
||||
(cffi:mem-aref pos :float 1) (aref (pos2-pos value) 1))))
|
||||
|
||||
(defmethod cffi:expand-into-foreign-memory (value (type c-pos2) ptr)
|
||||
`(cffi:with-foreign-slots ((pos color) ,ptr (:struct %pos2))
|
||||
(setf
|
||||
(cffi:mem-aref pos :float 0) (aref (pos2-pos ,value) 0)
|
||||
(cffi:mem-aref pos :float 1) (aref (pos2-pos ,value) 1))))
|
||||
|
||||
(cffi:defcstruct (%pos2-pos2-color4 :class c-pos2-pos2-color4)
|
||||
(posa :float :count 2)
|
||||
(posb :float :count 2)
|
||||
(color :float :count 4))
|
||||
|
||||
(defstruct pos2-pos2-color4
|
||||
(posa (vector 0.0 0.0))
|
||||
(posb (vector 0.0 0.0))
|
||||
(color (vector 0.0 0.0 0.0 0.0)))
|
||||
|
||||
(defmethod cffi:translate-from-foreign (ptr (type c-pos2-pos2-color4))
|
||||
(cffi:with-foreign-slots ((posa posb color) ptr (:struct %pos2-pos2-color4))
|
||||
(make-pos2-pos2-color4
|
||||
:posa (vector (cffi:mem-aref posa :float 0)
|
||||
(cffi:mem-aref posa :float 1))
|
||||
:posb (vector (cffi:mem-aref posb :float 0)
|
||||
(cffi:mem-aref posb :float 1))
|
||||
:color (vector (cffi:mem-aref color :float 0)
|
||||
(cffi:mem-aref color :float 1)
|
||||
(cffi:mem-aref color :float 2)))))
|
||||
(cffi:mem-aref color :float 2)
|
||||
(cffi:mem-aref color :float 4)))))
|
||||
|
||||
(defmethod cffi:expand-from-foreign (ptr (type c-pos2-color3-vertex))
|
||||
`(cffi:with-foreign-slots ((pos color) ,ptr (:struct %pos2-color3-vertex))
|
||||
(make-pos2-color3-vertex
|
||||
:pos (vector (cffi:mem-aref pos :float 0)
|
||||
(cffi:mem-aref pos :float 1))
|
||||
(defmethod cffi:expand-from-foreign (ptr (type c-pos2-pos2-color4))
|
||||
`(cffi:with-foreign-slots ((posa posb color) ,ptr (:struct %pos2-pos2-color4))
|
||||
(make-pos2-pos2-color4
|
||||
:posa (vector (cffi:mem-aref posa :float 0)
|
||||
(cffi:mem-aref posa :float 1))
|
||||
:posb (vector (cffi:mem-aref posb :float 0)
|
||||
(cffi:mem-aref posb :float 1))
|
||||
:color (vector (cffi:mem-aref color :float 0)
|
||||
(cffi:mem-aref color :float 1)
|
||||
(cffi:mem-aref color :float 2)))))
|
||||
|
||||
(defmethod cffi:translate-into-foreign-memory (value (type c-pos2-color3-vertex) ptr)
|
||||
(cffi:with-foreign-slots ((pos color) ptr (:struct %pos2-color3-vertex))
|
||||
(cffi:mem-aref color :float 2)
|
||||
(cffi:mem-aref color :float 4)))))
|
||||
|
||||
(defmethod cffi:translate-into-foreign-memory (value (type c-pos2-pos2-color4) ptr)
|
||||
(cffi:with-foreign-slots ((posa posb color) ptr (:struct %pos2-pos2-color4))
|
||||
(setf
|
||||
(cffi:mem-aref pos :float 0) (aref (pos2-color3-vertex-pos value) 0)
|
||||
(cffi:mem-aref pos :float 1) (aref (pos2-color3-vertex-pos value) 1)
|
||||
(cffi:mem-aref color :float 0) (aref (pos2-color3-vertex-color value) 0)
|
||||
(cffi:mem-aref color :float 1) (aref (pos2-color3-vertex-color value) 1)
|
||||
(cffi:mem-aref color :float 2) (aref (pos2-color3-vertex-color value) 2))))
|
||||
(cffi:mem-aref posa :float 0) (aref (pos2-pos2-color4-posa value) 0)
|
||||
(cffi:mem-aref posa :float 1) (aref (pos2-pos2-color4-posa value) 1)
|
||||
(cffi:mem-aref posb :float 0) (aref (pos2-pos2-color4-posb value) 0)
|
||||
(cffi:mem-aref posb :float 1) (aref (pos2-pos2-color4-posb value) 1)
|
||||
(cffi:mem-aref color :float 0) (aref (pos2-pos2-color4-color value) 0)
|
||||
(cffi:mem-aref color :float 1) (aref (pos2-pos2-color4-color value) 1)
|
||||
(cffi:mem-aref color :float 2) (aref (pos2-pos2-color4-color value) 2)
|
||||
(cffi:mem-aref color :float 3) (aref (pos2-pos2-color4-color value) 3))))
|
||||
|
||||
(defmethod cffi:expand-into-foreign-memory (value (type c-pos2-color3-vertex) ptr)
|
||||
`(cffi:with-foreign-slots ((pos color) ,ptr (:struct %pos2-color3-vertex))
|
||||
(setf
|
||||
(cffi:mem-aref pos :float 0) (aref (pos2-color3-vertex-pos ,value) 0)
|
||||
(cffi:mem-aref pos :float 1) (aref (pos2-color3-vertex-pos ,value) 1)
|
||||
(cffi:mem-aref color :float 0) (aref (pos2-color3-vertex-color ,value) 0)
|
||||
(cffi:mem-aref color :float 1) (aref (pos2-color3-vertex-color ,value) 1)
|
||||
(cffi:mem-aref color :float 2) (aref (pos2-color3-vertex-color ,value) 2))))
|
||||
(defmethod cffi:expand-into-foreign-memory (value (type c-pos2-pos2-color4) ptr)
|
||||
`(cffi:with-foreign-slots ((posa posb color) ,ptr (:struct %pos2-pos2-color4))
|
||||
(setf
|
||||
|
||||
(cffi:mem-aref posa :float 0) (aref (pos2-pos2-color4-posa ,value) 0)
|
||||
(cffi:mem-aref posa :float 1) (aref (pos2-pos2-color4-posa ,value) 1)
|
||||
(cffi:mem-aref posb :float 0) (aref (pos2-pos2-color4-posb ,value) 0)
|
||||
(cffi:mem-aref posb :float 1) (aref (pos2-pos2-color4-posb ,value) 1)
|
||||
(cffi:mem-aref color :float 0) (aref (pos2-pos2-color4-color ,value) 0)
|
||||
(cffi:mem-aref color :float 1) (aref (pos2-pos2-color4-color ,value) 1)
|
||||
(cffi:mem-aref color :float 2) (aref (pos2-pos2-color4-color ,value) 2)
|
||||
(cffi:mem-aref color :float 3) (aref (pos2-pos2-color4-color ,value) 3))))
|
||||
|
||||
(cffi:defcstruct %mesh-geometry
|
||||
(vertices :pointer)
|
||||
(vert-type vertex-type)
|
||||
(vertex-count :uint64)
|
||||
(indices (:pointer :uint32))
|
||||
(index-count :uint64))
|
||||
|
||||
(cffi:defcstruct (%graphics-pipeline-template :class c-graphics-pipeline-template)
|
||||
(cffi:defcstruct %mesh-instance-data
|
||||
(instances :pointer)
|
||||
(instance-count :uint64))
|
||||
|
||||
(cffi:defcstruct (%mesh-pipeline-template :class c-mesh-pipeline-template)
|
||||
(name :string)
|
||||
(vertex? :bool)
|
||||
(fragment? :bool)
|
||||
(vert-type vertex-type))
|
||||
(geometry-type vertex-input-type)
|
||||
(instance-type vertex-input-type))
|
||||
|
||||
(defstruct graphics-pipeline-template
|
||||
(defstruct mesh-pipeline-template
|
||||
(name "" :type string)
|
||||
(vertex? t :type boolean)
|
||||
(fragment? t :type boolean)
|
||||
(vert-type 0 :type integer))
|
||||
(geometry-type 0 :type integer)
|
||||
(instance-type 0 :type integer))
|
||||
|
||||
(defmethod cffi:translate-from-foreign (ptr (type c-graphics-pipeline-template))
|
||||
(cffi:with-foreign-slots ((name vertex? fragment? vert-type) ptr (:struct %graphics-pipeline-template))
|
||||
(make-graphics-pipeline-template
|
||||
(defmethod cffi:translate-from-foreign (ptr (type c-mesh-pipeline-template))
|
||||
(cffi:with-foreign-slots ((name geometry-type instance-type) ptr (:struct %mesh-pipeline-template))
|
||||
(make-mesh-pipeline-template
|
||||
:name name
|
||||
:vertex? vertex?
|
||||
:fragment? fragment?
|
||||
:vert-type vert-type)))
|
||||
:geometry-type geometry-type
|
||||
:instance-type instance-type)))
|
||||
|
||||
(defmethod cffi:expand-from-foreign (ptr (type c-graphics-pipeline-template))
|
||||
`(cffi:with-foreign-slots ((name vertex? fragment? vert-type) ,ptr (:struct %graphics-pipeline-template))
|
||||
(make-graphics-pipeline-template
|
||||
(defmethod cffi:expand-from-foreign (ptr (type c-mesh-pipeline-template))
|
||||
`(cffi:with-foreign-slots ((name geometry-type instance-type) ,ptr (:struct %mesh-pipeline-template))
|
||||
(make-mesh-pipeline-template
|
||||
:name name
|
||||
:vertex? vertex?
|
||||
:fragment? fragment?
|
||||
:vert-type vert-type)))
|
||||
:geometry-type geometry-type
|
||||
:instance-type instance-type)))
|
||||
|
||||
(defmethod cffi:translate-into-foreign-memory (value (type c-graphics-pipeline-template) ptr)
|
||||
(cffi:with-foreign-slots ((name vertex? fragment? vert-type) ptr (:struct %graphics-pipeline-template))
|
||||
(defmethod cffi:translate-into-foreign-memory (value (type c-mesh-pipeline-template) ptr)
|
||||
(cffi:with-foreign-slots ((name geometry-type instance-type) ptr (:struct %mesh-pipeline-template))
|
||||
(setf
|
||||
name (graphics-pipeline-template-name value)
|
||||
vertex? (graphics-pipeline-template-vertex? value)
|
||||
fragment? (graphics-pipeline-template-fragment? value)
|
||||
vert-type (graphics-pipeline-template-vert-type value))))
|
||||
name (mesh-pipeline-template-name value)
|
||||
geometry-type (mesh-pipeline-template-geometry-type value)
|
||||
instance-type (mesh-pipeline-template-instance-type value))))
|
||||
|
||||
(defmethod cffi:expand-into-foreign-memory (value (type c-graphics-pipeline-template) ptr)
|
||||
`(cffi:with-foreign-slots ((name vertex? fragment? vert-type) ,ptr (:struct %graphics-pipeline-template))
|
||||
(defmethod cffi:expand-into-foreign-memory (value (type c-mesh-pipeline-template) ptr)
|
||||
`(cffi:with-foreign-slots ((name geometry-type instance-type) ,ptr (:struct %mesh-pipeline-template))
|
||||
(setf
|
||||
name (graphics-pipeline-template-name ,value)
|
||||
vertex? (graphics-pipeline-template-vertex? ,value)
|
||||
fragment? (graphics-pipeline-template-fragment? ,value)
|
||||
vert-type (graphics-pipeline-template-vert-type ,value))))
|
||||
name (mesh-pipeline-template-name ,value)
|
||||
geometry-type (mesh-pipeline-template-geometry-type ,value)
|
||||
instance-type (mesh-pipeline-template-instance-type ,value))))
|
||||
|
||||
(cffi:defcenum graphics-pipeline-mode
|
||||
:graphics-pipeline-mode-main
|
||||
:graphics-pipeline-mode-wireframe)
|
||||
(cffi:defcenum mesh-pipeline-mode
|
||||
:mesh-pipeline-mode-main
|
||||
:mesh-pipeline-mode-wireframe)
|
||||
|
||||
(cffi:defcfun ("init_window" init-window) :boolean
|
||||
(name :string)
|
||||
@ -142,29 +184,30 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
|
||||
(cffi:defcfun ("poll_window_input" poll-window-input) :void)
|
||||
|
||||
(cffi:defcfun ("draw_graphics_pipeline" draw-graphics-pipeline) :boolean
|
||||
(cffi:defcfun ("draw_mesh_pipeline" draw-mesh-pipeline) :boolean
|
||||
(name :string))
|
||||
|
||||
(cffi:defcfun ("insert_graphics_pipeline" %insert-graphics-pipeline) :boolean
|
||||
(template (:pointer (:struct %graphics-pipeline-template))))
|
||||
(cffi:defcfun ("insert_mesh_pipeline" %insert-mesh-pipeline) :boolean
|
||||
(template (:pointer (:struct %mesh-pipeline-template))))
|
||||
|
||||
(defun insert-graphics-pipeline (name vert-type &key (vertex? t) (fragment? t))
|
||||
(let ((template (make-graphics-pipeline-template :name name :vertex? vertex? :fragment? fragment? :vert-type vert-type)))
|
||||
(cffi:with-foreign-object (ptr '(:struct %graphics-pipeline-template))
|
||||
(setf (cffi:mem-aref ptr '(:struct %graphics-pipeline-template)) template)
|
||||
(%insert-graphics-pipeline ptr))))
|
||||
(defun insert-mesh-pipeline (name geometry-type instance-type)
|
||||
(let ((template (make-mesh-pipeline-template :name name :geometry-type geometry-type :instance-type instance-type)))
|
||||
(cffi:with-foreign-object (ptr '(:struct %mesh-pipeline-template))
|
||||
(setf (cffi:mem-aref ptr '(:struct %mesh-pipeline-template)) template)
|
||||
(%insert-mesh-pipeline ptr))))
|
||||
|
||||
(cffi:defcfun ("remove_graphics_pipeline" remove-graphics-pipeline) :boolean
|
||||
(cffi:defcfun ("remove_mesh_pipeline" remove-mesh-pipeline) :boolean
|
||||
(name :string))
|
||||
|
||||
(cffi:defcfun ("change_graphics_pipeline_mode" change-graphics-pipeline-mode) :boolean
|
||||
(cffi:defcfun ("change_mesh_pipeline_mode" change-mesh-pipeline-mode) :boolean
|
||||
(name :string)
|
||||
(mode graphics-pipeline-mode))
|
||||
(mode mesh-pipeline-mode))
|
||||
|
||||
(cffi:defcfun ("insert_mesh" insert-mesh) :boolean
|
||||
(pipeline-name :string)
|
||||
(mesh-name :string)
|
||||
(geometry (:pointer (:struct %mesh-geometry))))
|
||||
(geometry (:pointer (:struct %mesh-geometry)))
|
||||
(instance-data (:pointer (:struct %mesh-instance-data))))
|
||||
|
||||
(cffi:defcfun ("remove_mesh" remove-mesh) :boolean
|
||||
(pipeline-name :string)
|
||||
@ -191,18 +234,17 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
(when (init-window name width height)
|
||||
(when (init-vulkan) t)))
|
||||
|
||||
(insert-graphics-pipeline "pos2color3" (cffi:foreign-enum-value 'vertex-type :vertex-type-pos2-color3))
|
||||
(insert-mesh-pipeline
|
||||
"ui-pane"
|
||||
(cffi:foreign-enum-value 'vertex-input-type :vertex-input-type-pos2)
|
||||
(cffi:foreign-enum-value 'vertex-input-type :vertex-input-type-pos2-pos2-color4))
|
||||
|
||||
(cffi:with-foreign-object (quad-vertices '(:struct %pos2-color3-vertex) 4)
|
||||
(cffi:with-foreign-object (quad-vertices '(:struct %pos2) 4)
|
||||
(setf
|
||||
(cffi:mem-aref quad-vertices '(:struct %pos2-color3-vertex) 0)
|
||||
(make-pos2-color3-vertex :pos (vector -0.5 -0.5) :color (vector 1.0 0.0 0.0))
|
||||
(cffi:mem-aref quad-vertices '(:struct %pos2-color3-vertex) 1)
|
||||
(make-pos2-color3-vertex :pos (vector 0.5 0.5) :color (vector 0.0 0.0 1.0))
|
||||
(cffi:mem-aref quad-vertices '(:struct %pos2-color3-vertex) 2)
|
||||
(make-pos2-color3-vertex :pos (vector 0.5 -0.5) :color (vector 0.0 1.0 0.0))
|
||||
(cffi:mem-aref quad-vertices '(:struct %pos2-color3-vertex) 3)
|
||||
(make-pos2-color3-vertex :pos (vector -0.5 0.5) :color (vector 1.0 1.0 1.0)))
|
||||
(cffi:mem-aref quad-vertices '(:struct %pos2) 0) (make-pos2 :pos (vector 0.0 0.0))
|
||||
(cffi:mem-aref quad-vertices '(:struct %pos2) 1) (make-pos2 :pos (vector 1.0 1.0))
|
||||
(cffi:mem-aref quad-vertices '(:struct %pos2) 2) (make-pos2 :pos (vector 1.0 0.0))
|
||||
(cffi:mem-aref quad-vertices '(:struct %pos2) 3) (make-pos2 :pos (vector 0.0 1.0)))
|
||||
(cffi:with-foreign-object (quad-indices :uint32 6)
|
||||
(setf
|
||||
(cffi:mem-aref quad-indices :uint32 0) 0
|
||||
@ -212,14 +254,24 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
(cffi:mem-aref quad-indices :uint32 4) 3
|
||||
(cffi:mem-aref quad-indices :uint32 5) 1)
|
||||
(cffi:with-foreign-object (geometry '(:struct %mesh-geometry))
|
||||
(cffi:with-foreign-slots ((vertices vert-type vertex-count indices index-count) geometry (:struct %mesh-geometry))
|
||||
(cffi:with-foreign-slots ((vertices vertex-count indices index-count) geometry (:struct %mesh-geometry))
|
||||
(setf
|
||||
vertices quad-vertices
|
||||
vert-type (cffi:foreign-enum-value 'vertex-type :vertex-type-pos2-color3)
|
||||
vertex-count 4
|
||||
indices quad-indices
|
||||
index-count 6)
|
||||
(insert-mesh "pos2color3" "quad" geometry))))))
|
||||
(cffi:with-foreign-object (quad-instances '(:struct %pos2-pos2-color4) 2)
|
||||
(setf
|
||||
(cffi:mem-aref quad-instances '(:struct %pos2-pos2-color4) 0)
|
||||
(make-pos2-pos2-color4 :posa (vector -0.5 0.5) :posb (vector 0.25 0.25) :color (vector 0.7 0.0 0.0 1.0))
|
||||
(cffi:mem-aref quad-instances '(:struct %pos2-pos2-color4) 1)
|
||||
(make-pos2-pos2-color4 :posa (vector 0.5 0.5) :posb (vector 0.4 0.4) :color (vector 0.0 0.5 0.5 0.6)))
|
||||
(cffi:with-foreign-object (instance-data '(:struct %mesh-instance-data))
|
||||
(cffi:with-foreign-slots ((instances instance-count) instance-data (:struct %mesh-instance-data))
|
||||
(setf
|
||||
instances quad-instances
|
||||
instance-count 2)
|
||||
(insert-mesh "ui-pane" "quad" geometry instance-data)))))))))
|
||||
|
||||
(defun shutdown-game ()
|
||||
(shutdown-vulkan)
|
||||
@ -230,7 +282,7 @@ You should have received a copy of the GNU General Public License along with Sha
|
||||
(defun render-game (l)
|
||||
(declare (ignore l))
|
||||
(when (begin-render-frame)
|
||||
(when (draw-graphics-pipeline "pos2color3")
|
||||
(when (draw-mesh-pipeline "ui-pane")
|
||||
(when (end-render-frame) t))))
|
||||
|
||||
;; Only compile this ONCE!
|
||||
|
Loading…
Reference in New Issue
Block a user