font: render font texture

This commit is contained in:
Zack Buhman 2026-05-20 19:12:09 -05:00
parent 51167365d5
commit 4042bbd623
12 changed files with 777 additions and 59 deletions

View File

@ -53,7 +53,8 @@ OBJS = \
src/minecraft/world.o \
src/minecraft/entry_table.o \
src/minecraft/vulkan.o \
src/minecraft/vulkan/per_world.o
src/minecraft/vulkan/per_world.o \
src/font/outline.o
WORLDS = \
data/minecraft/midnightmeadow/inthash.o \

Binary file not shown.

View File

@ -35,3 +35,6 @@ data/minecraft/midnightmeadow/global.dump
data/minecraft/midnightmeadow/global.lights.vtx
data/minecraft/terrain2.dds
shader/font.spv
data/font/outline/uncial_antiqua_36.data

79
include/font/outline.h Normal file
View File

@ -0,0 +1,79 @@
#pragma once
#include "outline_types.h"
#include "vulkan_helper.h"
namespace font::outline {
struct font_desc {
char const * const path;
};
font_desc const uncial_antiqua[] = {
{
.path = "data/font/outline/uncial_antiqua_36.data",
},
};
int const uncial_antiqua_length = (sizeof (uncial_antiqua)) / (sizeof (font_desc));
struct AllocatedImage {
VkImage image;
VkDeviceMemory memory;
VkImageView imageView;
};
struct LoadedFont {
types::font * font;
types::glyph * glyphs;
AllocatedImage allocatedImage;
};
struct font {
static constexpr int perVertexSize = (4) * 2;
static constexpr int perInstanceSize = (0) * 2;
VkInstance instance;
VkDevice device;
VkQueue queue;
VkCommandPool commandPool;
VkPhysicalDeviceProperties physicalDeviceProperties;
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties;
VkFormat colorFormat;
VkFormat depthFormat;
VkSampler linearSampler;
// font-specific state
VkPipelineLayout pipelineLayout;
VkShaderModule shaderModule;
VkPipeline pipeline;
VertexIndex vertexIndex;
LoadedFont loadedFont;
VkDescriptorPool descriptorPool{ VK_NULL_HANDLE };
static constexpr int descriptorSetLayoutCount = 1;
VkDescriptorSetLayout descriptorSetLayouts[descriptorSetLayoutCount]; // unrelated to maxFrames, unrelated to descriptorCount
VkDescriptorSet descriptorSet0;
void initial_state(VkInstance instance,
VkDevice device,
VkQueue queue,
VkCommandPool commandPool,
VkPhysicalDeviceProperties physicalDeviceProperties,
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties,
VkFormat colorFormat,
VkFormat depthFormat,
VkSampler linearSampler);
void init();
void load_vertex_index_buffer();
void load_shader();
void create_descriptor_sets();
void write_descriptor_sets(VkImageView fontImageView);
void create_pipeline();
void draw(VkCommandBuffer commandBuffer,
uint32_t frameIndex);
LoadedFont load_font(font_desc const& desc);
};
}

View File

@ -0,0 +1,49 @@
// this file is designed to be platform-agnostic
#pragma once
#include <stdint.h>
namespace font::outline::types {
// metrics are 26.6 fixed point
struct glyph_metrics {
int32_t horiBearingX;
int32_t horiBearingY;
int32_t horiAdvance;
};
static_assert((sizeof (struct glyph_metrics)) == ((sizeof (int32_t)) * 3));
struct glyph_bitmap {
uint16_t x;
uint16_t y;
uint16_t width;
uint16_t height;
};
static_assert((sizeof (struct glyph_bitmap)) == ((sizeof (uint16_t)) * 4));
struct glyph {
struct glyph_bitmap bitmap;
struct glyph_metrics metrics;
};
static_assert((sizeof (struct glyph)) == ((sizeof (struct glyph_bitmap)) + (sizeof (struct glyph_metrics))));
struct font {
uint32_t first_char_code;
uint32_t last_char_code;
struct face_metrics {
int32_t height; // 26.6 fixed point
int32_t max_advance; // 26.6 fixed point
} face_metrics;
uint16_t glyph_count;
uint16_t _texture_stride;
uint16_t texture_width;
uint16_t texture_height;
uint32_t max_z_curve_ix;
};
static_assert((sizeof (struct font)) == ((sizeof (uint32_t)) * 7));
}

