collada: per-scene pipelines and descriptor sets

This commit is contained in:
Zack Buhman 2026-04-12 21:58:22 -05:00
parent 0a33f58f04
commit c30394c3ed
13 changed files with 531 additions and 69 deletions

View File

@ -25,7 +25,7 @@ CFLAGS += -I./data
CFLAGS += -I../SDL3-dist/include CFLAGS += -I../SDL3-dist/include
CFLAGS += -fpic CFLAGS += -fpic
#FLAGS += -fstack-protector -fstack-protector-all -fno-omit-frame-pointer -fsanitize=address FLAGS += -fstack-protector -fstack-protector-all -fno-omit-frame-pointer -fsanitize=address
LDFLAGS += -lm LDFLAGS += -lm
ifeq ($(UNAME),Linux) ifeq ($(UNAME),Linux)

View File

@ -1575,6 +1575,15 @@ material const material_material__148_material = {
.effect = &effect_material__148, .effect = &effect_material__148,
}; };
material const * const materials[] = {
&material_coloreffectr5g54b179_material,
&material_coloreffectr134g110b8_material,
&material_coloreffectr255g229b0_material,
&material_coloreffectr6g134b6_material,
&material_coloreffectr88g88b225_material,
&material_material__148_material,
};
input_element const input_elements_position_0_3_normal_0_3_texcoord_0_3[] = { input_element const input_elements_position_0_3_normal_0_3_texcoord_0_3[] = {
{ {
.semantic = "POSITION", .semantic = "POSITION",
@ -2078,9 +2087,9 @@ instance_light const instance_lights_node_point001[] = {
}; };
channel const * const node_channels_node_point001[] = { channel const * const node_channels_node_point001[] = {
&node_channel_node_point001_translation_y,
&node_channel_node_point001_translation_z,
&node_channel_node_point001_translation_x, &node_channel_node_point001_translation_x,
&node_channel_node_point001_translation_z,
&node_channel_node_point001_translation_y,
}; };
node const node_node_point001 = { node const node_node_point001 = {
@ -2168,8 +2177,8 @@ instance_light const instance_lights_node_point002[] = {
}; };
channel const * const node_channels_node_point002[] = { channel const * const node_channels_node_point002[] = {
&node_channel_node_point002_translation_z,
&node_channel_node_point002_translation_x, &node_channel_node_point002_translation_x,
&node_channel_node_point002_translation_z,
&node_channel_node_point002_translation_y, &node_channel_node_point002_translation_y,
}; };
@ -2199,10 +2208,7 @@ node const node_node_point002 = {
transform const transforms_node_camera001[] = { transform const transforms_node_camera001[] = {
{ {
.type = transform_type::MATRIX, .type = transform_type::MATRIX,
.matrix = {-0.9161802f, 0.3124457f, -0.2509807f, -3.604237f, .matrix = {-0.9161802f, 0.3124457f, -0.2509807f, -3.604237f, -0.4006261f, -0.7305838f, 0.5529431f, 4.948456f, -0.01059775f, 0.6071451f, 0.7945203f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
-0.4006261f, -0.7305838f, 0.5529431f, 4.948456f,
-0.01059775f, 0.6071451f, 0.7945203f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f},
}, },
}; };
@ -2274,6 +2280,9 @@ collada::types::descriptor const descriptor = {
.images = images, .images = images,
.images_count = (sizeof (images)) / (sizeof (images[0])), .images_count = (sizeof (images)) / (sizeof (images[0])),
.materials = materials,
.materials_count = (sizeof (materials)) / (sizeof (materials[0])),
.position_normal_texture_buffer = "data/scenes/shadow_test/shadow_test.vtx", .position_normal_texture_buffer = "data/scenes/shadow_test/shadow_test.vtx",
.joint_weight_buffer = "data/scenes/shadow_test/shadow_test.vjw", .joint_weight_buffer = "data/scenes/shadow_test/shadow_test.vjw",
.index_buffer = "data/scenes/shadow_test/shadow_test.idx", .index_buffer = "data/scenes/shadow_test/shadow_test.idx",

View File

@ -9,5 +9,6 @@ namespace collada::node_state {
void allocate_node_instances(types::node const * const * const nodes, int nodes_count); void allocate_node_instances(types::node const * const * const nodes, int nodes_count);
void update_node_world_transform(instance_types::node & node_instance); void update_node_world_transform(instance_types::node & node_instance);
void deallocate_node_instances(int nodes_count);
}; };
}; };

View File

@ -19,5 +19,7 @@ namespace collada::scene {
void update(XMMATRIX const & projection, void update(XMMATRIX const & projection,
XMMATRIX const & view, XMMATRIX const & view,
float t); float t);
void unload_scene();
}; };
} }

View File

@ -6,34 +6,87 @@
#include "collada/instance_types.h" #include "collada/instance_types.h"
#include "collada/scene/vulkan.h" #include "collada/scene/vulkan.h"
#include "shader_data.h"
namespace collada::scene { namespace collada::scene {
// these structures are not vulkan-specific
struct Scene {
XMFLOAT4X4 projection;
XMFLOAT4 lightPosition;
};
struct Node {
XMFLOAT4X4 modelView;
//int materialIndex;
//int _padding0[3];
//int _padding1[4 * 3];
};
static_assert((sizeof (Node)) % 64 == 0);
struct MaterialColor {
XMFLOAT4 emission;
XMFLOAT4 ambient;
XMFLOAT4 diffuse;
XMFLOAT4 specular;
};
static_assert((sizeof (MaterialColor)) % 64 == 0);
struct vulkan { struct vulkan {
// externally initialized, opaque handle // externally initialized, opaque handle
VkInstance instance; VkInstance instance;
VkDevice device; VkDevice device;
VkPipelineLayout pipelineLayout;
VkDescriptorSetLayout descriptorSetLayout;
// externally initialized, structures // externally initialized, structures
VkPhysicalDeviceProperties physicalDeviceProperties; VkPhysicalDeviceProperties physicalDeviceProperties;
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties;
// externally initialized, enum // externally initialized, enum
VkFormat colorFormat; VkFormat colorFormat;
VkFormat depthFormat; VkFormat depthFormat;
// externally initialized, pointers
ShaderData * shaderData;
ShaderDataDevice const * shaderDataDevice;
//
// method initialized // method initialized
//
VkPipelineLayout pipelineLayout;
VkShaderModule shaderModule; VkShaderModule shaderModule;
VkPipeline * pipelines; VkPipeline * pipelines; // per-scene, one per descriptor->inputs_list_count
struct { struct {
VkDeviceSize indexOffset; VkDeviceSize indexOffset;
VkBuffer buffer; VkBuffer buffer;
VkDeviceMemory memory; VkDeviceMemory memory;
} vertexIndex; } vertexIndex;
VkDescriptorPool descriptorPool{ VK_NULL_HANDLE };
static constexpr uint32_t maxFrames = 2;
static constexpr uint32_t perFrameDescriptorCount = 2;
static constexpr uint32_t constantDescriptorCount = 1;
static constexpr uint32_t uniformBufferDescriptorCount = maxFrames * perFrameDescriptorCount + constantDescriptorCount;
VkDescriptorSetLayout descriptorSetLayouts[2]; // unrelated to maxFrames, unrelated to descriptorCount
VkDescriptorSet descriptorSets0[maxFrames];
VkDescriptorSet descriptorSet1;
struct {
Scene scene; // global(?)
Node * nodes; // per-scene
MaterialColor * materialColors; // per-scene
} shaderData;
struct {
VkDeviceMemory memory;
void * mappedData;
struct { // must match perFrameDescriptorCount
VkBuffer sceneBuffer;
VkDeviceAddress sceneOffset;
VkDeviceAddress sceneSize;
void * sceneMapped;
VkBuffer nodesBuffer;
VkDeviceAddress nodesOffset;
VkDeviceAddress nodesSize;
void * nodesMapped;
} frame[maxFrames];
struct { // must match constantDescriptorCount
VkBuffer materialColorsBuffer;
VkDeviceAddress materialColorsOffset;
VkDeviceAddress materialColorsSize;
void * materialColorsMapped;
} constant;
} shaderDataDevice;
// per-frame // per-frame
VkCommandBuffer commandBuffer; VkCommandBuffer commandBuffer;
uint32_t frameIndex; uint32_t frameIndex;
@ -44,14 +97,10 @@ namespace collada::scene {
void initial_state(VkInstance instance, void initial_state(VkInstance instance,
VkDevice device, VkDevice device,
VkPipelineLayout pipelineLayout,
VkDescriptorSetLayout descriptorSetLayout,
VkPhysicalDeviceProperties const & physicalDeviceProperties, VkPhysicalDeviceProperties const & physicalDeviceProperties,
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties, VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
VkFormat colorFormat, VkFormat colorFormat,
VkFormat depthFormat, VkFormat depthFormat);
ShaderData * shaderData,
ShaderDataDevice const * shaderDataDevice);
void per_frame_state(uint32_t frameIndex); void per_frame_state(uint32_t frameIndex);
@ -69,6 +118,10 @@ namespace collada::scene {
char const * index_filename); char const * index_filename);
void create_pipelines(collada::types::descriptor const * const descriptor); void create_pipelines(collada::types::descriptor const * const descriptor);
void create_uniform_buffers(collada::types::descriptor const * const descriptor);
void create_descriptor_sets();
void write_descriptor_sets(collada::types::descriptor const * const descriptor);
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// called by state::draw // called by state::draw
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -92,5 +145,12 @@ namespace collada::scene {
XMMATRIX const & view, XMMATRIX const & view,
int nodes_count, int nodes_count,
instance_types::node const * const node_instances); instance_types::node const * const node_instances);
//////////////////////////////////////////////////////////////////////
// called by main
//////////////////////////////////////////////////////////////////////
void change_frame(VkCommandBuffer commandBuffer, uint32_t frameIndex);
void destroy_all(collada::types::descriptor const * const descriptor);
}; };
} }

