font: render font texture
This commit is contained in:
parent
51167365d5
commit
4042bbd623
3
Makefile
3
Makefile
@ -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 \
|
||||
|
||||
BIN
data/font/outline/uncial_antiqua_36.data
Normal file
BIN
data/font/outline/uncial_antiqua_36.data
Normal file
Binary file not shown.
@ -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
79
include/font/outline.h
Normal 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);
|
||||
};
|
||||
}
|
||||
49
include/font/outline_types.h
Normal file
49
include/font/outline_types.h
Normal 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));
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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
32
shader/font.hlsl
Normal 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
481
src/font/outline.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
27
src/main.cpp
27
src/main.cpp
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user