View File

@ -3,6 +3,7 @@
#include "directxmath/directxmath.h"
#include "volk/volk.h"
#include "vulkan_helper.h"
#include "minecraft/vulkan/per_world.h"
namespace minecraft::vulkan {
@ -24,12 +25,7 @@ namespace minecraft::vulkan {
static constexpr int perVertexSize = (3 + 3 + 2) * 2;
static constexpr int perInstanceSize = (3 + 1 + 3 + 1) * 2;
struct {
VkDeviceSize jointWeightOffset;
VkDeviceSize indexOffset;
VkBuffer buffer;
VkDeviceMemory memory;
} vertexIndex;
VertexIndex vertexIndex;
// externally initialized, opaque handle
VkInstance instance;

View File

@ -73,3 +73,42 @@ void createImageFromFilenameTGA(VkDevice device,
VkImage * outImage,
VkDeviceMemory * outMemory,
VkImageView * outImageView);
void createImage(VkDevice device,
VkDeviceSize nonCoherentAtomSize,
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
VkFormat format,
uint32_t width,
uint32_t height,
uint32_t levelCount,
VkImage * outImage,
VkDeviceMemory * outMemory,
VkImageView * outImageView);
void textureTransfer(VkDevice device,
VkQueue queue,
VkCommandBuffer commandBuffer,
VkFence fence,
VkDeviceSize nonCoherentAtomSize,
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
uint32_t imageDataSize,
void * imageData,
VkImage image,
uint32_t width,
uint32_t height,
uint32_t levelCount,
uint32_t * levelOffsets);
struct VertexIndex {
VkDeviceSize indexOffset;
VkBuffer buffer;
VkDeviceMemory memory;
};
VertexIndex createVertexIndexBuffer(VkDevice device,
VkPhysicalDeviceProperties const& physicalDeviceProperties,
VkPhysicalDeviceMemoryProperties const& physicalDeviceMemoryProperties,
void const * vertexStart,
uint32_t vertexSize,
void const * indexStart,
uint32_t indexSize);

32
shader/font.hlsl Normal file
View File

@ -0,0 +1,32 @@
// set 1: constant
[[vk::binding(0, 0)]] SamplerState ClosestSampler;
[[vk::binding(1, 0)]] Texture2D FontTexture;
struct VSInput
{
float2 Position : POSITION0;
float2 Texture : TEXCOORD0;
};
struct VSOutput
{
float4 Position : SV_POSITION;
float2 Texture : NORMAL0;
};
[shader("vertex")]
VSOutput VSMain(VSInput input)
{
VSOutput output = (VSOutput)0;
output.Position = float4(input.Position, 0, 1);
output.Texture = input.Texture;
return output;
}
[shader("pixel")]
float4 PSMain(VSOutput input) : SV_TARGET
{
float4 color = FontTexture.Sample(ClosestSampler, input.Texture);
return float4(color.xxx, 1.0);
}

481
src/font/outline.cpp Normal file
View File

@ -0,0 +1,481 @@
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "volk/volk.h"
#include "vulkan/vk_enum_string_helper.h"
#include "directxmath/directxmath.h"
#include "vulkan_helper.h"
#include "check.h"
#include "file.h"
#include "font/outline.h"
#include "font/outline_types.h"
namespace font::outline {
static const _Float16 vertexData[] = {
// x y u v
(_Float16)-1.0, (_Float16)-1.0, (_Float16)0.0, (_Float16)0.0,
(_Float16)1.0, (_Float16)-1.0, (_Float16)1.0, (_Float16)0.0,
(_Float16)-1.0, (_Float16)1.0, (_Float16)0.0, (_Float16)1.0,
(_Float16)1.0, (_Float16)1.0, (_Float16)1.0, (_Float16)1.0,
};
static const uint32_t vertexSize = (sizeof (vertexData));
static const uint16_t indexData[] = {
0, 1, 2, 3,
};
static const uint32_t indexSize = (sizeof (indexData));
void font::initial_state(VkInstance instance,
VkDevice device,
VkQueue queue,
VkCommandPool commandPool,
VkPhysicalDeviceProperties physicalDeviceProperties,
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties,
VkFormat colorFormat,
VkFormat depthFormat,
VkSampler linearSampler)
{
this->instance = instance;
this->device = device;
this->queue = queue;
this->commandPool = commandPool;
this->physicalDeviceProperties = physicalDeviceProperties;
this->physicalDeviceMemoryProperties = physicalDeviceMemoryProperties;
this->colorFormat = colorFormat;
this->depthFormat = depthFormat;
this->linearSampler = linearSampler;
}
void font::init()
{
load_vertex_index_buffer();
load_shader();
create_descriptor_sets();
loadedFont = load_font(uncial_antiqua[0]);
write_descriptor_sets(loadedFont.allocatedImage.imageView);
create_pipeline();
}
//////////////////////////////////////////////////////////////////////
// vertex index buffer
//////////////////////////////////////////////////////////////////////
void font::load_vertex_index_buffer()
{
void const * vertexStart = (void const *)vertexData;
void const * indexStart = (void const *)indexData;
vertexIndex = createVertexIndexBuffer(device,
physicalDeviceProperties,
physicalDeviceMemoryProperties,
vertexStart, vertexSize,
indexStart, indexSize);
}
//////////////////////////////////////////////////////////////////////
// shader
//////////////////////////////////////////////////////////////////////
void font::load_shader()
{
uint32_t shaderSize;
void const * shaderStart = file::open("shader/font.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 font::create_pipeline()
{
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = descriptorSetLayoutCount,
.pSetLayouts = descriptorSetLayouts,
.pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr
};
VK_CHECK(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState{
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
};
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_FALSE,
.depthWriteEnable = VK_FALSE,
.depthCompareOp = VK_COMPARE_OP_ALWAYS,
.stencilTestEnable = VK_FALSE,
.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,
},
.back = {
.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
};
VkVertexInputBindingDescription vertexBindingDescriptions[2]{
{
.binding = 0,
.stride = perVertexSize,
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
},
{
.binding = 1,
.stride = perInstanceSize,
.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
}
};
VkVertexInputAttributeDescription vertexAttributeDescriptions[2]{
// per-vertex
{ // position
.location = 0,
.binding = 0,
.format = VK_FORMAT_R16G16_SFLOAT,
.offset = 0,
},
{ // texture
.location = 1,
.binding = 0,
.format = VK_FORMAT_R16G16_SFLOAT,
.offset = 4,
},
};
VkPipelineVertexInputStateCreateInfo vertexInputState{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
//.vertexBindingDescriptionCount = 2,
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = vertexBindingDescriptions,
.vertexAttributeDescriptionCount = 2,
.pVertexAttributeDescriptions = vertexAttributeDescriptions,
};
VkGraphicsPipelineCreateInfo pipelineCreateInfos[1]{
{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &renderingCreateInfo,
.stageCount = 2,
.pStages = shaderStages,
.pVertexInputState = &vertexInputState,
.pInputAssemblyState = &inputAssemblyState,
.pViewportState = &viewportState,
.pRasterizationState = &rasterizationState,
.pMultisampleState = &multisampleState,
.pDepthStencilState = &depthStencilState,
.pColorBlendState = &colorBlendState,
.pDynamicState = &dynamicState,
.layout = pipelineLayout
},
};
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, pipelineCreateInfos, nullptr, &pipeline));
}
//////////////////////////////////////////////////////////////////////
// load font
//////////////////////////////////////////////////////////////////////
LoadedFont font::load_font(font_desc const& desc)
{
uint32_t font_data_size;
void const * font_data = file::open(desc.path, &font_data_size);
assert(font_data != nullptr);
types::font * font = (types::font *)font_data;
types::glyph * glyphs = (types::glyph *)(((ptrdiff_t)font_data) + (sizeof (types::font)));
void * texture_data = (void *)(((ptrdiff_t)glyphs) + (sizeof (types::glyph)) * font->glyph_count);
ptrdiff_t font_end = ((ptrdiff_t)font_data) + font_data_size;
int texture_size = font->texture_width * font->texture_height;
assert(font_end - ((ptrdiff_t)texture_data) == texture_size);
// transfer texture
VkCommandBuffer commandBuffer{};
VkCommandBufferAllocateInfo commandBufferAllocateInfo{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = commandPool,
.commandBufferCount = 1
};
VK_CHECK(vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, &commandBuffer));
VkFenceCreateInfo fenceCreateInfo{
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
};
VkFence fence{};
VK_CHECK(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence));
void * imageData = texture_data;
uint32_t imageDataSize = texture_size;
VkFormat format = VK_FORMAT_R8_UNORM;
uint32_t width = font->texture_width;
uint32_t height = font->texture_height;
uint32_t levelCount = 1;
uint32_t levelOffset = 0;
VkImage outImage;
VkDeviceMemory outMemory;
VkImageView outImageView;
createImage(device,
physicalDeviceProperties.limits.nonCoherentAtomSize,
physicalDeviceMemoryProperties,
format,
width,
height,
levelCount,
&outImage,
&outMemory,
&outImageView);
textureTransfer(device,
queue,
commandBuffer,
fence,
physicalDeviceProperties.limits.nonCoherentAtomSize,
physicalDeviceMemoryProperties,
imageDataSize,
imageData,
outImage,
width,
height,
levelCount,
&levelOffset);
vkDestroyFence(device, fence, nullptr);
vkFreeCommandBuffers(device,
commandPool,
1,
&commandBuffer);
// return
return {
.font = font,
.glyphs = glyphs,
.allocatedImage = {
.image = outImage,
.memory = outMemory,
.imageView = outImageView,
},
};
}
//////////////////////////////////////////////////////////////////////
// descriptor sets
//////////////////////////////////////////////////////////////////////
void font::create_descriptor_sets()
{
//
// pool
//
constexpr int descriptorPoolSizesCount = 2;
VkDescriptorPoolSize descriptorPoolSizes[descriptorPoolSizesCount]{
{ // linear sampler
.type = VK_DESCRIPTOR_TYPE_SAMPLER,
.descriptorCount = 1,
},
{
.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.descriptorCount = 1,
}
};
VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.maxSets = 1,
.poolSizeCount = descriptorPoolSizesCount,
.pPoolSizes = descriptorPoolSizes
};
VK_CHECK(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool));
//
// (set 0, constant)
//
{
constexpr int bindingCount = 2;
VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[bindingCount]{
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
},
{ // font image
.binding = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
}
};
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = bindingCount,
.pBindings = descriptorSetLayoutBindings
};
VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayouts[0]));
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = descriptorPool,
.descriptorSetCount = 1,
.pSetLayouts = &descriptorSetLayouts[0]
};
VK_CHECK(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet0));
}
}
//////////////////////////////////////////////////////////////////////
// descriptor set writes
//////////////////////////////////////////////////////////////////////
void font::write_descriptor_sets(VkImageView fontImageView)
{
constexpr uint32_t writeCount = 2;
VkWriteDescriptorSet writeDescriptorSets[writeCount];
uint32_t writeIndex = 0;
// set1 bindings
VkDescriptorImageInfo samplerDescriptorImageInfo = {
.sampler = linearSampler,
};
writeDescriptorSets[writeIndex++] = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSet0,
.dstBinding = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
.pImageInfo = &samplerDescriptorImageInfo
};
VkDescriptorImageInfo terrainDescriptorImageInfo = {
.imageView = fontImageView,
.imageLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL
};
writeDescriptorSets[writeIndex++] = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSet0,
.dstBinding = 1,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.pImageInfo = &terrainDescriptorImageInfo
};
assert(writeIndex == writeCount);
vkUpdateDescriptorSets(device, writeIndex, writeDescriptorSets, 0, nullptr);
}
//////////////////////////////////////////////////////////////////////
// draw
//////////////////////////////////////////////////////////////////////
void font::draw(VkCommandBuffer commandBuffer,
uint32_t frameIndex)
{
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
VkDescriptorSet descriptorSets[1] = {
descriptorSet0,
};
vkCmdBindDescriptorSets(commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout,
0, 1, descriptorSets,
0, nullptr);
vkCmdBindIndexBuffer(commandBuffer, vertexIndex.buffer, vertexIndex.indexOffset, VK_INDEX_TYPE_UINT16);
VkDeviceSize vertexOffset{ 0 };
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndex.buffer, &vertexOffset);
vkCmdDrawIndexed(commandBuffer, 4, 1, 0, 0, 0);
}
}