View File

@ -399,6 +399,9 @@ namespace collada::types {
image const * const * const images; image const * const * const images;
int const images_count; int const images_count;
material const * const * const materials;
int const materials_count;
//animation const * const animations; //animation const * const animations;
//int const animations_count; //int const animations_count;

View File

@ -16,3 +16,12 @@ VkDeviceSize allocateFromMemoryRequirements(VkDevice device,
VkMemoryAllocateFlags memoryAllocateFlags, VkMemoryAllocateFlags memoryAllocateFlags,
uint32_t count, uint32_t count,
VkDeviceMemory * memory); VkDeviceMemory * memory);
VkDeviceSize allocateFromMemoryRequirements2(VkDevice device,
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
VkMemoryPropertyFlags memoryPropertyFlags,
VkMemoryAllocateFlags memoryAllocateFlags,
uint32_t memoryRequirementsCount,
VkMemoryRequirements const * memoryRequirements,
VkDeviceMemory * memory,
VkDeviceSize * offsets);

View File

@ -14,17 +14,54 @@ struct VSOutput
float3 ViewDirection : NORMAL2; float3 ViewDirection : NORMAL2;
}; };
struct ShaderData struct Node
{
column_major float4x4 ModelView;
//int MaterialIndex;
};
struct Scene
{ {
column_major float4x4 Projection; column_major float4x4 Projection;
column_major float4x4 ModelView[16];
float4 LightPosition; // view space float4 LightPosition; // view space
}; };
[[vk::binding(0, 0)]] ConstantBuffer<ShaderData> data; struct MaterialColor
{
float4 Emission;
float4 Ambient;
float4 Diffuse;
float4 Specular;
};
/*
struct Nodes {
Node n[16];
};
struct MaterialColors {
MaterialColor mc[16];
};
*/
struct SceneNodes {
Scene Scene;
};
struct Nodes {
Node n[11];
};
// set 0: per-frame
[[vk::binding(0, 0)]] ConstantBuffer<Scene> Scene;
[[vk::binding(1, 0)]] ConstantBuffer<Nodes> Nodes;
//[[vk::binding(1, 0)]] cbuffer asdf { Nodes Nodes; }
// set 1: constant
//[[vk::binding(0, 1)]] ConstantBuffer<MaterialColor[]> MaterialColors;
struct PushConstant { struct PushConstant {
int ModelViewIndex; int NodeIndex;
}; };
[[vk::push_constant]] [[vk::push_constant]]
@ -33,15 +70,16 @@ struct PushConstant constants;
[shader("vertex")] [shader("vertex")]
VSOutput VSMain(VSInput input) VSOutput VSMain(VSInput input)
{ {
float4x4 modelView = data.ModelView[constants.ModelViewIndex]; //[constants.NodeIndex]
float4x4 modelView = Nodes.n[constants.NodeIndex].ModelView;
VSOutput output = (VSOutput)0; VSOutput output = (VSOutput)0;
output.Position = mul(data.Projection, mul(modelView, float4(input.Position.xyz, 1.0))) * float4(-1, -1, 1, 1); output.Position = mul(Scene.Projection, mul(modelView, float4(input.Position.xyz, 1.0))) * float4(-1, -1, 1, 1);
output.Normal = mul((float3x3)modelView, input.Normal); output.Normal = mul((float3x3)modelView, input.Normal);
output.Texture = input.Texture.xy * 1.0; output.Texture = input.Texture.xy * 1.0;
float4 viewPosition = mul(modelView, float4(input.Position.xyz, 1.0)); float4 viewPosition = mul(modelView, float4(input.Position.xyz, 1.0));
output.LightDirection = (data.LightPosition - viewPosition).xyz; output.LightDirection = (Scene.LightPosition - viewPosition).xyz;
output.ViewDirection = -viewPosition.xyz; output.ViewDirection = -viewPosition.xyz;
return output; return output;

View File

@ -66,6 +66,14 @@ namespace collada::node_state {
} }
} }
void state::deallocate_node_instances(int nodes_count)
{
for (int i = 0; i < nodes_count; i++) {
free(node_instances[i].transforms);
}
free(node_instances);
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// world matrix // world matrix
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -8,9 +8,12 @@ namespace collada::scene {
{ {
this->descriptor = descriptor; this->descriptor = descriptor;
vulkan.create_pipelines(descriptor);
vulkan.load_vertex_index_buffer(descriptor->position_normal_texture_buffer, vulkan.load_vertex_index_buffer(descriptor->position_normal_texture_buffer,
descriptor->index_buffer); descriptor->index_buffer);
vulkan.create_uniform_buffers(descriptor);
vulkan.create_descriptor_sets();
vulkan.write_descriptor_sets(descriptor);
vulkan.create_pipelines(descriptor);
node_state.allocate_node_instances(descriptor->nodes, descriptor->nodes_count); node_state.allocate_node_instances(descriptor->nodes, descriptor->nodes_count);
} }
@ -47,4 +50,9 @@ namespace collada::scene {
descriptor->nodes_count, descriptor->nodes_count,
node_state.node_instances); node_state.node_instances);
} }
void state::unload_scene()
{
node_state.deallocate_node_instances(descriptor->nodes_count);
}
} }

