minecraft: draw world

This is currently off-screen, because no view/projection transform is
sent to the vertex shader.
This commit is contained in:
Zack Buhman 2026-04-30 12:28:57 -05:00
parent 8102ad7870
commit 4cc844addf
28 changed files with 247 additions and 19 deletions

View File

@ -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 \

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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

View File

@ -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);

31
shader/minecraft.hlsl Normal file
View File

@ -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);
}

View File

@ -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

View File

@ -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);
};
}
}

View File

@ -0,0 +1,104 @@
#include <stdio.h>
#include <string.h>
#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<uint32_t>(descriptor->region_count);
void const ** starts = NewM<void const *>(descriptor->region_count);
VkMemoryRequirements * memoryRequirements = NewM<VkMemoryRequirements>(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, &regions[i].vertexBuffer));
vkGetBufferMemoryRequirements(device, regions[i].vertexBuffer, &memoryRequirements[i]);
}
VkDeviceSize * offsets = NewM<VkDeviceSize>(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,
&regionVertexMemory,
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<region>(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);
}
}

View File

@ -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,
},
};