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 += -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
ifeq ($(UNAME),Linux)

View File

@ -1575,6 +1575,15 @@ material const material_material__148_material = {
.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[] = {
{
.semantic = "POSITION",
@ -2078,9 +2087,9 @@ instance_light const instance_lights_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_z,
&node_channel_node_point001_translation_y,
};
node const node_node_point001 = {
@ -2168,8 +2177,8 @@ instance_light const instance_lights_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_z,
&node_channel_node_point002_translation_y,
};
@ -2199,10 +2208,7 @@ node const node_node_point002 = {
transform const transforms_node_camera001[] = {
{
.type = transform_type::MATRIX,
.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},
.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},
},
};
@ -2274,6 +2280,9 @@ collada::types::descriptor const descriptor = {
.images = images,
.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",
.joint_weight_buffer = "data/scenes/shadow_test/shadow_test.vjw",
.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 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,
XMMATRIX const & view,
float t);
void unload_scene();
};
}

View File

@ -6,34 +6,87 @@
#include "collada/instance_types.h"
#include "collada/scene/vulkan.h"
#include "shader_data.h"
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 {
// externally initialized, opaque handle
VkInstance instance;
VkDevice device;
VkPipelineLayout pipelineLayout;
VkDescriptorSetLayout descriptorSetLayout;
// externally initialized, structures
VkPhysicalDeviceProperties physicalDeviceProperties;
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties;
// externally initialized, enum
VkFormat colorFormat;
VkFormat depthFormat;
// externally initialized, pointers
ShaderData * shaderData;
ShaderDataDevice const * shaderDataDevice;
//
// method initialized
//
VkPipelineLayout pipelineLayout;
VkShaderModule shaderModule;
VkPipeline * pipelines;
VkPipeline * pipelines; // per-scene, one per descriptor->inputs_list_count
struct {
VkDeviceSize indexOffset;
VkBuffer buffer;
VkDeviceMemory memory;
} 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
VkCommandBuffer commandBuffer;
uint32_t frameIndex;
@ -44,14 +97,10 @@ namespace collada::scene {
void initial_state(VkInstance instance,
VkDevice device,
VkPipelineLayout pipelineLayout,
VkDescriptorSetLayout descriptorSetLayout,
VkPhysicalDeviceProperties const & physicalDeviceProperties,
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
VkFormat colorFormat,
VkFormat depthFormat,
ShaderData * shaderData,
ShaderDataDevice const * shaderDataDevice);
VkFormat depthFormat);
void per_frame_state(uint32_t frameIndex);
@ -69,6 +118,10 @@ namespace collada::scene {
char const * index_filename);
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
//////////////////////////////////////////////////////////////////////
@ -92,5 +145,12 @@ namespace collada::scene {
XMMATRIX const & view,
int nodes_count,
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;
int const images_count;
material const * const * const materials;
int const materials_count;
//animation const * const animations;
//int const animations_count;

View File

@ -16,3 +16,12 @@ VkDeviceSize allocateFromMemoryRequirements(VkDevice device,
VkMemoryAllocateFlags memoryAllocateFlags,
uint32_t count,
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;
};
struct ShaderData
struct Node
{
column_major float4x4 ModelView;
//int MaterialIndex;
};
struct Scene
{
column_major float4x4 Projection;
column_major float4x4 ModelView[16];
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 {
int ModelViewIndex;
int NodeIndex;
};
[[vk::push_constant]]
@ -33,15 +70,16 @@ struct PushConstant constants;
[shader("vertex")]
VSOutput VSMain(VSInput input)
{
float4x4 modelView = data.ModelView[constants.ModelViewIndex];
//[constants.NodeIndex]
float4x4 modelView = Nodes.n[constants.NodeIndex].ModelView;
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.Texture = input.Texture.xy * 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;
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
//////////////////////////////////////////////////////////////////////

View File

@ -8,9 +8,12 @@ namespace collada::scene {
{
this->descriptor = descriptor;
vulkan.create_pipelines(descriptor);
vulkan.load_vertex_index_buffer(descriptor->position_normal_texture_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);
}
@ -47,4 +50,9 @@ namespace collada::scene {
descriptor->nodes_count,
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,
VkDevice device,
VkPipelineLayout pipelineLayout,
VkDescriptorSetLayout descriptorSetLayout,
VkPhysicalDeviceProperties const & physicalDeviceProperties,
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
VkFormat colorFormat,
VkFormat depthFormat,
ShaderData * shaderData,
ShaderDataDevice const * shaderDataDevice)
VkFormat depthFormat)
{
this->instance = instance;
this->device = device;
this->pipelineLayout = pipelineLayout;
this->descriptorSetLayout = descriptorSetLayout;
this->physicalDeviceProperties = physicalDeviceProperties;
this->physicalDeviceMemoryProperties = physicalDeviceMemoryProperties;
@ -122,9 +116,6 @@ namespace collada::scene {
this->colorFormat = colorFormat;
this->depthFormat = depthFormat;
this->shaderData = shaderData;
this->shaderDataDevice = shaderDataDevice;
load_shader();
}
@ -188,6 +179,253 @@ namespace collada::scene {
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
//////////////////////////////////////////////////////////////////////
@ -218,8 +456,8 @@ namespace collada::scene {
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 1,
.pSetLayouts = &descriptorSetLayout,
.setLayoutCount = 2,
.pSetLayouts = descriptorSetLayouts,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pushConstantRange
};
@ -336,6 +574,8 @@ namespace collada::scene {
pipelines = NewM<VkPipeline>(descriptor->inputs_list_count);
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, descriptor->inputs_list_count, pipelineCreateInfos, nullptr, pipelines));
free(pipelineCreateInfos);
free(vertexBindingDescriptions);
for (int i = 0; i < descriptor->inputs_list_count; i++) {
free((void *)vertexInputStates[i].pVertexAttributeDescriptions);
@ -387,32 +627,40 @@ namespace collada::scene {
instance_types::node const * const node_instances)
{
// store
XMStoreFloat4x4(&shaderData->projection, projection);
XMStoreFloat4x4(&shaderData.scene.projection, projection);
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++) {
XMMATRIX model_view = node_instances[i].world * view;
XMStoreFloat4x4(&shaderData->modelView[i], model_view);
XMStoreFloat4x4(&shaderData.nodes[i].modelView, model_view);
}
// copy
size_t frameOffset = shaderDataDevice->stride * frameIndex;
void * frameData = (void *)(((VkDeviceSize)shaderDataDevice->mappedData) + frameOffset);
VkDeviceSize frameSize{ (sizeof (ShaderData)) };
memcpy(frameData, &shaderData->projection, frameSize);
memcpy(shaderDataDevice.frame[frameIndex].sceneMapped, &shaderData.scene, (sizeof (Scene)));
memcpy(shaderDataDevice.frame[frameIndex].nodesMapped, &shaderData.nodes[0], (sizeof (Node)) * nodes_count);
// flush
VkDeviceSize flushSize{ roundAlignment(frameSize, physicalDeviceProperties.limits.nonCoherentAtomSize) };
VkMappedMemoryRange shaderDataMemoryRange{
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
.memory = shaderDataDevice->memory,
.offset = frameOffset,
.size = flushSize,
VkDeviceSize sceneFlushSize{ shaderDataDevice.frame[frameIndex].sceneSize };
VkDeviceSize nodesFlushSize{ shaderDataDevice.frame[frameIndex].nodesSize };
//fprintf(stderr, "sceneFlushSize %ld\n", sceneFlushSize);
//fprintf(stderr, "nodesFlushSize %ld\n", nodesFlushSize);
VkMappedMemoryRange shaderDataMemoryRanges[2]{
{
.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,
@ -423,4 +671,45 @@ namespace collada::scene {
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,
device,
pipelineLayout,
uniformBufferDescriptorSetLayout,
physicalDeviceProperties,
physicalDeviceMemoryProperties,
surfaceFormat.format,
depthFormat,
&shaderData,
&shaderDataDevice);
depthFormat);
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
@ -1365,18 +1362,12 @@ int main()
//vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0);
*/
collada_state.vulkan.commandBuffer = commandBuffer;
collada_state.vulkan.frameIndex = frameIndex;
collada_state.vulkan.change_frame(commandBuffer, frameIndex);
XMMATRIX projection = currentProjection();
XMMATRIX view = currentView();
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();
vkCmdEndRendering(commandBuffer);
@ -1440,6 +1431,10 @@ int main()
}
VK_CHECK(vkDeviceWaitIdle(device));
collada_state.vulkan.destroy_all(collada_scene_descriptor);
collada_state.unload_scene();
for (uint32_t i = 0; i < maxFramesInFlight; i++) {
vkDestroyFence(device, fences[i], nullptr);
vkDestroySemaphore(device, presentSemaphores[i], nullptr);

View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "volk/volk.h"
#include "vulkan/vk_enum_string_helper.h"
@ -62,3 +63,42 @@ VkDeviceSize allocateFromMemoryRequirements(VkDevice device,
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;
}