View File

@ -20,6 +20,7 @@
#include "collada/scene/vulkan.h"
#include "minecraft/vulkan.h"
#include "font/outline.h"
#include "scenes/shadow_test/shadow_test.h"
#include "scenes/eidelwind/eidelwind.h"
@ -678,6 +679,22 @@ int main()
shadowDepthImageViewDepth);
minecraft_state.init();
//////////////////////////////////////////////////////////////////////
// initialize font
//////////////////////////////////////////////////////////////////////
font::outline::font font_state;
font_state.initial_state(instance,
device,
queue,
commandPool,
physicalDeviceProperties,
physicalDeviceMemoryProperties,
surfaceFormat.format,
depthFormat,
textureSamplers[2]);
font_state.init();
//////////////////////////////////////////////////////////////////////
// initialize view
//////////////////////////////////////////////////////////////////////
@ -798,7 +815,7 @@ int main()
// transfer
//////////////////////////////////////////////////////////////////////
{
if (0) {
collada_state.vulkan.change_frame(commandBuffer, frameIndex);
XMMATRIX projection = currentProjection();
@ -901,7 +918,7 @@ int main()
collada_state.vulkan.excludeMaterialIndex = lightMaterialIndex;
collada_state.vulkan.pipelineIndex = 0; // shadow pipeline
collada_state.draw();
//collada_state.draw();
vkCmdEndRendering(commandBuffer);
@ -1022,11 +1039,13 @@ int main()
collada_state.vulkan.excludeMaterialIndex = -1;
collada_state.vulkan.pipelineIndex = 1; // non-shadow pipeline
collada_state.draw();
//collada_state.draw();
//collada_state.vulkan.pipelineIndex = 2; // geometry shader pipeline
//collada_state.draw();
minecraft_state.draw(commandBuffer, frameIndex);
//minecraft_state.draw(commandBuffer, frameIndex);
font_state.draw(commandBuffer, frameIndex);
vkCmdEndRendering(commandBuffer);

View File

@ -72,54 +72,11 @@ namespace minecraft::vulkan {
uint32_t indexSize;
void const * indexStart = file::open(index_filename, &indexSize);
vertexIndex.indexOffset = vertexSize;
// 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{};
VkDeviceSize stride;
allocateFromMemoryRequirements(device,
physicalDeviceProperties.limits.nonCoherentAtomSize,
vertexIndex = createVertexIndexBuffer(device,
physicalDeviceProperties,
physicalDeviceMemoryProperties,
memoryRequirements,
memoryPropertyFlags,
memoryAllocateFlags,
1,
&vertexIndex.memory,
&stride);
VK_CHECK(vkBindBufferMemory(device, vertexIndex.buffer, vertexIndex.memory, 0));
// copy data
void * vertexIndexMappedData;
VK_CHECK(vkMapMemory(device, vertexIndex.memory, 0, VK_WHOLE_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);
vertexStart, vertexSize,
indexStart, indexSize);
}
//////////////////////////////////////////////////////////////////////

View File

@ -418,3 +418,65 @@ void createImageFromFilenameTGA(VkDevice device,
free(imageStart);
}
VertexIndex createVertexIndexBuffer(VkDevice device,
VkPhysicalDeviceProperties const& physicalDeviceProperties,
VkPhysicalDeviceMemoryProperties const& physicalDeviceMemoryProperties,
void const * vertexStart,
uint32_t vertexSize,
void const * indexStart,
uint32_t indexSize)
{
VertexIndex vertexIndex{};
vertexIndex.indexOffset = vertexSize;
// 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{};
VkDeviceSize stride;
allocateFromMemoryRequirements(device,
physicalDeviceProperties.limits.nonCoherentAtomSize,
physicalDeviceMemoryProperties,
memoryRequirements,
memoryPropertyFlags,
memoryAllocateFlags,
1,
&vertexIndex.memory,
&stride);
VK_CHECK(vkBindBufferMemory(device, vertexIndex.buffer, vertexIndex.memory, 0));
// copy data
void * vertexIndexMappedData;
VK_CHECK(vkMapMemory(device, vertexIndex.memory, 0, VK_WHOLE_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);
return vertexIndex;
}