collada: per-scene pipelines and descriptor sets
This commit is contained in:
parent
0a33f58f04
commit
c30394c3ed
2
Makefile
2
Makefile
@ -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)
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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);
|
||||
};
|
||||
};
|
||||
|
||||
@ -19,5 +19,7 @@ namespace collada::scene {
|
||||
void update(XMMATRIX const & projection,
|
||||
XMMATRIX const & view,
|
||||
float t);
|
||||
|
||||
void unload_scene();
|
||||
};
|
||||
}
|
||||
|
||||
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
21
src/main.cpp
21
src/main.cpp
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user