render collada scene
This commit is contained in:
parent
1456e04200
commit
0a33f58f04
14
Makefile
14
Makefile
@ -21,10 +21,11 @@ CFLAGS += -Wno-error=array-bounds
|
|||||||
CFLAGS += -Wno-unknown-pragmas
|
CFLAGS += -Wno-unknown-pragmas
|
||||||
CFLAGS += -fno-strict-aliasing
|
CFLAGS += -fno-strict-aliasing
|
||||||
CFLAGS += -I./include
|
CFLAGS += -I./include
|
||||||
|
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)
|
||||||
@ -40,7 +41,14 @@ OBJS = \
|
|||||||
src/volk/volk.o \
|
src/volk/volk.o \
|
||||||
src/file.o \
|
src/file.o \
|
||||||
src/pack.o \
|
src/pack.o \
|
||||||
src/dds_validate.o
|
src/dds_validate.o \
|
||||||
|
src/vulkan_helper.o \
|
||||||
|
src/collada/scene/vulkan.o \
|
||||||
|
src/collada/scene.o \
|
||||||
|
src/collada/node_state.o
|
||||||
|
|
||||||
|
SCENES = \
|
||||||
|
data/scenes/shadow_test/shadow_test.o
|
||||||
|
|
||||||
ifeq ($(UNAME),Darwin)
|
ifeq ($(UNAME),Darwin)
|
||||||
LIBS = \
|
LIBS = \
|
||||||
@ -61,7 +69,7 @@ all: main
|
|||||||
%.o: %.s
|
%.o: %.s
|
||||||
$(AS) $< -o $@
|
$(AS) $< -o $@
|
||||||
|
|
||||||
main: $(OBJS) $(LIBS) $(BINS) $(SHADERS)
|
main: $(OBJS) $(LIBS) $(SCENES)
|
||||||
$(CC) $(ARCH) $(LDFLAGS) $(FLAGS) $(OPT) $(DEBUG) $^ -o $@
|
$(CC) $(ARCH) $(LDFLAGS) $(FLAGS) $(OPT) $(DEBUG) $^ -o $@
|
||||||
|
|
||||||
%.spv: %.hlsl
|
%.spv: %.hlsl
|
||||||
|
|||||||
999
data/scenes/shadow_test/shadow_test.DAE
Normal file
999
data/scenes/shadow_test/shadow_test.DAE
Normal file
File diff suppressed because one or more lines are too long
2282
data/scenes/shadow_test/shadow_test.cpp
Normal file
2282
data/scenes/shadow_test/shadow_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3
data/scenes/shadow_test/shadow_test.h
Normal file
3
data/scenes/shadow_test/shadow_test.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
namespace shadow_test {
|
||||||
|
extern collada::types::descriptor const descriptor;
|
||||||
|
}
|
||||||
BIN
data/scenes/shadow_test/shadow_test.idx
Normal file
BIN
data/scenes/shadow_test/shadow_test.idx
Normal file
Binary file not shown.
0
data/scenes/shadow_test/shadow_test.vjw
Normal file
0
data/scenes/shadow_test/shadow_test.vjw
Normal file
BIN
data/scenes/shadow_test/shadow_test.vtx
Normal file
BIN
data/scenes/shadow_test/shadow_test.vtx
Normal file
Binary file not shown.
@ -1,4 +1,7 @@
|
|||||||
shader/triangle.spv
|
shader/triangle.spv
|
||||||
|
shader/collada.spv
|
||||||
|
data/scenes/shadow_test/shadow_test.vtx
|
||||||
|
data/scenes/shadow_test/shadow_test.idx
|
||||||
checker.idx
|
checker.idx
|
||||||
checker.vtx
|
checker.vtx
|
||||||
checker.data
|
checker.data
|
||||||
|
|||||||
54
include/check.h
Normal file
54
include/check.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define SDL_CHECK(f) \
|
||||||
|
{ \
|
||||||
|
bool result = (f); \
|
||||||
|
if (result != true) { \
|
||||||
|
fprintf(stderr, "SDL: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, SDL_GetError()); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SDL_CHECK_NONNULL(f) \
|
||||||
|
{ \
|
||||||
|
void * ptr = (void *)(f); \
|
||||||
|
if (ptr == nullptr) { \
|
||||||
|
fprintf(stderr, "SDL: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, SDL_GetError()); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VK_CHECK(f) \
|
||||||
|
{ \
|
||||||
|
VkResult result = (f); \
|
||||||
|
if (result != VK_SUCCESS) { \
|
||||||
|
fprintf(stderr, "VK: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, string_VkResult(result)); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VK_CHECK_SWAPCHAIN(f) \
|
||||||
|
{ \
|
||||||
|
VkResult result = (f); \
|
||||||
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { \
|
||||||
|
updateSwapchain = true; \
|
||||||
|
} else if (result != VK_SUCCESS) { \
|
||||||
|
fprintf(stderr, "VK: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, string_VkResult(result)); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT(expr, msg) \
|
||||||
|
{ \
|
||||||
|
bool result = (expr); \
|
||||||
|
if (result != true) { \
|
||||||
|
fprintf(stderr, "%s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, msg); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__) // MSVC
|
||||||
|
#define UNREACHABLE() __assume(false);
|
||||||
|
#else // GCC, Clang
|
||||||
|
#define UNREACHABLE() __builtin_unreachable();
|
||||||
|
#endif
|
||||||
38
include/collada/inputs.h
Normal file
38
include/collada/inputs.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "collada/types.h"
|
||||||
|
|
||||||
|
namespace collada::inputs {
|
||||||
|
inline static uint32_t format_size(types::input_format format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case types::input_format::FLOAT1: return 1 * 4;
|
||||||
|
case types::input_format::FLOAT2: return 2 * 4;
|
||||||
|
case types::input_format::FLOAT3: return 3 * 4;
|
||||||
|
case types::input_format::FLOAT4: return 4 * 4;
|
||||||
|
case types::input_format::INT1: return 1 * 4;
|
||||||
|
case types::input_format::INT2: return 2 * 4;
|
||||||
|
case types::input_format::INT3: return 3 * 4;
|
||||||
|
case types::input_format::INT4: return 4 * 4;
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static types::input_element const input_elements_blendindices_0_4_blendweight_0_4[] = {
|
||||||
|
{
|
||||||
|
.semantic = "BLENDINDICES",
|
||||||
|
.semantic_index = 0,
|
||||||
|
.format = types::input_format::INT4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.semantic = "BLENDWEIGHT",
|
||||||
|
.semantic_index = 0,
|
||||||
|
.format = types::input_format::FLOAT4,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static types::inputs const skin_inputs = {
|
||||||
|
.elements = input_elements_blendindices_0_4_blendweight_0_4,
|
||||||
|
.elements_count = 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
32
include/collada/instance_types.h
Normal file
32
include/collada/instance_types.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "directxmath/directxmath.h"
|
||||||
|
|
||||||
|
#include "collada/types.h"
|
||||||
|
|
||||||
|
namespace collada::instance_types {
|
||||||
|
|
||||||
|
struct XM_ALIGNED_DATA(16) lookat {
|
||||||
|
XMVECTOR eye;
|
||||||
|
XMVECTOR at;
|
||||||
|
XMVECTOR up;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XM_ALIGNED_DATA(16) transform {
|
||||||
|
union {
|
||||||
|
instance_types::lookat lookat;
|
||||||
|
XMMATRIX matrix;
|
||||||
|
XMVECTOR vector;
|
||||||
|
};
|
||||||
|
types::transform_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct node {
|
||||||
|
// immutable state
|
||||||
|
types::node const * node;
|
||||||
|
|
||||||
|
// mutable state
|
||||||
|
transform * transforms;
|
||||||
|
XMMATRIX world;
|
||||||
|
};
|
||||||
|
}
|
||||||
13
include/collada/node_state.h
Normal file
13
include/collada/node_state.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "collada/types.h"
|
||||||
|
#include "collada/instance_types.h"
|
||||||
|
|
||||||
|
namespace collada::node_state {
|
||||||
|
struct state {
|
||||||
|
instance_types::node * node_instances;
|
||||||
|
|
||||||
|
void allocate_node_instances(types::node const * const * const nodes, int nodes_count);
|
||||||
|
void update_node_world_transform(instance_types::node & node_instance);
|
||||||
|
};
|
||||||
|
};
|
||||||
23
include/collada/scene.h
Normal file
23
include/collada/scene.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "collada/types.h"
|
||||||
|
#include "collada/instance_types.h"
|
||||||
|
#include "collada/node_state.h"
|
||||||
|
|
||||||
|
#include "collada/scene/vulkan.h"
|
||||||
|
|
||||||
|
namespace collada::scene {
|
||||||
|
struct state {
|
||||||
|
types::descriptor const * descriptor;
|
||||||
|
node_state::state node_state;
|
||||||
|
|
||||||
|
collada::scene::vulkan vulkan;
|
||||||
|
|
||||||
|
void load_scene(types::descriptor const * const descriptor);
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
void update(XMMATRIX const & projection,
|
||||||
|
XMMATRIX const & view,
|
||||||
|
float t);
|
||||||
|
};
|
||||||
|
}
|
||||||
96
include/collada/scene/vulkan.h
Normal file
96
include/collada/scene/vulkan.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "volk/volk.h"
|
||||||
|
|
||||||
|
#include "collada/types.h"
|
||||||
|
#include "collada/instance_types.h"
|
||||||
|
#include "collada/scene/vulkan.h"
|
||||||
|
|
||||||
|
#include "shader_data.h"
|
||||||
|
|
||||||
|
namespace collada::scene {
|
||||||
|
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
|
||||||
|
VkShaderModule shaderModule;
|
||||||
|
VkPipeline * pipelines;
|
||||||
|
struct {
|
||||||
|
VkDeviceSize indexOffset;
|
||||||
|
VkBuffer buffer;
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
} vertexIndex;
|
||||||
|
|
||||||
|
// per-frame
|
||||||
|
VkCommandBuffer commandBuffer;
|
||||||
|
uint32_t frameIndex;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// called directly
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
void per_frame_state(uint32_t frameIndex);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// called by initial_state
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void load_shader();
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// called by state::load_scene
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void load_vertex_index_buffer(char const * vertex_filename,
|
||||||
|
char const * index_filename);
|
||||||
|
void create_pipelines(collada::types::descriptor const * const descriptor);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// called by state::draw
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void draw_geometry(types::geometry const & geometry,
|
||||||
|
types::instance_material const * const instance_materials,
|
||||||
|
int const instance_materials_count);
|
||||||
|
|
||||||
|
void draw_instance_geometries(types::instance_geometry const * const instance_geometries,
|
||||||
|
int const instance_geometries_count);
|
||||||
|
|
||||||
|
void draw_node(int32_t node_index,
|
||||||
|
types::node const & node,
|
||||||
|
instance_types::node const & node_instance);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// called by state::update
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void transfer_transforms(XMMATRIX const & projection,
|
||||||
|
XMMATRIX const & view,
|
||||||
|
int nodes_count,
|
||||||
|
instance_types::node const * const node_instances);
|
||||||
|
};
|
||||||
|
}
|
||||||
410
include/collada/types.h
Normal file
410
include/collada/types.h
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace collada::types {
|
||||||
|
|
||||||
|
struct float2 {
|
||||||
|
float const x;
|
||||||
|
float const y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct float3 {
|
||||||
|
float const x;
|
||||||
|
float const y;
|
||||||
|
float const z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct float4 {
|
||||||
|
float const x;
|
||||||
|
float const y;
|
||||||
|
float const z;
|
||||||
|
float const w;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct float7 {
|
||||||
|
float const a;
|
||||||
|
float const b;
|
||||||
|
float const c;
|
||||||
|
float const d;
|
||||||
|
float const e;
|
||||||
|
float const f;
|
||||||
|
float const g;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct matrix {
|
||||||
|
float const _11, _12, _13, _14;
|
||||||
|
float const _21, _22, _23, _24;
|
||||||
|
float const _31, _32, _33, _34;
|
||||||
|
float const _41, _42, _43, _44;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// geometry
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
enum class input_format {
|
||||||
|
FLOAT1,
|
||||||
|
FLOAT2,
|
||||||
|
FLOAT3,
|
||||||
|
FLOAT4,
|
||||||
|
INT1,
|
||||||
|
INT2,
|
||||||
|
INT3,
|
||||||
|
INT4,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct input_element {
|
||||||
|
char const * const semantic;
|
||||||
|
int const semantic_index;
|
||||||
|
enum input_format const format;
|
||||||
|
};
|
||||||
|
|
||||||
|
// inputs uniqueness is by evaluted pointer
|
||||||
|
struct inputs {
|
||||||
|
input_element const * const elements;
|
||||||
|
int const elements_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct triangles {
|
||||||
|
int const count;
|
||||||
|
int const index_offset;
|
||||||
|
int const inputs_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mesh {
|
||||||
|
// `triangles` must become a union if non-triangles are implemented.
|
||||||
|
// instance_geometry is an index into this array.
|
||||||
|
types::triangles const * triangles;
|
||||||
|
int const triangles_count;
|
||||||
|
|
||||||
|
int const vertex_buffer_offset;
|
||||||
|
int const vertex_buffer_size;
|
||||||
|
|
||||||
|
int const index_buffer_offset;
|
||||||
|
int const index_buffer_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct geometry {
|
||||||
|
types::mesh mesh;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// light
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
enum class light_type {
|
||||||
|
AMBIENT,
|
||||||
|
DIRECTIONAL,
|
||||||
|
POINT,
|
||||||
|
SPOT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct light {
|
||||||
|
light_type type;
|
||||||
|
float3 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// image
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct image {
|
||||||
|
const char * uri;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// effect
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
enum class color_or_texture_type {
|
||||||
|
COLOR,
|
||||||
|
TEXTURE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct texture {
|
||||||
|
int const image_index; // index in to images
|
||||||
|
};
|
||||||
|
|
||||||
|
struct color_or_texture {
|
||||||
|
color_or_texture_type type;
|
||||||
|
union {
|
||||||
|
float4 color;
|
||||||
|
types::texture texture;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct blinn {
|
||||||
|
color_or_texture const emission;
|
||||||
|
color_or_texture const ambient;
|
||||||
|
color_or_texture const diffuse;
|
||||||
|
color_or_texture const specular;
|
||||||
|
float const shininess;
|
||||||
|
color_or_texture const reflective;
|
||||||
|
float const reflectivity;
|
||||||
|
color_or_texture const transparent;
|
||||||
|
float const transparency;
|
||||||
|
float const index_of_refraction;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lambert {
|
||||||
|
color_or_texture const emission;
|
||||||
|
color_or_texture const ambient;
|
||||||
|
color_or_texture const diffuse;
|
||||||
|
color_or_texture const reflective;
|
||||||
|
float const reflectivity;
|
||||||
|
color_or_texture const transparent;
|
||||||
|
float const transparency;
|
||||||
|
float const index_of_refraction;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct phong {
|
||||||
|
color_or_texture const emission;
|
||||||
|
color_or_texture const ambient;
|
||||||
|
color_or_texture const diffuse;
|
||||||
|
color_or_texture const specular;
|
||||||
|
float const shininess;
|
||||||
|
color_or_texture const reflective;
|
||||||
|
float const reflectivity;
|
||||||
|
color_or_texture const transparent;
|
||||||
|
float const transparency;
|
||||||
|
float const index_of_refraction;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct constant {
|
||||||
|
float4 const color;
|
||||||
|
color_or_texture const reflective;
|
||||||
|
float const reflectivity;
|
||||||
|
color_or_texture const transparent;
|
||||||
|
float const transparency;
|
||||||
|
float const index_of_refraction;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class effect_type {
|
||||||
|
BLINN,
|
||||||
|
LAMBERT,
|
||||||
|
PHONG,
|
||||||
|
CONSTANT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct effect {
|
||||||
|
effect_type const type;
|
||||||
|
union {
|
||||||
|
types::blinn const blinn;
|
||||||
|
types::lambert const lambert;
|
||||||
|
types::phong const phong;
|
||||||
|
types::constant const constant;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// node
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct lookat {
|
||||||
|
float3 const eye;
|
||||||
|
float3 const at;
|
||||||
|
float3 const up;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class transform_type {
|
||||||
|
LOOKAT,
|
||||||
|
MATRIX,
|
||||||
|
ROTATE,
|
||||||
|
SCALE,
|
||||||
|
SKEW,
|
||||||
|
TRANSLATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct transform {
|
||||||
|
transform_type const type;
|
||||||
|
union {
|
||||||
|
types::lookat const lookat;
|
||||||
|
types::matrix const matrix;
|
||||||
|
float4 const rotate;
|
||||||
|
float3 const scale;
|
||||||
|
float7 const skew;
|
||||||
|
float3 const translate;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class node_type {
|
||||||
|
JOINT,
|
||||||
|
NODE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct material {
|
||||||
|
types::effect const * const effect;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bind_vertex_input {
|
||||||
|
int input_set; // TEXCOORD semantic input slot
|
||||||
|
};
|
||||||
|
|
||||||
|
struct instance_material {
|
||||||
|
int const element_index; // an index into mesh.triangles
|
||||||
|
types::material const * const material;
|
||||||
|
|
||||||
|
// heavily simplified from collada data model
|
||||||
|
bind_vertex_input const emission;
|
||||||
|
bind_vertex_input const ambient;
|
||||||
|
bind_vertex_input const diffuse;
|
||||||
|
bind_vertex_input const specular;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct instance_geometry {
|
||||||
|
types::geometry const * const geometry;
|
||||||
|
|
||||||
|
instance_material const * const instance_materials;
|
||||||
|
int const instance_materials_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skin {
|
||||||
|
types::geometry const * const geometry; // source
|
||||||
|
|
||||||
|
matrix const bind_shape_matrix; // one per skin
|
||||||
|
matrix const * const inverse_bind_matrices; // one per joint
|
||||||
|
|
||||||
|
int const vertex_buffer_offset;
|
||||||
|
int const vertex_buffer_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct controller {
|
||||||
|
types::skin skin;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct instance_controller {
|
||||||
|
types::controller const * const controller;
|
||||||
|
|
||||||
|
//node const * const skeleton; // a reference to the root of the joint heirarchy
|
||||||
|
|
||||||
|
int const * const joint_node_indices; // one per joint
|
||||||
|
int const joint_count;
|
||||||
|
|
||||||
|
instance_material const * const instance_materials;
|
||||||
|
int const instance_materials_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct instance_light {
|
||||||
|
types::light const * const light;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// animation
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
enum class interpolation {
|
||||||
|
LINEAR,
|
||||||
|
BEZIER,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct source {
|
||||||
|
union {
|
||||||
|
float const * const float_array;
|
||||||
|
enum interpolation const * const interpolation_array;
|
||||||
|
};
|
||||||
|
int const count;
|
||||||
|
int const stride;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sampler {
|
||||||
|
source const input;
|
||||||
|
source const output;
|
||||||
|
source const in_tangent;
|
||||||
|
source const out_tangent;
|
||||||
|
source const interpolation;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class target_attribute {
|
||||||
|
A, // alpha color component
|
||||||
|
ANGLE, // euler angle
|
||||||
|
B, // blue color component
|
||||||
|
G, // green color component
|
||||||
|
P, // third texture component
|
||||||
|
Q, // fourth texture component
|
||||||
|
R, // red color component
|
||||||
|
S, // first texture coordinate
|
||||||
|
T, // second texture coordinate
|
||||||
|
TIME, // time in seconds
|
||||||
|
U, // first generic parameter
|
||||||
|
V, // second generic parameter
|
||||||
|
W, // fourth cartesian coordinate
|
||||||
|
X, // first cartesian coordinate
|
||||||
|
Y, // second cartesian coordinate
|
||||||
|
Z, // third cartesian coordinate
|
||||||
|
ALL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct channel {
|
||||||
|
sampler const * const source_sampler;
|
||||||
|
int const target_node_index; // an index into the nodes array
|
||||||
|
int const target_transform_index;
|
||||||
|
types::target_attribute const target_attribute;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct animation {
|
||||||
|
animation const * const animations; // nested animations
|
||||||
|
int const animations_count;
|
||||||
|
|
||||||
|
channels const * const channels;
|
||||||
|
int const channels_count;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct camera {
|
||||||
|
float xfov;
|
||||||
|
float yfov;
|
||||||
|
float znear;
|
||||||
|
float zfar;
|
||||||
|
float aspect_ratio;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// scene
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct node {
|
||||||
|
char const * name;
|
||||||
|
|
||||||
|
int const parent_index;
|
||||||
|
|
||||||
|
node_type const type;
|
||||||
|
|
||||||
|
transform const * const transforms;
|
||||||
|
int const transforms_count;
|
||||||
|
|
||||||
|
instance_geometry const * const instance_geometries;
|
||||||
|
int const instance_geometries_count;
|
||||||
|
|
||||||
|
instance_controller const * const instance_controllers;
|
||||||
|
int const instance_controllers_count;
|
||||||
|
|
||||||
|
instance_light const * const instance_lights;
|
||||||
|
int const instance_lights_count;
|
||||||
|
|
||||||
|
channel const * const * const channels;
|
||||||
|
int const channels_count;
|
||||||
|
|
||||||
|
//node const * const * const nodes;
|
||||||
|
//int const nodes_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct descriptor {
|
||||||
|
// these are only the top-level nodes; nodes may have children
|
||||||
|
node const * const * const nodes;
|
||||||
|
int const nodes_count;
|
||||||
|
|
||||||
|
inputs const * const inputs_list;
|
||||||
|
int const inputs_list_count;
|
||||||
|
|
||||||
|
image const * const * const images;
|
||||||
|
int const images_count;
|
||||||
|
|
||||||
|
//animation const * const animations;
|
||||||
|
//int const animations_count;
|
||||||
|
|
||||||
|
// hmm, this part is not really platform-agnostic:
|
||||||
|
char const * const position_normal_texture_buffer;
|
||||||
|
char const * const joint_weight_buffer;
|
||||||
|
char const * const index_buffer;
|
||||||
|
};
|
||||||
|
}
|
||||||
21
include/shader_data.h
Normal file
21
include/shader_data.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "directxmath/directxmath.h"
|
||||||
|
|
||||||
|
constexpr uint32_t maxFramesInFlight{ 2 };
|
||||||
|
|
||||||
|
struct ShaderData {
|
||||||
|
XMFLOAT4X4 projection;
|
||||||
|
XMFLOAT4X4 modelView[16];
|
||||||
|
XMFLOAT4 lightPosition;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ShaderDataDevice {
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
VkDeviceAddress stride;
|
||||||
|
void * mappedData;
|
||||||
|
struct {
|
||||||
|
VkBuffer buffer{ VK_NULL_HANDLE };
|
||||||
|
VkDeviceAddress deviceAddress{};
|
||||||
|
} frame[maxFramesInFlight];
|
||||||
|
};
|
||||||
18
include/vulkan_helper.h
Normal file
18
include/vulkan_helper.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
inline static constexpr VkDeviceSize roundAlignment(VkDeviceSize offset, VkDeviceSize alignment)
|
||||||
|
{
|
||||||
|
// must be a power of two
|
||||||
|
assert(alignment && ((alignment & (alignment - 1)) == 0));
|
||||||
|
return (offset + (alignment - 1)) & (-alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDeviceSize allocateFromMemoryRequirements(VkDevice device,
|
||||||
|
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
|
||||||
|
VkMemoryRequirements const & memoryRequirements,
|
||||||
|
VkMemoryPropertyFlags memoryPropertyFlags,
|
||||||
|
VkMemoryAllocateFlags memoryAllocateFlags,
|
||||||
|
uint32_t count,
|
||||||
|
VkDeviceMemory * memory);
|
||||||
66
shader/collada.hlsl
Normal file
66
shader/collada.hlsl
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
struct VSInput
|
||||||
|
{
|
||||||
|
float3 Position : POSITION0;
|
||||||
|
float3 Normal : NORMAL0;
|
||||||
|
float3 Texture : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VSOutput
|
||||||
|
{
|
||||||
|
float4 Position : SV_POSITION;
|
||||||
|
float3 Normal : NORMAL0;
|
||||||
|
float2 Texture : TEXCOORD0;
|
||||||
|
float3 LightDirection : NORMAL1;
|
||||||
|
float3 ViewDirection : NORMAL2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ShaderData
|
||||||
|
{
|
||||||
|
column_major float4x4 Projection;
|
||||||
|
column_major float4x4 ModelView[16];
|
||||||
|
float4 LightPosition; // view space
|
||||||
|
};
|
||||||
|
|
||||||
|
[[vk::binding(0, 0)]] ConstantBuffer<ShaderData> data;
|
||||||
|
|
||||||
|
struct PushConstant {
|
||||||
|
int ModelViewIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[vk::push_constant]]
|
||||||
|
struct PushConstant constants;
|
||||||
|
|
||||||
|
[shader("vertex")]
|
||||||
|
VSOutput VSMain(VSInput input)
|
||||||
|
{
|
||||||
|
float4x4 modelView = data.ModelView[constants.ModelViewIndex];
|
||||||
|
|
||||||
|
VSOutput output = (VSOutput)0;
|
||||||
|
output.Position = mul(data.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.ViewDirection = -viewPosition.xyz;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[shader("pixel")]
|
||||||
|
float4 PSMain(VSOutput input) : SV_TARGET
|
||||||
|
{
|
||||||
|
//float3 color = texture.Sample(samplers[0], input.Texture).bgr;
|
||||||
|
|
||||||
|
float3 N = normalize(input.Normal);
|
||||||
|
float3 L = normalize(input.LightDirection);
|
||||||
|
float3 V = normalize(input.ViewDirection);
|
||||||
|
float3 R = reflect(-L, N);
|
||||||
|
|
||||||
|
const float a = 16.0;
|
||||||
|
const float specularIntensity = 0.8;
|
||||||
|
float3 specular = pow(max(dot(R, V), 0), a) * specularIntensity;
|
||||||
|
float3 diffuse = max(dot(N, L), 0.001);
|
||||||
|
|
||||||
|
return float4(diffuse + specular, 1.0);
|
||||||
|
}
|
||||||
117
src/collada/node_state.cpp
Normal file
117
src/collada/node_state.cpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "directxmath/directxmath.h"
|
||||||
|
|
||||||
|
#include "new.h"
|
||||||
|
|
||||||
|
#include "collada/node_state.h"
|
||||||
|
|
||||||
|
namespace collada::node_state {
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// transforms
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline static void load_transform(types::transform const & transform,
|
||||||
|
instance_types::transform * instance_transform)
|
||||||
|
{
|
||||||
|
switch (transform.type) {
|
||||||
|
case types::transform_type::LOOKAT:
|
||||||
|
instance_transform->lookat.eye = XMLoadFloat3((XMFLOAT3 *)&transform.lookat.eye);
|
||||||
|
instance_transform->lookat.at = XMLoadFloat3((XMFLOAT3 *)&transform.lookat.at);
|
||||||
|
instance_transform->lookat.up = XMLoadFloat3((XMFLOAT3 *)&transform.lookat.up);
|
||||||
|
break;
|
||||||
|
case types::transform_type::MATRIX:
|
||||||
|
instance_transform->matrix = XMMatrixTranspose(XMLoadFloat4x4((XMFLOAT4X4 *)&transform.matrix));
|
||||||
|
break;
|
||||||
|
case types::transform_type::ROTATE:
|
||||||
|
instance_transform->vector = XMLoadFloat4((XMFLOAT4 *)&transform.rotate);
|
||||||
|
break;
|
||||||
|
case types::transform_type::SCALE:
|
||||||
|
instance_transform->vector = XMLoadFloat3((XMFLOAT3*)&transform.scale);
|
||||||
|
break;
|
||||||
|
case types::transform_type::TRANSLATE:
|
||||||
|
instance_transform->vector = XMLoadFloat3((XMFLOAT3*)&transform.translate);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
instance_transform->type = transform.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void initialize_node_transforms(instance_types::node & node_instance)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < node_instance.node->transforms_count; i++) {
|
||||||
|
load_transform(node_instance.node->transforms[i], &node_instance.transforms[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void allocate_node_instance(instance_types::node & node_instance,
|
||||||
|
types::node const * const node)
|
||||||
|
{
|
||||||
|
node_instance.node = node;
|
||||||
|
node_instance.transforms = NewM<instance_types::transform>(node->transforms_count);
|
||||||
|
|
||||||
|
initialize_node_transforms(node_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void state::allocate_node_instances(types::node const * const * const nodes, int nodes_count)
|
||||||
|
{
|
||||||
|
node_instances = NewM<instance_types::node>(nodes_count);
|
||||||
|
for (int i = 0; i < nodes_count; i++) {
|
||||||
|
allocate_node_instance(node_instances[i], nodes[i]);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < nodes_count; i++) {
|
||||||
|
update_node_world_transform(node_instances[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// world matrix
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline static bool vector_equal(XMVECTOR V1, XMVECTOR V2)
|
||||||
|
{
|
||||||
|
uint32_t CR;
|
||||||
|
XMVectorEqualR(&CR, V1, V2);
|
||||||
|
return XMComparisonAllTrue(CR);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static XMMATRIX transform_matrix(instance_types::transform const& transform)
|
||||||
|
{
|
||||||
|
switch (transform.type) {
|
||||||
|
case types::transform_type::TRANSLATE:
|
||||||
|
return XMMatrixTranslationFromVector(transform.vector);
|
||||||
|
case types::transform_type::ROTATE:
|
||||||
|
//assert(!vector_equal(XMVectorSetW(transform.vector, 0), XMVectorZero()));
|
||||||
|
if (vector_equal(XMVectorSetW(transform.vector, 0), XMVectorZero()))
|
||||||
|
return XMMatrixIdentity();
|
||||||
|
return XMMatrixRotationNormal(transform.vector,
|
||||||
|
XMConvertToRadians(XMVectorGetW(transform.vector)));
|
||||||
|
case types::transform_type::SCALE:
|
||||||
|
return XMMatrixScalingFromVector(transform.vector);
|
||||||
|
case types::transform_type::MATRIX:
|
||||||
|
return transform.matrix;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "unknown transform type %d\n", (int)transform.type);
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void state::update_node_world_transform(instance_types::node & node_instance)
|
||||||
|
{
|
||||||
|
XMMATRIX world;
|
||||||
|
|
||||||
|
if (node_instance.node->parent_index >= 0)
|
||||||
|
world = node_instances[node_instance.node->parent_index].world;
|
||||||
|
else
|
||||||
|
world = XMMatrixIdentity();
|
||||||
|
|
||||||
|
for (int i = 0; i < node_instance.node->transforms_count; i++) {
|
||||||
|
world = transform_matrix(node_instance.transforms[i]) * world;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_instance.world = world;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/collada/scene.cpp
Normal file
50
src/collada/scene.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "collada/scene.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace collada::scene {
|
||||||
|
|
||||||
|
void state::load_scene(types::descriptor const * const descriptor)
|
||||||
|
{
|
||||||
|
this->descriptor = descriptor;
|
||||||
|
|
||||||
|
vulkan.create_pipelines(descriptor);
|
||||||
|
vulkan.load_vertex_index_buffer(descriptor->position_normal_texture_buffer,
|
||||||
|
descriptor->index_buffer);
|
||||||
|
|
||||||
|
node_state.allocate_node_instances(descriptor->nodes, descriptor->nodes_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void state::draw()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < descriptor->nodes_count; i++) {
|
||||||
|
types::node const & node = *descriptor->nodes[i];
|
||||||
|
instance_types::node const & node_instance = node_state.node_instances[i];
|
||||||
|
|
||||||
|
if (node.instance_geometries_count <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vulkan.draw_node(i,
|
||||||
|
node,
|
||||||
|
node_instance);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void state::update(XMMATRIX const & projection,
|
||||||
|
XMMATRIX const & view,
|
||||||
|
float t)
|
||||||
|
{
|
||||||
|
//t = animate::loop(t / 1.0f, 1.0f);
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptor->nodes_count; i++) {
|
||||||
|
//animate::animate_node(node_state.node_instances[i], t);
|
||||||
|
node_state.update_node_world_transform(node_state.node_instances[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vulkan.transfer_transforms(projection,
|
||||||
|
view,
|
||||||
|
descriptor->nodes_count,
|
||||||
|
node_state.node_instances);
|
||||||
|
}
|
||||||
|
}
|
||||||
426
src/collada/scene/vulkan.cpp
Normal file
426
src/collada/scene/vulkan.cpp
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "volk/volk.h"
|
||||||
|
#include "vulkan/vk_enum_string_helper.h"
|
||||||
|
|
||||||
|
#include "collada/inputs.h"
|
||||||
|
#include "collada/scene/vulkan.h"
|
||||||
|
|
||||||
|
#include "vulkan_helper.h"
|
||||||
|
|
||||||
|
#include "check.h"
|
||||||
|
#include "new.h"
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
inline static uint32_t vulkan_semantic_location(char const * const semantic, int semantic_index)
|
||||||
|
{
|
||||||
|
if (strcmp(semantic, "POSITION") == 0 && semantic_index == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (strcmp(semantic, "NORMAL") == 0 && semantic_index == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(semantic, "TEXCOORD") == 0 && semantic_index == 0) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (strcmp(semantic, "BLENDINDICES") == 0 && semantic_index == 0) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (strcmp(semantic, "BLENDWEIGHT") == 0 && semantic_index == 0) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "unknown semantic %s index %d\n", semantic, semantic_index);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static VkFormat vulkan_format(collada::types::input_format format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case collada::types::input_format::FLOAT1: return VK_FORMAT_R32_SFLOAT;
|
||||||
|
case collada::types::input_format::FLOAT2: return VK_FORMAT_R32G32_SFLOAT;
|
||||||
|
case collada::types::input_format::FLOAT3: return VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
|
case collada::types::input_format::FLOAT4: return VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
|
case collada::types::input_format::INT1: return VK_FORMAT_R32_SINT;
|
||||||
|
case collada::types::input_format::INT2: return VK_FORMAT_R32G32_SINT;
|
||||||
|
case collada::types::input_format::INT3: return VK_FORMAT_R32G32B32_SINT;
|
||||||
|
case collada::types::input_format::INT4: return VK_FORMAT_R32G32B32A32_SINT;
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline static uint32_t vulkan_load_layout(collada::types::inputs const & inputs,
|
||||||
|
uint32_t binding,
|
||||||
|
uint32_t start_offset,
|
||||||
|
VkVertexInputAttributeDescription * vertexAttributeDescriptions)
|
||||||
|
{
|
||||||
|
uint32_t offset = start_offset;
|
||||||
|
for (int i = 0; i < inputs.elements_count; i++) {
|
||||||
|
uint32_t location = vulkan_semantic_location(inputs.elements[i].semantic, inputs.elements[i].semantic_index);
|
||||||
|
VkFormat format = vulkan_format(inputs.elements[i].format);
|
||||||
|
vertexAttributeDescriptions[i].location = location;
|
||||||
|
vertexAttributeDescriptions[i].binding = binding;
|
||||||
|
vertexAttributeDescriptions[i].format = format;
|
||||||
|
vertexAttributeDescriptions[i].offset = offset;
|
||||||
|
offset += collada::inputs::format_size(inputs.elements[i].format);
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void vulkan_vertex_input_states(collada::types::descriptor const * const descriptor,
|
||||||
|
VkPipelineVertexInputStateCreateInfo * vertexInputStates,
|
||||||
|
VkVertexInputBindingDescription * vertexBindingDescriptions)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < descriptor->inputs_list_count; i++) {
|
||||||
|
collada::types::inputs const & inputs = descriptor->inputs_list[i];
|
||||||
|
VkVertexInputAttributeDescription * vertexAttributeDescriptions = NewM<VkVertexInputAttributeDescription>(inputs.elements_count);
|
||||||
|
uint32_t stride = vulkan_load_layout(inputs,
|
||||||
|
0, // binding
|
||||||
|
0, // start_offset
|
||||||
|
vertexAttributeDescriptions);
|
||||||
|
|
||||||
|
vertexBindingDescriptions[i] = {
|
||||||
|
.binding = 0,
|
||||||
|
.stride = stride,
|
||||||
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||||
|
};
|
||||||
|
|
||||||
|
vertexInputStates[i] = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
|
.vertexBindingDescriptionCount = 1,
|
||||||
|
.pVertexBindingDescriptions = &vertexBindingDescriptions[i],
|
||||||
|
.vertexAttributeDescriptionCount = (uint32_t)inputs.elements_count,
|
||||||
|
.pVertexAttributeDescriptions = vertexAttributeDescriptions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
this->instance = instance;
|
||||||
|
this->device = device;
|
||||||
|
this->pipelineLayout = pipelineLayout;
|
||||||
|
this->descriptorSetLayout = descriptorSetLayout;
|
||||||
|
|
||||||
|
this->physicalDeviceProperties = physicalDeviceProperties;
|
||||||
|
this->physicalDeviceMemoryProperties = physicalDeviceMemoryProperties;
|
||||||
|
|
||||||
|
this->colorFormat = colorFormat;
|
||||||
|
this->depthFormat = depthFormat;
|
||||||
|
|
||||||
|
this->shaderData = shaderData;
|
||||||
|
this->shaderDataDevice = shaderDataDevice;
|
||||||
|
|
||||||
|
load_shader();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// vertex index buffer
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::load_vertex_index_buffer(char const * vertex_filename,
|
||||||
|
char const * index_filename)
|
||||||
|
{
|
||||||
|
uint32_t vertexSize;
|
||||||
|
void const * vertexStart = file::open(vertex_filename, &vertexSize);
|
||||||
|
uint32_t indexSize;
|
||||||
|
void const * indexStart = file::open(index_filename, &indexSize);
|
||||||
|
|
||||||
|
vertexIndex.indexOffset = vertexSize; // + vertexJWStart;
|
||||||
|
|
||||||
|
// create buffer
|
||||||
|
|
||||||
|
VkDeviceSize bufferSize{ vertexSize + indexSize };
|
||||||
|
VkBufferCreateInfo vertexIndexBufferCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
|
.size = bufferSize,
|
||||||
|
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||||
|
};
|
||||||
|
VK_CHECK(vkCreateBuffer(device, &vertexIndexBufferCreateInfo, nullptr, &vertexIndex.buffer));
|
||||||
|
|
||||||
|
// allocate memory
|
||||||
|
|
||||||
|
VkMemoryRequirements memoryRequirements;
|
||||||
|
vkGetBufferMemoryRequirements(device, vertexIndex.buffer, &memoryRequirements);
|
||||||
|
VkMemoryPropertyFlags memoryPropertyFlags{ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT };
|
||||||
|
VkMemoryAllocateFlags memoryAllocateFlags{};
|
||||||
|
|
||||||
|
allocateFromMemoryRequirements(device,
|
||||||
|
physicalDeviceMemoryProperties,
|
||||||
|
memoryRequirements,
|
||||||
|
memoryPropertyFlags,
|
||||||
|
memoryAllocateFlags,
|
||||||
|
1,
|
||||||
|
&vertexIndex.memory);
|
||||||
|
|
||||||
|
VK_CHECK(vkBindBufferMemory(device, vertexIndex.buffer, vertexIndex.memory, 0));
|
||||||
|
|
||||||
|
// copy data
|
||||||
|
|
||||||
|
void * vertexIndexMappedData;
|
||||||
|
VK_CHECK(vkMapMemory(device, vertexIndex.memory, 0, vertexIndexBufferCreateInfo.size, 0, &vertexIndexMappedData));
|
||||||
|
memcpy((void *)(((ptrdiff_t)vertexIndexMappedData) + 0), vertexStart, vertexSize);
|
||||||
|
memcpy((void *)(((ptrdiff_t)vertexIndexMappedData) + vertexSize), indexStart, indexSize);
|
||||||
|
|
||||||
|
VkMappedMemoryRange mappedMemoryRange{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
|
.memory = vertexIndex.memory,
|
||||||
|
.offset = 0,
|
||||||
|
.size = VK_WHOLE_SIZE,
|
||||||
|
};
|
||||||
|
vkFlushMappedMemoryRanges(device, 1, &mappedMemoryRange);
|
||||||
|
|
||||||
|
vkUnmapMemory(device, vertexIndex.memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// shader
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::load_shader()
|
||||||
|
{
|
||||||
|
uint32_t shaderSize;
|
||||||
|
void const * shaderStart = file::open("shader/collada.spv", &shaderSize);
|
||||||
|
|
||||||
|
VkShaderModuleCreateInfo shaderModuleCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||||
|
.codeSize = shaderSize,
|
||||||
|
.pCode = (uint32_t *)shaderStart
|
||||||
|
};
|
||||||
|
VK_CHECK(vkCreateShaderModule(device, &shaderModuleCreateInfo, nullptr, &shaderModule));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// pipeline
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::create_pipelines(collada::types::descriptor const * const descriptor)
|
||||||
|
{
|
||||||
|
VkPushConstantRange pushConstantRange{
|
||||||
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
.size = (sizeof (int32_t))
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
|
.setLayoutCount = 1,
|
||||||
|
.pSetLayouts = &descriptorSetLayout,
|
||||||
|
.pushConstantRangeCount = 1,
|
||||||
|
.pPushConstantRanges = &pushConstantRange
|
||||||
|
};
|
||||||
|
VK_CHECK(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||||
|
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||||
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineShaderStageCreateInfo shaderStages[2]{
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
.module = shaderModule,
|
||||||
|
.pName = "VSMain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
.module = shaderModule,
|
||||||
|
.pName = "PSMain"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineViewportStateCreateInfo viewportState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
|
.viewportCount = 1,
|
||||||
|
.scissorCount = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr uint32_t dynamicStateCount = 2;
|
||||||
|
VkDynamicState dynamicStates[dynamicStateCount]{
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR,
|
||||||
|
};
|
||||||
|
VkPipelineDynamicStateCreateInfo dynamicState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||||
|
.dynamicStateCount = dynamicStateCount,
|
||||||
|
.pDynamicStates = dynamicStates
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineDepthStencilStateCreateInfo depthStencilState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||||
|
.depthTestEnable = VK_TRUE,
|
||||||
|
.depthWriteEnable = VK_TRUE,
|
||||||
|
.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL,
|
||||||
|
.stencilTestEnable = VK_TRUE,
|
||||||
|
.front = {
|
||||||
|
.failOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.passOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.depthFailOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||||
|
.compareMask = 0x01,
|
||||||
|
.writeMask = 0x01,
|
||||||
|
.reference = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineRenderingCreateInfo renderingCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
||||||
|
.colorAttachmentCount = 1,
|
||||||
|
.pColorAttachmentFormats = &colorFormat,
|
||||||
|
.depthAttachmentFormat = depthFormat,
|
||||||
|
.stencilAttachmentFormat = depthFormat
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineColorBlendAttachmentState blendAttachment{
|
||||||
|
.colorWriteMask = 0xF
|
||||||
|
};
|
||||||
|
VkPipelineColorBlendStateCreateInfo colorBlendState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||||
|
.attachmentCount = 1,
|
||||||
|
.pAttachments = &blendAttachment
|
||||||
|
};
|
||||||
|
VkPipelineRasterizationStateCreateInfo rasterizationState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
.cullMode = VK_CULL_MODE_BACK_BIT,
|
||||||
|
//.cullMode = VK_CULL_MODE_NONE,
|
||||||
|
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||||
|
.lineWidth = 1.0f
|
||||||
|
};
|
||||||
|
VkPipelineMultisampleStateCreateInfo multisampleState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||||
|
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineVertexInputStateCreateInfo * vertexInputStates = NewM<VkPipelineVertexInputStateCreateInfo>(descriptor->inputs_list_count);
|
||||||
|
VkVertexInputBindingDescription * vertexBindingDescriptions = NewM<VkVertexInputBindingDescription>(descriptor->inputs_list_count);
|
||||||
|
vulkan_vertex_input_states(descriptor,
|
||||||
|
vertexInputStates,
|
||||||
|
vertexBindingDescriptions);
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo * pipelineCreateInfos = NewM<VkGraphicsPipelineCreateInfo>(descriptor->inputs_list_count);
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptor->inputs_list_count; i++) {
|
||||||
|
pipelineCreateInfos[i] = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
|
.pNext = &renderingCreateInfo,
|
||||||
|
.stageCount = 2,
|
||||||
|
.pStages = shaderStages,
|
||||||
|
.pVertexInputState = &vertexInputStates[i],
|
||||||
|
.pInputAssemblyState = &inputAssemblyState,
|
||||||
|
.pViewportState = &viewportState,
|
||||||
|
.pRasterizationState = &rasterizationState,
|
||||||
|
.pMultisampleState = &multisampleState,
|
||||||
|
.pDepthStencilState = &depthStencilState,
|
||||||
|
.pColorBlendState = &colorBlendState,
|
||||||
|
.pDynamicState = &dynamicState,
|
||||||
|
.layout = pipelineLayout
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pipelines = NewM<VkPipeline>(descriptor->inputs_list_count);
|
||||||
|
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, descriptor->inputs_list_count, pipelineCreateInfos, nullptr, pipelines));
|
||||||
|
|
||||||
|
free(vertexBindingDescriptions);
|
||||||
|
for (int i = 0; i < descriptor->inputs_list_count; i++) {
|
||||||
|
free((void *)vertexInputStates[i].pVertexAttributeDescriptions);
|
||||||
|
}
|
||||||
|
free(vertexInputStates);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// draw
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::draw_geometry(types::geometry const & geometry,
|
||||||
|
types::instance_material const * const instance_materials,
|
||||||
|
int const instance_materials_count)
|
||||||
|
{
|
||||||
|
types::mesh const& mesh = geometry.mesh;
|
||||||
|
|
||||||
|
vkCmdBindIndexBuffer(commandBuffer, vertexIndex.buffer, vertexIndex.indexOffset + mesh.index_buffer_offset, VK_INDEX_TYPE_UINT32);
|
||||||
|
|
||||||
|
for (int j = 0; j < instance_materials_count; j++) {
|
||||||
|
types::instance_material const& instance_material = instance_materials[j];
|
||||||
|
types::triangles const& triangles = mesh.triangles[instance_material.element_index];
|
||||||
|
|
||||||
|
//set_instance_material(instance_material);
|
||||||
|
|
||||||
|
VkDeviceSize vertexOffset{ (VkDeviceSize)mesh.vertex_buffer_offset };
|
||||||
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndex.buffer, &vertexOffset);
|
||||||
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[triangles.inputs_index]);
|
||||||
|
|
||||||
|
uint32_t indexCount = triangles.count * 3;
|
||||||
|
vkCmdDrawIndexed(commandBuffer, indexCount, 1, triangles.index_offset, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan::draw_instance_geometries(types::instance_geometry const * const instance_geometries,
|
||||||
|
int const instance_geometries_count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < instance_geometries_count; i++) {
|
||||||
|
types::instance_geometry const &instance_geometry = instance_geometries[i];
|
||||||
|
draw_geometry(*instance_geometry.geometry,
|
||||||
|
instance_geometry.instance_materials,
|
||||||
|
instance_geometry.instance_materials_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan::transfer_transforms(XMMATRIX const & projection,
|
||||||
|
XMMATRIX const & view,
|
||||||
|
int nodes_count,
|
||||||
|
instance_types::node const * const node_instances)
|
||||||
|
{
|
||||||
|
// store
|
||||||
|
XMStoreFloat4x4(&shaderData->projection, projection);
|
||||||
|
XMVECTOR lightPosition = XMVector3Transform(XMVectorSet(-42, -40, 156, 0), view);
|
||||||
|
XMStoreFloat4(&shaderData->lightPosition, lightPosition);
|
||||||
|
|
||||||
|
for (int i = 0; i < nodes_count; i++) {
|
||||||
|
XMMATRIX model_view = node_instances[i].world * view;
|
||||||
|
XMStoreFloat4x4(&shaderData->modelView[i], 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);
|
||||||
|
|
||||||
|
// flush
|
||||||
|
|
||||||
|
VkDeviceSize flushSize{ roundAlignment(frameSize, physicalDeviceProperties.limits.nonCoherentAtomSize) };
|
||||||
|
VkMappedMemoryRange shaderDataMemoryRange{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
|
.memory = shaderDataDevice->memory,
|
||||||
|
.offset = frameOffset,
|
||||||
|
.size = flushSize,
|
||||||
|
};
|
||||||
|
vkFlushMappedMemoryRanges(device, 1, &shaderDataMemoryRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan::draw_node(int32_t node_index,
|
||||||
|
types::node const & node,
|
||||||
|
instance_types::node const & node_instance)
|
||||||
|
{
|
||||||
|
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, (sizeof (int32_t)), &node_index);
|
||||||
|
|
||||||
|
draw_instance_geometries(node.instance_geometries, node.instance_geometries_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
275
src/main.cpp
275
src/main.cpp
@ -7,9 +7,17 @@
|
|||||||
#include "SDL3/SDL_vulkan.h"
|
#include "SDL3/SDL_vulkan.h"
|
||||||
#include "directxmath/directxmath.h"
|
#include "directxmath/directxmath.h"
|
||||||
|
|
||||||
|
#include "check.h"
|
||||||
#include "new.h"
|
#include "new.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "dds_validate.h"
|
#include "dds_validate.h"
|
||||||
|
#include "vulkan_helper.h"
|
||||||
|
#include "shader_data.h"
|
||||||
|
|
||||||
|
#include "collada/scene.h"
|
||||||
|
#include "collada/scene/vulkan.h"
|
||||||
|
|
||||||
|
#include "scenes/shadow_test/shadow_test.h"
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline static constexpr T min(T a, T b)
|
inline static constexpr T min(T a, T b)
|
||||||
@ -29,61 +37,6 @@ inline static constexpr T clamp(T n, T minVal, T maxVal)
|
|||||||
return min(max(n, minVal), maxVal);
|
return min(max(n, minVal), maxVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SDL_CHECK(f) \
|
|
||||||
{ \
|
|
||||||
bool result = (f); \
|
|
||||||
if (result != true) { \
|
|
||||||
fprintf(stderr, "SDL: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, SDL_GetError()); \
|
|
||||||
exit(EXIT_FAILURE); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SDL_CHECK_NONNULL(f) \
|
|
||||||
{ \
|
|
||||||
void * ptr = (void *)(f); \
|
|
||||||
if (ptr == nullptr) { \
|
|
||||||
fprintf(stderr, "SDL: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, SDL_GetError()); \
|
|
||||||
exit(EXIT_FAILURE); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VK_CHECK(f) \
|
|
||||||
{ \
|
|
||||||
VkResult result = (f); \
|
|
||||||
if (result != VK_SUCCESS) { \
|
|
||||||
fprintf(stderr, "VK: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, string_VkResult(result)); \
|
|
||||||
exit(EXIT_FAILURE); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VK_CHECK_SWAPCHAIN(f) \
|
|
||||||
{ \
|
|
||||||
VkResult result = (f); \
|
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { \
|
|
||||||
updateSwapchain = true; \
|
|
||||||
} else if (result != VK_SUCCESS) { \
|
|
||||||
fprintf(stderr, "VK: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, string_VkResult(result)); \
|
|
||||||
exit(EXIT_FAILURE); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ASSERT(expr, msg) \
|
|
||||||
{ \
|
|
||||||
bool result = (expr); \
|
|
||||||
if (result != true) { \
|
|
||||||
fprintf(stderr, "%s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, msg); \
|
|
||||||
exit(EXIT_FAILURE); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(__clang__) // MSVC
|
|
||||||
#define UNREACHABLE() __assume(false);
|
|
||||||
#else // GCC, Clang
|
|
||||||
#define UNREACHABLE() __builtin_unreachable();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
constexpr uint32_t maxFramesInFlight{ 2 };
|
|
||||||
|
|
||||||
VkInstance instance{ VK_NULL_HANDLE };
|
VkInstance instance{ VK_NULL_HANDLE };
|
||||||
VkDevice device{ VK_NULL_HANDLE };
|
VkDevice device{ VK_NULL_HANDLE };
|
||||||
VkQueue queue{ VK_NULL_HANDLE };
|
VkQueue queue{ VK_NULL_HANDLE };
|
||||||
@ -131,25 +84,7 @@ VkDescriptorSet textureDescriptorSet{ VK_NULL_HANDLE };
|
|||||||
|
|
||||||
XMINT2 windowSize{};
|
XMINT2 windowSize{};
|
||||||
|
|
||||||
struct ShaderData {
|
|
||||||
XMFLOAT4X4 transform;
|
|
||||||
XMFLOAT4X4 modelView;
|
|
||||||
XMFLOAT4 lightPosition;
|
|
||||||
uint32_t selected;
|
|
||||||
};
|
|
||||||
|
|
||||||
ShaderData shaderData{};
|
ShaderData shaderData{};
|
||||||
|
|
||||||
struct ShaderDataDevice {
|
|
||||||
VkDeviceMemory memory;
|
|
||||||
VkDeviceAddress stride;
|
|
||||||
void * mappedData;
|
|
||||||
struct {
|
|
||||||
VkBuffer buffer{ VK_NULL_HANDLE };
|
|
||||||
VkDeviceAddress deviceAddress{};
|
|
||||||
} frame[maxFramesInFlight];
|
|
||||||
};
|
|
||||||
|
|
||||||
ShaderDataDevice shaderDataDevice{};
|
ShaderDataDevice shaderDataDevice{};
|
||||||
|
|
||||||
void print_memoryPropertyFlags(VkMemoryPropertyFlags propertyFlags)
|
void print_memoryPropertyFlags(VkMemoryPropertyFlags propertyFlags)
|
||||||
@ -167,48 +102,22 @@ void print_memoryPropertyFlags(VkMemoryPropertyFlags propertyFlags)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t findMemoryTypeIndex(VkPhysicalDeviceMemoryProperties const & memoryProperties, uint32_t memoryTypeBits, VkMemoryPropertyFlags propertyFlags)
|
|
||||||
{
|
|
||||||
// find an exact match
|
|
||||||
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
|
|
||||||
if (!(memoryTypeBits & (1u << i)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (memoryProperties.memoryTypes[i].propertyFlags == propertyFlags) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// find a partial match
|
|
||||||
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
|
|
||||||
if (!(memoryTypeBits & (1u << i)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((memoryProperties.memoryTypes[i].propertyFlags & propertyFlags) == propertyFlags) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(false, "no memory type index matching memoryTypeBits and propertyFlags");
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
XMMATRIX currentProjection()
|
XMMATRIX currentProjection()
|
||||||
{
|
{
|
||||||
float fov_angle_y = XMConvertToRadians(45 * 1.0);
|
float fov_angle_y = XMConvertToRadians(45 * 1.0);
|
||||||
float aspect_ratio = (float)windowSize.x / (float)windowSize.y;
|
float aspect_ratio = (float)windowSize.x / (float)windowSize.y;
|
||||||
float near_z = 0.1;
|
float near_z = 0.1;
|
||||||
float far_z = 100.0;
|
float far_z = 1000.0;
|
||||||
XMMATRIX projection = XMMatrixPerspectiveFovRH(fov_angle_y, aspect_ratio, near_z, far_z);
|
XMMATRIX projection = XMMatrixPerspectiveFovLH(fov_angle_y, aspect_ratio, near_z, far_z);
|
||||||
return projection;
|
return projection;
|
||||||
}
|
}
|
||||||
|
|
||||||
XMMATRIX currentView()
|
XMMATRIX currentView()
|
||||||
{
|
{
|
||||||
XMVECTOR eye = XMVectorSet(0, -3, 0, 0);
|
XMVECTOR eye = XMVectorSet(-57, 159, 269, 0);
|
||||||
XMVECTOR at = XMVectorSet(0, 0, 0, 0);
|
XMVECTOR at = XMVectorSet(0, 0, 0, 0);
|
||||||
XMVECTOR up = XMVectorSet(0, 0, 1, 0);
|
XMVECTOR up = XMVectorSet(0, 0, 1, 0);
|
||||||
XMMATRIX view = XMMatrixLookAtRH(eye, at, up);
|
XMMATRIX view = XMMatrixLookAtLH(eye, at, up);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +129,7 @@ XMMATRIX currentModel()
|
|||||||
return XMMatrixTranslation(0, 0, 0.0) * XMMatrixRotationX(theta) * XMMatrixRotationZ(XM_PI * 0.5f);
|
return XMMatrixTranslation(0, 0, 0.0) * XMMatrixRotationX(theta) * XMMatrixRotationZ(XM_PI * 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void recreateSwapchain(VkSurfaceFormatKHR surfaceFormat, VkFormat depthFormat, VkPhysicalDeviceMemoryProperties const & memoryProperties, VkSurfaceCapabilitiesKHR const & surfaceCapabilities)
|
void recreateSwapchain(VkSurfaceFormatKHR surfaceFormat, VkFormat depthFormat, VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties, VkSurfaceCapabilitiesKHR const & surfaceCapabilities)
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// swapchain and images
|
// swapchain and images
|
||||||
@ -339,14 +248,14 @@ void recreateSwapchain(VkSurfaceFormatKHR surfaceFormat, VkFormat depthFormat, V
|
|||||||
VkMemoryPropertyFlags depthImageMemoryPropertyFlags{
|
VkMemoryPropertyFlags depthImageMemoryPropertyFlags{
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||||
};
|
};
|
||||||
uint32_t depthImageMemoryTypeIndex = findMemoryTypeIndex(memoryProperties, depthImageMemoryRequirements.memoryTypeBits, depthImageMemoryPropertyFlags);
|
VkMemoryAllocateFlags depthImageMemoryAllocateFlags{ };
|
||||||
VkMemoryAllocateInfo depthImageAllocateInfo{
|
allocateFromMemoryRequirements(device,
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
physicalDeviceMemoryProperties,
|
||||||
.allocationSize = depthImageMemoryRequirements.size,
|
depthImageMemoryRequirements,
|
||||||
.memoryTypeIndex = depthImageMemoryTypeIndex,
|
depthImageMemoryPropertyFlags,
|
||||||
};
|
depthImageMemoryAllocateFlags,
|
||||||
|
1,
|
||||||
VK_CHECK(vkAllocateMemory(device, &depthImageAllocateInfo, nullptr, &depthImageMemory));
|
&depthImageMemory);
|
||||||
VK_CHECK(vkBindImageMemory(device, depthImage, depthImageMemory, 0));
|
VK_CHECK(vkBindImageMemory(device, depthImage, depthImageMemory, 0));
|
||||||
|
|
||||||
VkImageViewCreateInfo depthViewCreateInfo{
|
VkImageViewCreateInfo depthViewCreateInfo{
|
||||||
@ -363,41 +272,6 @@ void recreateSwapchain(VkSurfaceFormatKHR surfaceFormat, VkFormat depthFormat, V
|
|||||||
VK_CHECK(vkCreateImageView(device, &depthViewCreateInfo, nullptr, &depthImageView));
|
VK_CHECK(vkCreateImageView(device, &depthViewCreateInfo, nullptr, &depthImageView));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static constexpr VkDeviceSize roundAlignment(VkDeviceSize offset, VkDeviceSize alignment)
|
|
||||||
{
|
|
||||||
// must be a power of two
|
|
||||||
assert(alignment && ((alignment & (alignment - 1)) == 0));
|
|
||||||
return (offset + (alignment - 1)) & (-alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDeviceSize allocateFromMemoryRequirements(VkPhysicalDeviceMemoryProperties2 const & physicalDeviceMemoryProperties,
|
|
||||||
VkMemoryRequirements const & memoryRequirements,
|
|
||||||
VkMemoryPropertyFlags memoryPropertyFlags,
|
|
||||||
VkMemoryAllocateFlags memoryAllocateFlags,
|
|
||||||
uint32_t count,
|
|
||||||
VkDeviceMemory * memory)
|
|
||||||
{
|
|
||||||
uint32_t memoryTypeIndex = findMemoryTypeIndex(physicalDeviceMemoryProperties.memoryProperties,
|
|
||||||
memoryRequirements.memoryTypeBits,
|
|
||||||
memoryPropertyFlags);
|
|
||||||
|
|
||||||
VkDeviceSize stride = (count == 1) ? memoryRequirements.size : roundAlignment(memoryRequirements.size, memoryRequirements.alignment);
|
|
||||||
|
|
||||||
VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
|
|
||||||
.flags = memoryAllocateFlags,
|
|
||||||
};
|
|
||||||
VkMemoryAllocateInfo memoryAllocateInfo{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
||||||
.pNext = &memoryAllocateFlagsInfo,
|
|
||||||
.allocationSize = stride * count,
|
|
||||||
.memoryTypeIndex = memoryTypeIndex,
|
|
||||||
};
|
|
||||||
VK_CHECK(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, memory));
|
|
||||||
|
|
||||||
return stride;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int positive_modulo(int i, unsigned int n) {
|
inline static int positive_modulo(int i, unsigned int n) {
|
||||||
return (i % n + n) % n;
|
return (i % n + n) % n;
|
||||||
}
|
}
|
||||||
@ -484,21 +358,21 @@ int main()
|
|||||||
// memory
|
// memory
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
VkPhysicalDeviceMemoryProperties2 physicalDeviceMemoryProperties{
|
VkPhysicalDeviceMemoryProperties2 physicalDeviceMemoryProperties2{
|
||||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2,
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2,
|
||||||
.pNext = nullptr
|
.pNext = nullptr
|
||||||
};
|
};
|
||||||
vkGetPhysicalDeviceMemoryProperties2(physicalDevice, &physicalDeviceMemoryProperties);
|
vkGetPhysicalDeviceMemoryProperties2(physicalDevice, &physicalDeviceMemoryProperties2);
|
||||||
|
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties = physicalDeviceMemoryProperties2.memoryProperties;
|
||||||
if constexpr (true) {
|
if constexpr (true) {
|
||||||
VkPhysicalDeviceMemoryProperties const & memoryProperties = physicalDeviceMemoryProperties.memoryProperties;
|
for (uint32_t i = 0; i < physicalDeviceMemoryProperties.memoryTypeCount; i++) {
|
||||||
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
|
|
||||||
printf("memoryTypes[%u].propertyFlags: ", i);
|
printf("memoryTypes[%u].propertyFlags: ", i);
|
||||||
print_memoryPropertyFlags(memoryProperties.memoryTypes[i].propertyFlags);
|
print_memoryPropertyFlags(physicalDeviceMemoryProperties.memoryTypes[i].propertyFlags);
|
||||||
printf("memoryTypes[%u].heapIndex: %u\n", i, memoryProperties.memoryTypes[i].heapIndex);
|
printf("memoryTypes[%u].heapIndex: %u\n", i, physicalDeviceMemoryProperties.memoryTypes[i].heapIndex);
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < memoryProperties.memoryHeapCount; i++) {
|
for (uint32_t i = 0; i < physicalDeviceMemoryProperties.memoryHeapCount; i++) {
|
||||||
printf("memoryHeaps[%u].size %lu\n", i, memoryProperties.memoryHeaps[i].size);
|
printf("memoryHeaps[%u].size %lu\n", i, physicalDeviceMemoryProperties.memoryHeaps[i].size);
|
||||||
printf("memoryHeaps[%u].flags %08x\n", i, memoryProperties.memoryHeaps[i].flags);
|
printf("memoryHeaps[%u].flags %08x\n", i, physicalDeviceMemoryProperties.memoryHeaps[i].flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,7 +459,7 @@ int main()
|
|||||||
ASSERT(depthFormat != VK_FORMAT_UNDEFINED, "no depth format with VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT");
|
ASSERT(depthFormat != VK_FORMAT_UNDEFINED, "no depth format with VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT");
|
||||||
printf("depthFormat: %s\n", string_VkFormat(depthFormat));
|
printf("depthFormat: %s\n", string_VkFormat(depthFormat));
|
||||||
|
|
||||||
recreateSwapchain(surfaceFormat, depthFormat, physicalDeviceMemoryProperties.memoryProperties, surfaceCapabilities);
|
recreateSwapchain(surfaceFormat, depthFormat, physicalDeviceMemoryProperties, surfaceCapabilities);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// mesh
|
// mesh
|
||||||
@ -613,7 +487,8 @@ int main()
|
|||||||
VkMemoryPropertyFlags memoryPropertyFlags{ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT };
|
VkMemoryPropertyFlags memoryPropertyFlags{ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT };
|
||||||
VkMemoryAllocateFlags memoryAllocateFlags{};
|
VkMemoryAllocateFlags memoryAllocateFlags{};
|
||||||
|
|
||||||
allocateFromMemoryRequirements(physicalDeviceMemoryProperties,
|
allocateFromMemoryRequirements(device,
|
||||||
|
physicalDeviceMemoryProperties,
|
||||||
memoryRequirements,
|
memoryRequirements,
|
||||||
memoryPropertyFlags,
|
memoryPropertyFlags,
|
||||||
memoryAllocateFlags,
|
memoryAllocateFlags,
|
||||||
@ -659,7 +534,8 @@ int main()
|
|||||||
|
|
||||||
VkMemoryPropertyFlags memoryPropertyFlags{ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT };
|
VkMemoryPropertyFlags memoryPropertyFlags{ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT };
|
||||||
VkMemoryAllocateFlags memoryAllocateFlags{ };
|
VkMemoryAllocateFlags memoryAllocateFlags{ };
|
||||||
shaderDataDevice.stride = allocateFromMemoryRequirements(physicalDeviceMemoryProperties,
|
shaderDataDevice.stride = allocateFromMemoryRequirements(device,
|
||||||
|
physicalDeviceMemoryProperties,
|
||||||
memoryRequirements,
|
memoryRequirements,
|
||||||
memoryPropertyFlags,
|
memoryPropertyFlags,
|
||||||
memoryAllocateFlags,
|
memoryAllocateFlags,
|
||||||
@ -748,15 +624,14 @@ int main()
|
|||||||
VkMemoryPropertyFlags textureImageMemoryPropertyFlags{
|
VkMemoryPropertyFlags textureImageMemoryPropertyFlags{
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||||
};
|
};
|
||||||
uint32_t textureImageMemoryTypeIndex = findMemoryTypeIndex(physicalDeviceMemoryProperties.memoryProperties, textureImageMemoryRequirements.memoryTypeBits, textureImageMemoryPropertyFlags);
|
VkMemoryAllocateFlags textureImageMemoryAllocateFlags{ };
|
||||||
|
allocateFromMemoryRequirements(device,
|
||||||
VkMemoryAllocateInfo textureImageAllocateInfo{
|
physicalDeviceMemoryProperties,
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
textureImageMemoryRequirements,
|
||||||
.allocationSize = textureImageMemoryRequirements.size,
|
textureImageMemoryPropertyFlags,
|
||||||
.memoryTypeIndex = textureImageMemoryTypeIndex,
|
textureImageMemoryAllocateFlags,
|
||||||
};
|
1,
|
||||||
|
&textureImageMemory);
|
||||||
VK_CHECK(vkAllocateMemory(device, &textureImageAllocateInfo, nullptr, &textureImageMemory));
|
|
||||||
VK_CHECK(vkBindImageMemory(device, textureImage, textureImageMemory, 0));
|
VK_CHECK(vkBindImageMemory(device, textureImage, textureImageMemory, 0));
|
||||||
|
|
||||||
VkImageViewCreateInfo textureViewCreateInfo{
|
VkImageViewCreateInfo textureViewCreateInfo{
|
||||||
@ -786,14 +661,15 @@ int main()
|
|||||||
VkMemoryPropertyFlags textureSourceBufferMemoryPropertyFlags{
|
VkMemoryPropertyFlags textureSourceBufferMemoryPropertyFlags{
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||||
};
|
};
|
||||||
uint32_t textureSourceBufferMemoryTypeIndex = findMemoryTypeIndex(physicalDeviceMemoryProperties.memoryProperties, textureSourceBufferMemoryRequirements.memoryTypeBits, textureSourceBufferMemoryPropertyFlags);
|
VkMemoryAllocateFlags textureSourceBufferMemoryAllocateFlags{ };
|
||||||
VkMemoryAllocateInfo textureSourceBufferAllocateInfo{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
||||||
.allocationSize = textureSourceBufferMemoryRequirements.size,
|
|
||||||
.memoryTypeIndex = textureSourceBufferMemoryTypeIndex,
|
|
||||||
};
|
|
||||||
VkDeviceMemory textureSourceBufferMemory;
|
VkDeviceMemory textureSourceBufferMemory;
|
||||||
VK_CHECK(vkAllocateMemory(device, &textureSourceBufferAllocateInfo, nullptr, &textureSourceBufferMemory));
|
allocateFromMemoryRequirements(device,
|
||||||
|
physicalDeviceMemoryProperties,
|
||||||
|
textureSourceBufferMemoryRequirements,
|
||||||
|
textureSourceBufferMemoryPropertyFlags,
|
||||||
|
textureSourceBufferMemoryAllocateFlags,
|
||||||
|
1,
|
||||||
|
&textureSourceBufferMemory);
|
||||||
VK_CHECK(vkBindBufferMemory(device, textureSourceBuffer, textureSourceBufferMemory, 0));
|
VK_CHECK(vkBindBufferMemory(device, textureSourceBuffer, textureSourceBufferMemory, 0));
|
||||||
|
|
||||||
void * textureSourceMappedData;
|
void * textureSourceMappedData;
|
||||||
@ -1290,6 +1166,25 @@ int main()
|
|||||||
};
|
};
|
||||||
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 2, pipelineCreateInfos, nullptr, pipelines));
|
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 2, pipelineCreateInfos, nullptr, pipelines));
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// initialize collada
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
collada::scene::state collada_state;
|
||||||
|
|
||||||
|
collada_state.vulkan.initial_state(instance,
|
||||||
|
device,
|
||||||
|
pipelineLayout,
|
||||||
|
uniformBufferDescriptorSetLayout,
|
||||||
|
physicalDeviceProperties,
|
||||||
|
physicalDeviceMemoryProperties,
|
||||||
|
surfaceFormat.format,
|
||||||
|
depthFormat,
|
||||||
|
&shaderData,
|
||||||
|
&shaderDataDevice);
|
||||||
|
|
||||||
|
collada_state.load_scene(&shadow_test::descriptor);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// loop
|
// loop
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -1330,6 +1225,8 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shader data
|
// shader data
|
||||||
|
|
||||||
|
/*
|
||||||
XMMATRIX model = currentModel();
|
XMMATRIX model = currentModel();
|
||||||
XMMATRIX view = currentView();
|
XMMATRIX view = currentView();
|
||||||
XMMATRIX modelView = model * view;
|
XMMATRIX modelView = model * view;
|
||||||
@ -1351,7 +1248,7 @@ int main()
|
|||||||
.size = flushSize,
|
.size = flushSize,
|
||||||
};
|
};
|
||||||
vkFlushMappedMemoryRanges(device, 1, &shaderDataMemoryRange);
|
vkFlushMappedMemoryRanges(device, 1, &shaderDataMemoryRange);
|
||||||
|
*/
|
||||||
|
|
||||||
// wait for fence
|
// wait for fence
|
||||||
VK_CHECK(vkWaitForFences(device, 1, &fences[frameIndex], true, UINT64_MAX));
|
VK_CHECK(vkWaitForFences(device, 1, &fences[frameIndex], true, UINT64_MAX));
|
||||||
@ -1437,6 +1334,8 @@ int main()
|
|||||||
vkCmdBeginRendering(commandBuffer, &renderingInfo);
|
vkCmdBeginRendering(commandBuffer, &renderingInfo);
|
||||||
|
|
||||||
VkViewport viewport{
|
VkViewport viewport{
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,//static_cast<float>(windowSize.y),
|
||||||
.width = static_cast<float>(windowSize.x),
|
.width = static_cast<float>(windowSize.x),
|
||||||
.height = static_cast<float>(windowSize.y),
|
.height = static_cast<float>(windowSize.y),
|
||||||
.minDepth = 0.0f,
|
.minDepth = 0.0f,
|
||||||
@ -1446,12 +1345,13 @@ int main()
|
|||||||
VkRect2D scissor{ .extent{ .width = (uint32_t)windowSize.x, .height = (uint32_t)windowSize.y } };
|
VkRect2D scissor{ .extent{ .width = (uint32_t)windowSize.x, .height = (uint32_t)windowSize.y } };
|
||||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||||
|
|
||||||
VkDeviceSize vertexOffset{ 0 };
|
/*
|
||||||
VkDescriptorSet descriptorSets[2] = {
|
VkDescriptorSet descriptorSets[2] = {
|
||||||
uniformBufferDescriptorSets[frameIndex],
|
uniformBufferDescriptorSets[frameIndex],
|
||||||
textureDescriptorSet,
|
textureDescriptorSet,
|
||||||
};
|
};
|
||||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, descriptorSets, 0, nullptr);
|
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, descriptorSets, 0, nullptr);
|
||||||
|
VkDeviceSize vertexOffset{ 0 };
|
||||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndexBuffer, &vertexOffset);
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndexBuffer, &vertexOffset);
|
||||||
VkDeviceSize indexOffset{ vertexBufferSize };
|
VkDeviceSize indexOffset{ vertexBufferSize };
|
||||||
vkCmdBindIndexBuffer(commandBuffer, vertexIndexBuffer, indexOffset, VK_INDEX_TYPE_UINT32);
|
vkCmdBindIndexBuffer(commandBuffer, vertexIndexBuffer, indexOffset, VK_INDEX_TYPE_UINT32);
|
||||||
@ -1459,10 +1359,25 @@ int main()
|
|||||||
VkDeviceSize indexCount{ 2400 };
|
VkDeviceSize indexCount{ 2400 };
|
||||||
|
|
||||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[MAIN_PIPELINE]);
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[MAIN_PIPELINE]);
|
||||||
vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0);
|
vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0);
|
||||||
|
|
||||||
//vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[OUTLINE_PIPELINE]);
|
//vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[OUTLINE_PIPELINE]);
|
||||||
//vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0);
|
//vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0);
|
||||||
|
*/
|
||||||
|
|
||||||
|
collada_state.vulkan.commandBuffer = commandBuffer;
|
||||||
|
collada_state.vulkan.frameIndex = 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);
|
vkCmdEndRendering(commandBuffer);
|
||||||
|
|
||||||
@ -1520,7 +1435,7 @@ int main()
|
|||||||
updateSwapchain = false;
|
updateSwapchain = false;
|
||||||
VK_CHECK(vkDeviceWaitIdle(device));
|
VK_CHECK(vkDeviceWaitIdle(device));
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfaceCapabilities));
|
VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfaceCapabilities));
|
||||||
recreateSwapchain(surfaceFormat, depthFormat, physicalDeviceMemoryProperties.memoryProperties, surfaceCapabilities);
|
recreateSwapchain(surfaceFormat, depthFormat, physicalDeviceMemoryProperties, surfaceCapabilities);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
64
src/vulkan_helper.cpp
Normal file
64
src/vulkan_helper.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "volk/volk.h"
|
||||||
|
#include "vulkan/vk_enum_string_helper.h"
|
||||||
|
|
||||||
|
#include "check.h"
|
||||||
|
|
||||||
|
#include "vulkan_helper.h"
|
||||||
|
|
||||||
|
inline static uint32_t findMemoryTypeIndex(VkPhysicalDeviceMemoryProperties const & memoryProperties, uint32_t memoryTypeBits, VkMemoryPropertyFlags propertyFlags)
|
||||||
|
{
|
||||||
|
// find an exact match
|
||||||
|
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
|
||||||
|
if (!(memoryTypeBits & (1u << i)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (memoryProperties.memoryTypes[i].propertyFlags == propertyFlags) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find a partial match
|
||||||
|
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
|
||||||
|
if (!(memoryTypeBits & (1u << i)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((memoryProperties.memoryTypes[i].propertyFlags & propertyFlags) == propertyFlags) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(false, "no memory type index matching memoryTypeBits and propertyFlags");
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDeviceSize allocateFromMemoryRequirements(VkDevice device,
|
||||||
|
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
|
||||||
|
VkMemoryRequirements const & memoryRequirements,
|
||||||
|
VkMemoryPropertyFlags memoryPropertyFlags,
|
||||||
|
VkMemoryAllocateFlags memoryAllocateFlags,
|
||||||
|
uint32_t count,
|
||||||
|
VkDeviceMemory * memory)
|
||||||
|
{
|
||||||
|
uint32_t memoryTypeIndex = findMemoryTypeIndex(physicalDeviceMemoryProperties,
|
||||||
|
memoryRequirements.memoryTypeBits,
|
||||||
|
memoryPropertyFlags);
|
||||||
|
|
||||||
|
VkDeviceSize stride = (count == 1) ? memoryRequirements.size : roundAlignment(memoryRequirements.size, memoryRequirements.alignment);
|
||||||
|
|
||||||
|
VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
|
||||||
|
.flags = memoryAllocateFlags,
|
||||||
|
};
|
||||||
|
VkMemoryAllocateInfo memoryAllocateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||||
|
.pNext = &memoryAllocateFlagsInfo,
|
||||||
|
.allocationSize = stride * count,
|
||||||
|
.memoryTypeIndex = memoryTypeIndex,
|
||||||
|
};
|
||||||
|
VK_CHECK(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, memory));
|
||||||
|
|
||||||
|
return stride;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user