View File

@ -102,19 +102,13 @@ namespace collada::scene {
void vulkan::initial_state(VkInstance instance, void vulkan::initial_state(VkInstance instance,
VkDevice device, VkDevice device,
VkPipelineLayout pipelineLayout,
VkDescriptorSetLayout descriptorSetLayout,
VkPhysicalDeviceProperties const & physicalDeviceProperties, VkPhysicalDeviceProperties const & physicalDeviceProperties,
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties, VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
VkFormat colorFormat, VkFormat colorFormat,
VkFormat depthFormat, VkFormat depthFormat)
ShaderData * shaderData,
ShaderDataDevice const * shaderDataDevice)
{ {
this->instance = instance; this->instance = instance;
this->device = device; this->device = device;
this->pipelineLayout = pipelineLayout;
this->descriptorSetLayout = descriptorSetLayout;
this->physicalDeviceProperties = physicalDeviceProperties; this->physicalDeviceProperties = physicalDeviceProperties;
this->physicalDeviceMemoryProperties = physicalDeviceMemoryProperties; this->physicalDeviceMemoryProperties = physicalDeviceMemoryProperties;
@ -122,9 +116,6 @@ namespace collada::scene {
this->colorFormat = colorFormat; this->colorFormat = colorFormat;
this->depthFormat = depthFormat; this->depthFormat = depthFormat;
this->shaderData = shaderData;
this->shaderDataDevice = shaderDataDevice;
load_shader(); load_shader();
} }
@ -188,6 +179,253 @@ namespace collada::scene {
vkUnmapMemory(device, vertexIndex.memory); vkUnmapMemory(device, vertexIndex.memory);
} }
//////////////////////////////////////////////////////////////////////
// uniform buffers
//////////////////////////////////////////////////////////////////////
void vulkan::create_uniform_buffers(collada::types::descriptor const * const descriptor)
{
VkMemoryRequirements memoryRequirements[uniformBufferDescriptorCount];
VkDeviceSize offsets[uniformBufferDescriptorCount];
shaderData.nodes = NewM<Node>(descriptor->nodes_count);
shaderData.materialColors = NewM<MaterialColor>(descriptor->materials_count);
uint32_t memoryRequirementsIndex = 0;
// per-frame
for (uint32_t i = 0; i < maxFrames; i++) {
// scene buffer
VkBufferCreateInfo sceneBufferCreateInfo{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = (sizeof (Scene)),
.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
};
VK_CHECK(vkCreateBuffer(device, &sceneBufferCreateInfo, nullptr, &shaderDataDevice.frame[i].sceneBuffer));
vkGetBufferMemoryRequirements(device, shaderDataDevice.frame[i].sceneBuffer, &memoryRequirements[memoryRequirementsIndex++]);
// nodes buffer
VkBufferCreateInfo nodesBufferCreateInfo{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = (sizeof (Node)) * descriptor->nodes_count,
.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
};
VK_CHECK(vkCreateBuffer(device, &nodesBufferCreateInfo, nullptr, &shaderDataDevice.frame[i].nodesBuffer));
vkGetBufferMemoryRequirements(device, shaderDataDevice.frame[i].nodesBuffer, &memoryRequirements[memoryRequirementsIndex++]);
};
// material color buffer
VkBufferCreateInfo materialColorsBufferCreateInfo{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = (sizeof (MaterialColor)) * descriptor->materials_count,
.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
};
VK_CHECK(vkCreateBuffer(device, &materialColorsBufferCreateInfo, nullptr, &shaderDataDevice.constant.materialColorsBuffer));
vkGetBufferMemoryRequirements(device, shaderDataDevice.constant.materialColorsBuffer, &memoryRequirements[memoryRequirementsIndex++]);
assert(memoryRequirementsIndex == uniformBufferDescriptorCount);
VkMemoryPropertyFlags memoryPropertyFlags{ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT };
VkMemoryAllocateFlags memoryAllocateFlags{ };
VkDeviceSize allocationSize = allocateFromMemoryRequirements2(device,
physicalDeviceMemoryProperties,
memoryPropertyFlags,
memoryAllocateFlags,
uniformBufferDescriptorCount,
memoryRequirements,
&shaderDataDevice.memory,
offsets);
VkDeviceSize offset{ 0 };
VkDeviceSize size{ VK_WHOLE_SIZE };
VkMemoryMapFlags flags{ 0 };
VK_CHECK(vkMapMemory(device, shaderDataDevice.memory, offset, size, flags, &shaderDataDevice.mappedData));
uint32_t offsetsIndex = 0;
// this must match the same order as memoryRequirements
for (uint32_t i = 0; i < maxFrames; i++) {
shaderDataDevice.frame[i].sceneOffset = offsets[offsetsIndex];
shaderDataDevice.frame[i].sceneSize = memoryRequirements[offsetsIndex++].size;
shaderDataDevice.frame[i].sceneMapped = (void *)(((size_t)shaderDataDevice.mappedData) + shaderDataDevice.frame[i].sceneOffset);
VK_CHECK(vkBindBufferMemory(device, shaderDataDevice.frame[i].sceneBuffer, shaderDataDevice.memory, shaderDataDevice.frame[i].sceneOffset));
shaderDataDevice.frame[i].nodesOffset = offsets[offsetsIndex];
shaderDataDevice.frame[i].nodesSize = memoryRequirements[offsetsIndex++].size;
shaderDataDevice.frame[i].nodesMapped = (void *)(((size_t)shaderDataDevice.mappedData) + shaderDataDevice.frame[i].nodesOffset);
VK_CHECK(vkBindBufferMemory(device, shaderDataDevice.frame[i].nodesBuffer, shaderDataDevice.memory, shaderDataDevice.frame[i].nodesOffset));
}
shaderDataDevice.constant.materialColorsOffset = offsets[offsetsIndex];
shaderDataDevice.constant.materialColorsSize = memoryRequirements[offsetsIndex++].size;
shaderDataDevice.constant.materialColorsMapped = (void *)(((size_t)shaderDataDevice.mappedData) + shaderDataDevice.constant.materialColorsOffset);
VK_CHECK(vkBindBufferMemory(device, shaderDataDevice.constant.materialColorsBuffer, shaderDataDevice.memory, shaderDataDevice.constant.materialColorsOffset));
// if materialColorSize rounded to a multiple of nonCoherentAtomSize is larger than the size of the allocated memory, round down to VK_WHOLE_SIZE
if (shaderDataDevice.constant.materialColorsOffset + shaderDataDevice.constant.materialColorsSize > allocationSize) {
shaderDataDevice.constant.materialColorsSize = VK_WHOLE_SIZE;
}
assert(offsetsIndex == uniformBufferDescriptorCount);
}
//////////////////////////////////////////////////////////////////////
// descriptor sets
//////////////////////////////////////////////////////////////////////
void vulkan::create_descriptor_sets()
{
//
// pool
//
VkDescriptorPoolSize descriptorPoolSizes[1]{
{
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = uniformBufferDescriptorCount + 1, // why + 1?
}
};
VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.maxSets = 2,
.poolSizeCount = 1,
.pPoolSizes = descriptorPoolSizes
};
VK_CHECK(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool));
//
// uniform buffer descriptor set layout/allocation (set 0, per-frame)
//
{
constexpr int bindingCount = 2;
VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[bindingCount]{
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT
},
{
.binding = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT
}
};
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = bindingCount,
.pBindings = descriptorSetLayoutBindings
};
VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayouts[0]));
VkDescriptorSetLayout setLayouts[maxFrames];
for (uint32_t i = 0; i < maxFrames; i++) {
setLayouts[i] = descriptorSetLayouts[0];
};
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = descriptorPool,
.descriptorSetCount = maxFrames,
.pSetLayouts = setLayouts
};
VK_CHECK(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, descriptorSets0));
}
//
// uniform buffer descriptor set layout/allocation (set 1, constant)
//
{
constexpr int bindingCount = 1;
VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[bindingCount]{
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT
},
};
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = bindingCount,
.pBindings = descriptorSetLayoutBindings
};
VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayouts[1]));
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = descriptorPool,
.descriptorSetCount = 1,
.pSetLayouts = &descriptorSetLayouts[1]
};
VK_CHECK(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet1));
}
}
//////////////////////////////////////////////////////////////////////
// descriptor set writes
//////////////////////////////////////////////////////////////////////
void vulkan::write_descriptor_sets(collada::types::descriptor const * const descriptor)
{
VkWriteDescriptorSet writeDescriptorSets[uniformBufferDescriptorCount];
uint32_t writeIndex = 0;
VkDescriptorBufferInfo sceneDescriptorBufferInfos[maxFrames];
VkDescriptorBufferInfo nodesDescriptorBufferInfos[maxFrames];
for (uint32_t i = 0; i < maxFrames; i++) {
sceneDescriptorBufferInfos[i] = {
.buffer = shaderDataDevice.frame[i].sceneBuffer,
.offset = 0,
.range = shaderDataDevice.frame[i].sceneSize,
};
writeDescriptorSets[writeIndex++] = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSets0[i],
.dstBinding = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.pBufferInfo = &sceneDescriptorBufferInfos[i]
};
nodesDescriptorBufferInfos[i] = {
.buffer = shaderDataDevice.frame[i].nodesBuffer,
.offset = 0,
.range = shaderDataDevice.frame[i].nodesSize,
};
writeDescriptorSets[writeIndex++] = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSets0[i],
.dstBinding = 1,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.pBufferInfo = &nodesDescriptorBufferInfos[i]
};
}
VkDescriptorBufferInfo materialColorsDescriptorBufferInfo{
.buffer = shaderDataDevice.constant.materialColorsBuffer,
.offset = 0,
.range = shaderDataDevice.constant.materialColorsSize,
};
writeDescriptorSets[writeIndex++] = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSet1,
.dstBinding = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.pBufferInfo = &materialColorsDescriptorBufferInfo
};
assert(writeIndex == uniformBufferDescriptorCount);
vkUpdateDescriptorSets(device, writeIndex, writeDescriptorSets, 0, nullptr);
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// shader // shader
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -218,8 +456,8 @@ namespace collada::scene {
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{ VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 1, .setLayoutCount = 2,
.pSetLayouts = &descriptorSetLayout, .pSetLayouts = descriptorSetLayouts,
.pushConstantRangeCount = 1, .pushConstantRangeCount = 1,
.pPushConstantRanges = &pushConstantRange .pPushConstantRanges = &pushConstantRange
}; };
@ -336,6 +574,8 @@ namespace collada::scene {
pipelines = NewM<VkPipeline>(descriptor->inputs_list_count); pipelines = NewM<VkPipeline>(descriptor->inputs_list_count);
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, descriptor->inputs_list_count, pipelineCreateInfos, nullptr, pipelines)); VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, descriptor->inputs_list_count, pipelineCreateInfos, nullptr, pipelines));
free(pipelineCreateInfos);
free(vertexBindingDescriptions); free(vertexBindingDescriptions);
for (int i = 0; i < descriptor->inputs_list_count; i++) { for (int i = 0; i < descriptor->inputs_list_count; i++) {
free((void *)vertexInputStates[i].pVertexAttributeDescriptions); free((void *)vertexInputStates[i].pVertexAttributeDescriptions);
@ -387,32 +627,40 @@ namespace collada::scene {
instance_types::node const * const node_instances) instance_types::node const * const node_instances)
{ {
// store // store
XMStoreFloat4x4(&shaderData->projection, projection); XMStoreFloat4x4(&shaderData.scene.projection, projection);
XMVECTOR lightPosition = XMVector3Transform(XMVectorSet(-42, -40, 156, 0), view); XMVECTOR lightPosition = XMVector3Transform(XMVectorSet(-42, -40, 156, 0), view);
XMStoreFloat4(&shaderData->lightPosition, lightPosition); XMStoreFloat4(&shaderData.scene.lightPosition, lightPosition);
for (int i = 0; i < nodes_count; i++) { for (int i = 0; i < nodes_count; i++) {
XMMATRIX model_view = node_instances[i].world * view; XMMATRIX model_view = node_instances[i].world * view;
XMStoreFloat4x4(&shaderData->modelView[i], model_view); XMStoreFloat4x4(&shaderData.nodes[i].modelView, model_view);
} }
// copy // copy
memcpy(shaderDataDevice.frame[frameIndex].sceneMapped, &shaderData.scene, (sizeof (Scene)));
size_t frameOffset = shaderDataDevice->stride * frameIndex; memcpy(shaderDataDevice.frame[frameIndex].nodesMapped, &shaderData.nodes[0], (sizeof (Node)) * nodes_count);
void * frameData = (void *)(((VkDeviceSize)shaderDataDevice->mappedData) + frameOffset);
VkDeviceSize frameSize{ (sizeof (ShaderData)) };
memcpy(frameData, &shaderData->projection, frameSize);
// flush // flush
VkDeviceSize flushSize{ roundAlignment(frameSize, physicalDeviceProperties.limits.nonCoherentAtomSize) }; VkDeviceSize sceneFlushSize{ shaderDataDevice.frame[frameIndex].sceneSize };
VkMappedMemoryRange shaderDataMemoryRange{ VkDeviceSize nodesFlushSize{ shaderDataDevice.frame[frameIndex].nodesSize };
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, //fprintf(stderr, "sceneFlushSize %ld\n", sceneFlushSize);
.memory = shaderDataDevice->memory, //fprintf(stderr, "nodesFlushSize %ld\n", nodesFlushSize);
.offset = frameOffset, VkMappedMemoryRange shaderDataMemoryRanges[2]{
.size = flushSize, {
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
.memory = shaderDataDevice.memory,
.offset = shaderDataDevice.frame[frameIndex].sceneOffset,
.size = roundAlignment(sceneFlushSize, physicalDeviceProperties.limits.nonCoherentAtomSize),
},
{
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
.memory = shaderDataDevice.memory,
.offset = shaderDataDevice.frame[frameIndex].nodesOffset,
.size = roundAlignment(nodesFlushSize, physicalDeviceProperties.limits.nonCoherentAtomSize),
}
}; };
vkFlushMappedMemoryRanges(device, 1, &shaderDataMemoryRange); vkFlushMappedMemoryRanges(device, 2, shaderDataMemoryRanges);
} }
void vulkan::draw_node(int32_t node_index, void vulkan::draw_node(int32_t node_index,
@ -423,4 +671,45 @@ namespace collada::scene {
draw_instance_geometries(node.instance_geometries, node.instance_geometries_count); draw_instance_geometries(node.instance_geometries, node.instance_geometries_count);
} }
void vulkan::change_frame(VkCommandBuffer commandBuffer, uint32_t frameIndex)
{
this->commandBuffer = commandBuffer;
this->frameIndex = frameIndex;
VkDescriptorSet descriptorSets[2] = {
descriptorSets0[frameIndex],
descriptorSet1,
};
vkCmdBindDescriptorSets(commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout,
0, 2, descriptorSets,
0, nullptr);
}
void vulkan::destroy_all(collada::types::descriptor const * const descriptor)
{
free(shaderData.nodes);
free(shaderData.materialColors);
vkDestroyBuffer(device, vertexIndex.buffer, nullptr);
vkFreeMemory(device, vertexIndex.memory, nullptr);
for (uint32_t i = 0; i < maxFrames; i++) {
vkDestroyBuffer(device, shaderDataDevice.frame[i].sceneBuffer, nullptr);
vkDestroyBuffer(device, shaderDataDevice.frame[i].nodesBuffer, nullptr);
}
vkDestroyBuffer(device, shaderDataDevice.constant.materialColorsBuffer, nullptr);
vkFreeMemory(device, shaderDataDevice.memory, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts[0], nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts[1], nullptr);
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
for (int i = 0; i < descriptor->inputs_list_count; i++) {
vkDestroyPipeline(device, pipelines[i], nullptr);
}
free(pipelines);
vkDestroyShaderModule(device, shaderModule, nullptr);
}
} }

