diff --git a/Makefile b/Makefile index a9613ce..e3cc623 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,8 @@ OBJS = \ src/collada/animate.o \ src/minecraft/world.o \ src/minecraft/entry_table.o \ - src/minecraft/vulkan.o + src/minecraft/vulkan.o \ + src/minecraft/vulkan/per_world.o WORLDS = \ data/minecraft/midnightmeadow/inthash.o \ diff --git a/data/minecraft/grandlecturn/global.dump b/data/minecraft/grandlecturn/global.dump new file mode 100644 index 0000000..86cdd15 Binary files /dev/null and b/data/minecraft/grandlecturn/global.dump differ diff --git a/data/minecraft/grandlecturn/global.lights.vtx b/data/minecraft/grandlecturn/global.lights.vtx new file mode 100644 index 0000000..d05f7d6 Binary files /dev/null and b/data/minecraft/grandlecturn/global.lights.vtx differ diff --git a/data/minecraft/grandlecturn/region.-1.-1.instance.cfg b/data/minecraft/grandlecturn/region.-1.-1.instance.cfg new file mode 100644 index 0000000..0353e0a Binary files /dev/null and b/data/minecraft/grandlecturn/region.-1.-1.instance.cfg differ diff --git a/data/minecraft/grandlecturn/region.-1.-1.instance.vtx b/data/minecraft/grandlecturn/region.-1.-1.instance.vtx new file mode 100644 index 0000000..6cb6ee7 Binary files /dev/null and b/data/minecraft/grandlecturn/region.-1.-1.instance.vtx differ diff --git a/data/minecraft/grandlecturn/region.-1.0.instance.cfg b/data/minecraft/grandlecturn/region.-1.0.instance.cfg new file mode 100644 index 0000000..a837a9f Binary files /dev/null and b/data/minecraft/grandlecturn/region.-1.0.instance.cfg differ diff --git a/data/minecraft/grandlecturn/region.-1.0.instance.vtx b/data/minecraft/grandlecturn/region.-1.0.instance.vtx new file mode 100644 index 0000000..b4a2ecf Binary files /dev/null and b/data/minecraft/grandlecturn/region.-1.0.instance.vtx differ diff --git a/data/minecraft/grandlecturn/region.0.-1.instance.cfg b/data/minecraft/grandlecturn/region.0.-1.instance.cfg new file mode 100644 index 0000000..93804bd Binary files /dev/null and b/data/minecraft/grandlecturn/region.0.-1.instance.cfg differ diff --git a/data/minecraft/grandlecturn/region.0.-1.instance.vtx b/data/minecraft/grandlecturn/region.0.-1.instance.vtx new file mode 100644 index 0000000..13e0f57 Binary files /dev/null and b/data/minecraft/grandlecturn/region.0.-1.instance.vtx differ diff --git a/data/minecraft/grandlecturn/region.0.0.instance.cfg b/data/minecraft/grandlecturn/region.0.0.instance.cfg new file mode 100644 index 0000000..bc97ea1 Binary files /dev/null and b/data/minecraft/grandlecturn/region.0.0.instance.cfg differ diff --git a/data/minecraft/grandlecturn/region.0.0.instance.vtx b/data/minecraft/grandlecturn/region.0.0.instance.vtx new file mode 100644 index 0000000..5b8bcf4 Binary files /dev/null and b/data/minecraft/grandlecturn/region.0.0.instance.vtx differ diff --git a/data/minecraft/midnightmeadow/global.dump b/data/minecraft/midnightmeadow/global.dump new file mode 100644 index 0000000..23d26ec Binary files /dev/null and b/data/minecraft/midnightmeadow/global.dump differ diff --git a/data/minecraft/midnightmeadow/global.lights.vtx b/data/minecraft/midnightmeadow/global.lights.vtx new file mode 100644 index 0000000..e69de29 diff --git a/data/minecraft/midnightmeadow/region.-1.-1.instance.cfg b/data/minecraft/midnightmeadow/region.-1.-1.instance.cfg new file mode 100644 index 0000000..20928d3 Binary files /dev/null and b/data/minecraft/midnightmeadow/region.-1.-1.instance.cfg differ diff --git a/data/minecraft/midnightmeadow/region.-1.-1.instance.vtx b/data/minecraft/midnightmeadow/region.-1.-1.instance.vtx new file mode 100644 index 0000000..28be869 Binary files /dev/null and b/data/minecraft/midnightmeadow/region.-1.-1.instance.vtx differ diff --git a/data/minecraft/midnightmeadow/region.-1.0.instance.cfg b/data/minecraft/midnightmeadow/region.-1.0.instance.cfg new file mode 100644 index 0000000..25a1a9b Binary files /dev/null and b/data/minecraft/midnightmeadow/region.-1.0.instance.cfg differ diff --git a/data/minecraft/midnightmeadow/region.-1.0.instance.vtx b/data/minecraft/midnightmeadow/region.-1.0.instance.vtx new file mode 100644 index 0000000..18f75fb Binary files /dev/null and b/data/minecraft/midnightmeadow/region.-1.0.instance.vtx differ diff --git a/data/minecraft/midnightmeadow/region.0.-1.instance.cfg b/data/minecraft/midnightmeadow/region.0.-1.instance.cfg new file mode 100644 index 0000000..bf956c8 Binary files /dev/null and b/data/minecraft/midnightmeadow/region.0.-1.instance.cfg differ diff --git a/data/minecraft/midnightmeadow/region.0.-1.instance.vtx b/data/minecraft/midnightmeadow/region.0.-1.instance.vtx new file mode 100644 index 0000000..238fe9c Binary files /dev/null and b/data/minecraft/midnightmeadow/region.0.-1.instance.vtx differ diff --git a/data/minecraft/midnightmeadow/region.0.0.instance.cfg b/data/minecraft/midnightmeadow/region.0.0.instance.cfg new file mode 100644 index 0000000..4956c3a Binary files /dev/null and b/data/minecraft/midnightmeadow/region.0.0.instance.cfg differ diff --git a/data/minecraft/midnightmeadow/region.0.0.instance.vtx b/data/minecraft/midnightmeadow/region.0.0.instance.vtx new file mode 100644 index 0000000..eb701d6 Binary files /dev/null and b/data/minecraft/midnightmeadow/region.0.0.instance.vtx differ diff --git a/filenames.txt b/filenames.txt index d7b7458..923aef2 100644 --- a/filenames.txt +++ b/filenames.txt @@ -7,3 +7,29 @@ data/scenes/eidelwind/eidelwind.vtx data/scenes/eidelwind/eidelwind.vjw data/scenes/eidelwind/eidelwind.idx data/scenes/eidelwind/images/0_EidelWindTextureTest.dds + +shader/minecraft.spv +data/minecraft/per_vertex.vtx +data/minecraft/configuration.idx + +data/minecraft/grandlecturn/region.0.0.instance.vtx +data/minecraft/grandlecturn/region.-1.0.instance.vtx +data/minecraft/grandlecturn/region.0.-1.instance.vtx +data/minecraft/grandlecturn/region.-1.-1.instance.vtx +data/minecraft/grandlecturn/region.0.0.instance.cfg +data/minecraft/grandlecturn/region.-1.0.instance.cfg +data/minecraft/grandlecturn/region.0.-1.instance.cfg +data/minecraft/grandlecturn/region.-1.-1.instance.cfg +data/minecraft/grandlecturn/global.dump +data/minecraft/grandlecturn/global.lights.vtx + +data/minecraft/midnightmeadow/region.0.0.instance.vtx +data/minecraft/midnightmeadow/region.-1.0.instance.vtx +data/minecraft/midnightmeadow/region.0.-1.instance.vtx +data/minecraft/midnightmeadow/region.-1.-1.instance.vtx +data/minecraft/midnightmeadow/region.0.0.instance.cfg +data/minecraft/midnightmeadow/region.-1.0.instance.cfg +data/minecraft/midnightmeadow/region.0.-1.instance.cfg +data/minecraft/midnightmeadow/region.-1.-1.instance.cfg +data/minecraft/midnightmeadow/global.dump +data/minecraft/midnightmeadow/global.lights.vtx diff --git a/include/minecraft/vulkan.h b/include/minecraft/vulkan.h index a17e1d3..c88fed9 100644 --- a/include/minecraft/vulkan.h +++ b/include/minecraft/vulkan.h @@ -35,6 +35,17 @@ namespace minecraft::vulkan { per_world * worlds; + static constexpr int perVertexSize = (3 + 3 + 2) * 2; + static constexpr int perInstanceSize = (3 + 1 + 3 + 1) * 2; + + void initial_state(VkInstance instance, + VkDevice device, + VkQueue queue, + VkCommandPool commandPool, + VkPhysicalDeviceProperties physicalDeviceProperties, + VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties, + VkFormat colorFormat, + VkFormat depthFormat); void init(); void load_vertex_index_buffer(char const * vertex_filename, char const * index_filename); diff --git a/shader/minecraft.hlsl b/shader/minecraft.hlsl new file mode 100644 index 0000000..ec50a2a --- /dev/null +++ b/shader/minecraft.hlsl @@ -0,0 +1,31 @@ +struct VSInput +{ + float3 Position : POSITION0; + float3 Normal : NORMAL0; + float2 Texture : TEXCOORD0; + // per-instance + int3 BlockPosition : BlockPosition; + int Blockid : BlockID; + int Data : Data; + int TextureID : TextureID; + int Special : Special; +}; + +struct VSOutput +{ + float4 Position : SV_POSITION; +}; + +[shader("vertex")] +VSOutput VSMain(VSInput input) +{ + VSOutput output = (VSOutput)0; + output.Position = float4(input.Position.xyz + input.BlockPosition, 1.0); + return output; +} + +[shader("pixel")] +float4 PSMain(VSOutput input) : SV_TARGET +{ + return float4(1, 0, 0, 1); +} diff --git a/src/main.cpp b/src/main.cpp index 26d1f70..d9d1478 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,8 @@ #include "collada/scene.h" #include "collada/scene/vulkan.h" +#include "minecraft/vulkan.h" + #include "scenes/shadow_test/shadow_test.h" #include "scenes/eidelwind/eidelwind.h" @@ -595,6 +597,21 @@ int main() collada::types::descriptor const * collada_scene_descriptor = &eidelwind::descriptor; collada_state.load_scene(collada_scene_descriptor); + ////////////////////////////////////////////////////////////////////// + // initialize minecraft + ////////////////////////////////////////////////////////////////////// + + minecraft::vulkan::vulkan minecraft_state; + minecraft_state.initial_state(instance, + device, + queue, + commandPool, + physicalDeviceProperties, + physicalDeviceMemoryProperties, + surfaceFormat.format, + depthFormat); + minecraft_state.init(); + ////////////////////////////////////////////////////////////////////// // loop ////////////////////////////////////////////////////////////////////// @@ -905,6 +922,8 @@ int main() //collada_state.vulkan.pipelineIndex = 2; // geometry shader pipeline //collada_state.draw(); + minecraft_state.draw(commandBuffer); + vkCmdEndRendering(commandBuffer); // barrier diff --git a/src/minecraft/vulkan.cpp b/src/minecraft/vulkan.cpp index ff24d75..ae1e7c5 100644 --- a/src/minecraft/vulkan.cpp +++ b/src/minecraft/vulkan.cpp @@ -10,8 +10,10 @@ #include "new.h" #include "popcount.h" -#include "minecraft/vulkan.h" #include "minecraft/data.inc" +#include "minecraft/world.h" +#include "minecraft/vulkan.h" +#include "minecraft/vulkan/per_world.h" namespace minecraft::vulkan { @@ -20,11 +22,33 @@ namespace minecraft::vulkan { return __builtin_popcount(x); } + void vulkan::initial_state(VkInstance instance, + VkDevice device, + VkQueue queue, + VkCommandPool commandPool, + VkPhysicalDeviceProperties physicalDeviceProperties, + VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties, + VkFormat colorFormat, + VkFormat depthFormat) + { + this->instance = instance; + this->device = device; + this->queue = queue; + this->commandPool = commandPool; + + this->physicalDeviceProperties = physicalDeviceProperties; + this->physicalDeviceMemoryProperties = physicalDeviceMemoryProperties; + + this->colorFormat = colorFormat; + this->depthFormat = depthFormat; + } + void vulkan::init() { load_vertex_index_buffer("data/minecraft/per_vertex.vtx", "data/minecraft/configuration.idx"); load_shader(); create_pipeline(); + load_worlds(); } ////////////////////////////////////////////////////////////////////// @@ -213,8 +237,6 @@ namespace minecraft::vulkan { .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT }; - constexpr int perVertexSize = (3 + 3 + 2) * 2; - constexpr int perInstanceSize = (3 + 1 + 3 + 1) * 2; VkVertexInputBindingDescription vertexBindingDescriptions[2]{ { .binding = 0, @@ -330,11 +352,25 @@ namespace minecraft::vulkan { void vulkan::draw(VkCommandBuffer commandBuffer) { vkCmdBindIndexBuffer(commandBuffer, vertexIndex.buffer, vertexIndex.indexOffset, VK_INDEX_TYPE_UINT16); + VkBuffer vertexBuffers[2]{ + vertexIndex.buffer, + worlds[0].regions[0].vertexBuffer, + }; + VkDeviceSize vertexOffsets[2]{ 0, 0 }; + + vkCmdBindVertexBuffers(commandBuffer, 0, 2, vertexBuffers, vertexOffsets); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); for (int configuration = 1; configuration < 64; configuration++) { - int element_count = 6 * popcount(configuration); - int index_offset = 2 * index_buffer_configuration_offsets[configuration]; - int instance_count = worlds[; + int index_count = 6 * popcount(configuration); + int first_index = index_buffer_configuration_offsets[configuration]; + int instance_count = worlds[0].regions[0].instanceCFG[configuration].count; + int first_instance = worlds[0].regions[0].instanceCFG[configuration].offset / perInstanceSize; + + if (instance_count == 0) + continue; + + vkCmdDrawIndexed(commandBuffer, index_count, instance_count, first_index, 0, first_instance); }; } } diff --git a/src/minecraft/vulkan/per_world.cpp b/src/minecraft/vulkan/per_world.cpp new file mode 100644 index 0000000..e96d39c --- /dev/null +++ b/src/minecraft/vulkan/per_world.cpp @@ -0,0 +1,104 @@ +#include +#include + +#include "volk/volk.h" +#include "vulkan/vk_enum_string_helper.h" + +#include "new.h" +#include "file.h" +#include "check.h" +#include "vulkan_helper.h" + +#include "minecraft/vulkan/per_world.h" + +namespace minecraft::vulkan { + + void per_world::load_regions(VkDevice device, + VkPhysicalDeviceProperties const & physicalDeviceProperties, + VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties, + world::descriptor const * const descriptor) + { + uint32_t * sizes = NewM(descriptor->region_count); + void const ** starts = NewM(descriptor->region_count); + + VkMemoryRequirements * memoryRequirements = NewM(descriptor->region_count); + for (int i = 0; i < descriptor->region_count; i++) { + starts[i] = file::open(descriptor->vertex_paths[i].vtx, &sizes[i]); + + VkBufferCreateInfo bufferCreateInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = sizes[i], + .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE + }; + VK_CHECK(vkCreateBuffer(device, &bufferCreateInfo, nullptr, ®ions[i].vertexBuffer)); + vkGetBufferMemoryRequirements(device, regions[i].vertexBuffer, &memoryRequirements[i]); + } + + VkDeviceSize * offsets = NewM(descriptor->region_count); + VkMemoryPropertyFlags memoryPropertyFlags{ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT }; + VkMemoryAllocateFlags memoryAllocateFlags{ }; + allocateFromMemoryRequirements2(device, + physicalDeviceProperties.limits.nonCoherentAtomSize, + physicalDeviceMemoryProperties, + memoryPropertyFlags, + memoryAllocateFlags, + descriptor->region_count, + memoryRequirements, + ®ionVertexMemory, + offsets); + + VkDeviceSize offset{ 0 }; + VkDeviceSize size{ VK_WHOLE_SIZE }; + VkMemoryMapFlags flags{ 0 }; + void * mappedData; + VK_CHECK(vkMapMemory(device, regionVertexMemory, offset, size, flags, &mappedData)); + + for (int i = 0; i < descriptor->region_count; i++) { + VK_CHECK(vkBindBufferMemory(device, regions[i].vertexBuffer, regionVertexMemory, offsets[i])); + void * data = (void *)(((size_t)mappedData) + offsets[i]); + memcpy(data, starts[i], sizes[i]); + } + + VkMappedMemoryRange mappedMemoryRange{ + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = regionVertexMemory, + .offset = 0, + .size = VK_WHOLE_SIZE, + }; + vkFlushMappedMemoryRanges(device, 1, &mappedMemoryRange); + + vkUnmapMemory(device, regionVertexMemory); + + free(offsets); + free(sizes); + free(starts); + + // instance-cfg + for (int i = 0; i < descriptor->region_count; i++) { + uint32_t size; + void const * start = file::open(descriptor->vertex_paths[i].cfg, &size); + assert(size == (world::instance_cfg_length * (sizeof (world::instance_cfg_entry)))); + regions[i].instanceCFG = (world::instance_cfg_entry *)start; + } + } + + void per_world::load(VkDevice device, + VkPhysicalDeviceProperties const & physicalDeviceProperties, + VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties, + world::descriptor const * const descriptor) + { + this->descriptor = descriptor; + regions = NewM(descriptor->region_count); + load_regions(device, + physicalDeviceProperties, + physicalDeviceMemoryProperties, + descriptor); + + // collision data + entry_table::load_entry_table(descriptor->entry_table_path, + &entry_table, + &entry_table_length, + descriptor->hash_func); + } +} diff --git a/src/minecraft/world.cpp b/src/minecraft/world.cpp index 0a97448..a1aa636 100644 --- a/src/minecraft/world.cpp +++ b/src/minecraft/world.cpp @@ -3,17 +3,17 @@ namespace minecraft::world { static vtx_cfg const grandlecturn_vertex_paths[] = { - { "minecraft/grandlecturn/region.0.0.instance.vtx", "minecraft/grandlecturn/region.0.0.instance.cfg" }, - { "minecraft/grandlecturn/region.-1.0.instance.vtx", "minecraft/grandlecturn/region.-1.0.instance.cfg" }, - { "minecraft/grandlecturn/region.0.-1.instance.vtx", "minecraft/grandlecturn/region.0.-1.instance.cfg" }, - { "minecraft/grandlecturn/region.-1.-1.instance.vtx", "minecraft/grandlecturn/region.-1.-1.instance.cfg" }, + { "data/minecraft/grandlecturn/region.0.0.instance.vtx", "data/minecraft/grandlecturn/region.0.0.instance.cfg" }, + { "data/minecraft/grandlecturn/region.-1.0.instance.vtx", "data/minecraft/grandlecturn/region.-1.0.instance.cfg" }, + { "data/minecraft/grandlecturn/region.0.-1.instance.vtx", "data/minecraft/grandlecturn/region.0.-1.instance.cfg" }, + { "data/minecraft/grandlecturn/region.-1.-1.instance.vtx", "data/minecraft/grandlecturn/region.-1.-1.instance.cfg" }, }; static vtx_cfg const midnightmeadow_vertex_paths[] = { - { "minecraft/midnightmeadow/region.0.0.instance.vtx", "minecraft/midnightmeadow/region.0.0.instance.cfg" }, - { "minecraft/midnightmeadow/region.-1.0.instance.vtx", "minecraft/midnightmeadow/region.-1.0.instance.cfg" }, - { "minecraft/midnightmeadow/region.0.-1.instance.vtx", "minecraft/midnightmeadow/region.0.-1.instance.cfg" }, - { "minecraft/midnightmeadow/region.-1.-1.instance.vtx", "minecraft/midnightmeadow/region.-1.-1.instance.cfg" }, + { "data/minecraft/midnightmeadow/region.0.0.instance.vtx", "data/minecraft/midnightmeadow/region.0.0.instance.cfg" }, + { "data/minecraft/midnightmeadow/region.-1.0.instance.vtx", "data/minecraft/midnightmeadow/region.-1.0.instance.cfg" }, + { "data/minecraft/midnightmeadow/region.0.-1.instance.vtx", "data/minecraft/midnightmeadow/region.0.-1.instance.cfg" }, + { "data/minecraft/midnightmeadow/region.-1.-1.instance.vtx", "data/minecraft/midnightmeadow/region.-1.-1.instance.cfg" }, }; descriptor const descriptors[] = { @@ -21,16 +21,16 @@ namespace minecraft::world { { .region_count = 4, .vertex_paths = grandlecturn_vertex_paths, - .entry_table_path = "minecraft/grandlecturn/global.dump", - .lights_path = "minecraft/grandlecturn/global.lights.vtx", + .entry_table_path = "data/minecraft/grandlecturn/global.dump", + .lights_path = "data/minecraft/grandlecturn/global.lights.vtx", .hash_func = grandlecturn_hash, }, //[world_id::MIDNIGHTMEADOW] = { .region_count = 4, .vertex_paths = midnightmeadow_vertex_paths, - .entry_table_path = "minecraft/midnightmeadow/global.dump", - .lights_path = "minecraft/midnightmeadow/global.lights.vtx", + .entry_table_path = "data/minecraft/midnightmeadow/global.dump", + .lights_path = "data/minecraft/midnightmeadow/global.lights.vtx", .hash_func = midnightmeadow_hash, }, };