View File

@ -1174,16 +1174,13 @@ int main()
collada_state.vulkan.initial_state(instance, collada_state.vulkan.initial_state(instance,
device, device,
pipelineLayout,
uniformBufferDescriptorSetLayout,
physicalDeviceProperties, physicalDeviceProperties,
physicalDeviceMemoryProperties, physicalDeviceMemoryProperties,
surfaceFormat.format, surfaceFormat.format,
depthFormat, depthFormat);
&shaderData,
&shaderDataDevice);
collada_state.load_scene(&shadow_test::descriptor); collada::types::descriptor const * collada_scene_descriptor = &shadow_test::descriptor;
collada_state.load_scene(collada_scene_descriptor);
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// loop // loop
@ -1365,18 +1362,12 @@ int main()
//vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0); //vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0);
*/ */
collada_state.vulkan.commandBuffer = commandBuffer; collada_state.vulkan.change_frame(commandBuffer, frameIndex);
collada_state.vulkan.frameIndex = frameIndex;
XMMATRIX projection = currentProjection(); XMMATRIX projection = currentProjection();
XMMATRIX view = currentView(); XMMATRIX view = currentView();
collada_state.update(projection, view, 0); collada_state.update(projection, view, 0);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
collada_state.vulkan.pipelineLayout,
0, 1, &uniformBufferDescriptorSets[frameIndex],
0, nullptr);
collada_state.draw(); collada_state.draw();
vkCmdEndRendering(commandBuffer); vkCmdEndRendering(commandBuffer);
@ -1440,6 +1431,10 @@ int main()
} }
VK_CHECK(vkDeviceWaitIdle(device)); VK_CHECK(vkDeviceWaitIdle(device));
collada_state.vulkan.destroy_all(collada_scene_descriptor);
collada_state.unload_scene();
for (uint32_t i = 0; i < maxFramesInFlight; i++) { for (uint32_t i = 0; i < maxFramesInFlight; i++) {
vkDestroyFence(device, fences[i], nullptr); vkDestroyFence(device, fences[i], nullptr);
vkDestroySemaphore(device, presentSemaphores[i], nullptr); vkDestroySemaphore(device, presentSemaphores[i], nullptr);

View File

@ -1,5 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#include "volk/volk.h" #include "volk/volk.h"
#include "vulkan/vk_enum_string_helper.h" #include "vulkan/vk_enum_string_helper.h"
@ -62,3 +63,42 @@ VkDeviceSize allocateFromMemoryRequirements(VkDevice device,
return stride; return stride;
} }
VkDeviceSize allocateFromMemoryRequirements2(VkDevice device,
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
VkMemoryPropertyFlags memoryPropertyFlags,
VkMemoryAllocateFlags memoryAllocateFlags,
uint32_t memoryRequirementsCount,
VkMemoryRequirements const * memoryRequirements,
VkDeviceMemory * memory,
VkDeviceSize * offsets)
{
assert(memoryRequirementsCount > 0);
uint32_t memoryTypeBits = memoryRequirements[0].memoryTypeBits;
for (uint32_t i = 1; i < memoryRequirementsCount; i++) {
assert(memoryRequirements[i].memoryTypeBits == memoryTypeBits);
}
uint32_t memoryTypeIndex = findMemoryTypeIndex(physicalDeviceMemoryProperties,
memoryTypeBits,
memoryPropertyFlags);
VkDeviceSize offset = 0;
for (uint32_t i = 0; i < memoryRequirementsCount; i++) {
offset = roundAlignment(offset, memoryRequirements[i].alignment);
offsets[i] = offset;
offset += memoryRequirements[i].size;
}
VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
.flags = memoryAllocateFlags,
};
VkMemoryAllocateInfo memoryAllocateInfo{
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &memoryAllocateFlagsInfo,
.allocationSize = offset,
.memoryTypeIndex = memoryTypeIndex,
};
VK_CHECK(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, memory));
return offset;
}