minecraft: send view and projection matrices to vertex shader
This commit is contained in:
parent
4cc844addf
commit
46924c8451
2
Makefile
2
Makefile
@ -25,7 +25,7 @@ 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)
|
||||||
|
|||||||
@ -1,12 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "directxmath/directxmath.h"
|
||||||
#include "volk/volk.h"
|
#include "volk/volk.h"
|
||||||
|
|
||||||
#include "minecraft/vulkan/per_world.h"
|
#include "minecraft/vulkan/per_world.h"
|
||||||
|
|
||||||
namespace minecraft::vulkan {
|
namespace minecraft::vulkan {
|
||||||
|
|
||||||
|
struct Scene {
|
||||||
|
XMFLOAT4X4 projection;
|
||||||
|
XMFLOAT4X4 view;
|
||||||
|
XMFLOAT4X4 shadowProjection;
|
||||||
|
XMFLOAT4X4 shadowView;
|
||||||
|
XMFLOAT4 lightPosition;
|
||||||
|
};
|
||||||
|
|
||||||
struct vulkan {
|
struct vulkan {
|
||||||
|
static constexpr uint32_t maxFrames = 2;
|
||||||
|
static constexpr uint32_t perFrameDescriptorCount = 1;
|
||||||
|
static constexpr uint32_t uniformBufferDescriptorCount = maxFrames * perFrameDescriptorCount;
|
||||||
|
static constexpr uint32_t bindingCount = uniformBufferDescriptorCount + 0;
|
||||||
|
|
||||||
|
static constexpr int perVertexSize = (3 + 3 + 2) * 2;
|
||||||
|
static constexpr int perInstanceSize = (3 + 1 + 3 + 1) * 2;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
VkDeviceSize jointWeightOffset;
|
VkDeviceSize jointWeightOffset;
|
||||||
VkDeviceSize indexOffset;
|
VkDeviceSize indexOffset;
|
||||||
@ -35,8 +52,22 @@ namespace minecraft::vulkan {
|
|||||||
|
|
||||||
per_world * worlds;
|
per_world * worlds;
|
||||||
|
|
||||||
static constexpr int perVertexSize = (3 + 3 + 2) * 2;
|
VkDescriptorPool descriptorPool{ VK_NULL_HANDLE };
|
||||||
static constexpr int perInstanceSize = (3 + 1 + 3 + 1) * 2;
|
|
||||||
|
VkDescriptorSetLayout descriptorSetLayouts[1]; // unrelated to maxFrames, unrelated to descriptorCount
|
||||||
|
VkDescriptorSet descriptorSets0[maxFrames];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
VkDeviceSize memorySize;
|
||||||
|
void * mappedData;
|
||||||
|
struct { // must match perFrameDescriptorCount
|
||||||
|
VkBuffer sceneBuffer;
|
||||||
|
VkDeviceAddress sceneOffset;
|
||||||
|
VkDeviceAddress sceneSize;
|
||||||
|
Scene * sceneMapped;
|
||||||
|
} frame[maxFrames];
|
||||||
|
} shaderDataDevice;
|
||||||
|
|
||||||
void initial_state(VkInstance instance,
|
void initial_state(VkInstance instance,
|
||||||
VkDevice device,
|
VkDevice device,
|
||||||
@ -52,6 +83,14 @@ namespace minecraft::vulkan {
|
|||||||
void load_shader();
|
void load_shader();
|
||||||
void create_pipeline();
|
void create_pipeline();
|
||||||
void load_worlds();
|
void load_worlds();
|
||||||
void draw(VkCommandBuffer commandBuffer);
|
void create_uniform_buffers();
|
||||||
|
void create_descriptor_sets();
|
||||||
|
void write_descriptor_sets();
|
||||||
|
void transfer_transforms(XMMATRIX const & projection,
|
||||||
|
XMMATRIX const & view,
|
||||||
|
uint32_t frameIndex);
|
||||||
|
|
||||||
|
void draw(VkCommandBuffer commandBuffer,
|
||||||
|
uint32_t frameIndex);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,11 +16,24 @@ struct VSOutput
|
|||||||
float4 Position : SV_POSITION;
|
float4 Position : SV_POSITION;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Scene
|
||||||
|
{
|
||||||
|
column_major float4x4 Projection;
|
||||||
|
column_major float4x4 View;
|
||||||
|
column_major float4x4 ShadowProjection;
|
||||||
|
column_major float4x4 ShadowView;
|
||||||
|
float4 LightPosition; // view space
|
||||||
|
};
|
||||||
|
|
||||||
|
// set 0: per-frame
|
||||||
|
[[vk::binding(0, 0)]] ConstantBuffer<Scene> Scene;
|
||||||
|
|
||||||
[shader("vertex")]
|
[shader("vertex")]
|
||||||
VSOutput VSMain(VSInput input)
|
VSOutput VSMain(VSInput input)
|
||||||
{
|
{
|
||||||
VSOutput output = (VSOutput)0;
|
VSOutput output = (VSOutput)0;
|
||||||
output.Position = float4(input.Position.xyz + input.BlockPosition, 1.0);
|
float4 Position = float4(input.Position.xyz + input.BlockPosition, 1.0);
|
||||||
|
output.Position = mul(Scene.Projection, mul(Scene.View, Position));
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -722,6 +722,12 @@ int main()
|
|||||||
lightPositionWorld,
|
lightPositionWorld,
|
||||||
collada_state.descriptor->nodes_count,
|
collada_state.descriptor->nodes_count,
|
||||||
collada_state.node_state.node_instances);
|
collada_state.node_state.node_instances);
|
||||||
|
|
||||||
|
// minecraft
|
||||||
|
|
||||||
|
minecraft_state.transfer_transforms(projection,
|
||||||
|
view,
|
||||||
|
frameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -922,7 +928,7 @@ int main()
|
|||||||
//collada_state.vulkan.pipelineIndex = 2; // geometry shader pipeline
|
//collada_state.vulkan.pipelineIndex = 2; // geometry shader pipeline
|
||||||
//collada_state.draw();
|
//collada_state.draw();
|
||||||
|
|
||||||
minecraft_state.draw(commandBuffer);
|
minecraft_state.draw(commandBuffer, frameIndex);
|
||||||
|
|
||||||
vkCmdEndRendering(commandBuffer);
|
vkCmdEndRendering(commandBuffer);
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,9 @@ namespace minecraft::vulkan {
|
|||||||
{
|
{
|
||||||
load_vertex_index_buffer("data/minecraft/per_vertex.vtx", "data/minecraft/configuration.idx");
|
load_vertex_index_buffer("data/minecraft/per_vertex.vtx", "data/minecraft/configuration.idx");
|
||||||
load_shader();
|
load_shader();
|
||||||
|
create_uniform_buffers();
|
||||||
|
create_descriptor_sets();
|
||||||
|
write_descriptor_sets();
|
||||||
create_pipeline();
|
create_pipeline();
|
||||||
load_worlds();
|
load_worlds();
|
||||||
}
|
}
|
||||||
@ -139,8 +142,8 @@ namespace minecraft::vulkan {
|
|||||||
{
|
{
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
|
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
//.setLayoutCount = 2,
|
.setLayoutCount = 1,
|
||||||
//.pSetLayouts = descriptorSetLayouts,
|
.pSetLayouts = descriptorSetLayouts,
|
||||||
//.pushConstantRangeCount = 0,
|
//.pushConstantRangeCount = 0,
|
||||||
//.pPushConstantRanges = nullptr
|
//.pPushConstantRanges = nullptr
|
||||||
};
|
};
|
||||||
@ -332,6 +335,150 @@ namespace minecraft::vulkan {
|
|||||||
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, pipelineCreateInfos, nullptr, &pipeline));
|
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, pipelineCreateInfos, nullptr, &pipeline));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// uniform buffers
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::create_uniform_buffers()
|
||||||
|
{
|
||||||
|
VkMemoryRequirements memoryRequirements[uniformBufferDescriptorCount];
|
||||||
|
VkDeviceSize offsets[uniformBufferDescriptorCount];
|
||||||
|
|
||||||
|
uint32_t memoryRequirementsIndex = 0;
|
||||||
|
// per-frame
|
||||||
|
for (uint32_t i = 0; i < maxFrames; i++) {
|
||||||
|
VkBufferCreateInfo sceneBufferCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
|
.size = (sizeof (Scene)),
|
||||||
|
.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||||
|
};
|
||||||
|
|
||||||
|
VK_CHECK(vkCreateBuffer(device, &sceneBufferCreateInfo, nullptr, &shaderDataDevice.frame[i].sceneBuffer));
|
||||||
|
vkGetBufferMemoryRequirements(device, shaderDataDevice.frame[i].sceneBuffer, &memoryRequirements[memoryRequirementsIndex++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(memoryRequirementsIndex == uniformBufferDescriptorCount);
|
||||||
|
|
||||||
|
VkMemoryPropertyFlags memoryPropertyFlags{ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT };
|
||||||
|
VkMemoryAllocateFlags memoryAllocateFlags{ };
|
||||||
|
shaderDataDevice.memorySize = allocateFromMemoryRequirements2(device,
|
||||||
|
physicalDeviceProperties.limits.nonCoherentAtomSize,
|
||||||
|
physicalDeviceMemoryProperties,
|
||||||
|
memoryPropertyFlags,
|
||||||
|
memoryAllocateFlags,
|
||||||
|
uniformBufferDescriptorCount,
|
||||||
|
memoryRequirements,
|
||||||
|
&shaderDataDevice.memory,
|
||||||
|
offsets);
|
||||||
|
|
||||||
|
VkDeviceSize offset{ 0 };
|
||||||
|
VkDeviceSize size{ VK_WHOLE_SIZE };
|
||||||
|
VkMemoryMapFlags flags{ 0 };
|
||||||
|
VK_CHECK(vkMapMemory(device, shaderDataDevice.memory, offset, size, flags, &shaderDataDevice.mappedData));
|
||||||
|
|
||||||
|
uint32_t offsetsIndex = 0;
|
||||||
|
// this must match the same order as memoryRequirements
|
||||||
|
for (uint32_t i = 0; i < maxFrames; i++) {
|
||||||
|
shaderDataDevice.frame[i].sceneOffset = offsets[offsetsIndex];
|
||||||
|
shaderDataDevice.frame[i].sceneSize = memoryRequirements[offsetsIndex++].size;
|
||||||
|
shaderDataDevice.frame[i].sceneMapped = (Scene *)(((size_t)shaderDataDevice.mappedData) + shaderDataDevice.frame[i].sceneOffset);
|
||||||
|
VK_CHECK(vkBindBufferMemory(device, shaderDataDevice.frame[i].sceneBuffer, shaderDataDevice.memory, shaderDataDevice.frame[i].sceneOffset));
|
||||||
|
}
|
||||||
|
assert(offsetsIndex == uniformBufferDescriptorCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// descriptor sets
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::create_descriptor_sets()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// pool
|
||||||
|
//
|
||||||
|
constexpr int descriptorPoolSizesCount = 1;
|
||||||
|
VkDescriptorPoolSize descriptorPoolSizes[descriptorPoolSizesCount]{
|
||||||
|
{
|
||||||
|
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.descriptorCount = (maxFrames * 1),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||||
|
.maxSets = maxFrames,
|
||||||
|
.poolSizeCount = descriptorPoolSizesCount,
|
||||||
|
.pPoolSizes = descriptorPoolSizes
|
||||||
|
};
|
||||||
|
VK_CHECK(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool));
|
||||||
|
|
||||||
|
//
|
||||||
|
// uniform buffer descriptor set layout/allocation (set 0, per-frame)
|
||||||
|
//
|
||||||
|
{
|
||||||
|
constexpr int bindingCount = 1;
|
||||||
|
VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[bindingCount]{
|
||||||
|
{
|
||||||
|
.binding = 0,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||||
|
.bindingCount = bindingCount,
|
||||||
|
.pBindings = descriptorSetLayoutBindings
|
||||||
|
};
|
||||||
|
VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayouts[0]));
|
||||||
|
|
||||||
|
VkDescriptorSetLayout setLayouts[maxFrames];
|
||||||
|
for (uint32_t i = 0; i < maxFrames; i++) {
|
||||||
|
setLayouts[i] = descriptorSetLayouts[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||||
|
.descriptorPool = descriptorPool,
|
||||||
|
.descriptorSetCount = maxFrames,
|
||||||
|
.pSetLayouts = setLayouts
|
||||||
|
};
|
||||||
|
VK_CHECK(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, descriptorSets0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// descriptor set writes
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::write_descriptor_sets()
|
||||||
|
{
|
||||||
|
VkWriteDescriptorSet writeDescriptorSets[bindingCount];
|
||||||
|
uint32_t writeIndex = 0;
|
||||||
|
|
||||||
|
VkDescriptorBufferInfo sceneDescriptorBufferInfos[maxFrames];
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < maxFrames; i++) {
|
||||||
|
sceneDescriptorBufferInfos[i] = {
|
||||||
|
.buffer = shaderDataDevice.frame[i].sceneBuffer,
|
||||||
|
.offset = 0,
|
||||||
|
.range = shaderDataDevice.frame[i].sceneSize,
|
||||||
|
};
|
||||||
|
writeDescriptorSets[writeIndex++] = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.dstSet = descriptorSets0[i],
|
||||||
|
.dstBinding = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.pBufferInfo = &sceneDescriptorBufferInfos[i]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(writeIndex == bindingCount);
|
||||||
|
vkUpdateDescriptorSets(device, writeIndex, writeDescriptorSets, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// load worlds
|
// load worlds
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -345,12 +492,50 @@ namespace minecraft::vulkan {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// scene data
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::transfer_transforms(XMMATRIX const & projection,
|
||||||
|
XMMATRIX const & view,
|
||||||
|
uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
XMStoreFloat4x4(&shaderDataDevice.frame[frameIndex].sceneMapped->projection, projection);
|
||||||
|
XMStoreFloat4x4(&shaderDataDevice.frame[frameIndex].sceneMapped->view, view);
|
||||||
|
|
||||||
|
// flush
|
||||||
|
constexpr int mappedMemoryRangesCount = 1;
|
||||||
|
VkMappedMemoryRange mappedMemoryRanges[mappedMemoryRangesCount]{
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
|
.memory = shaderDataDevice.memory,
|
||||||
|
.offset = shaderDataDevice.frame[frameIndex].sceneOffset,
|
||||||
|
.size = shaderDataDevice.frame[frameIndex].sceneSize,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
alignMappedMemoryRanges(physicalDeviceProperties.limits.nonCoherentAtomSize,
|
||||||
|
shaderDataDevice.memorySize,
|
||||||
|
mappedMemoryRangesCount,
|
||||||
|
mappedMemoryRanges);
|
||||||
|
vkFlushMappedMemoryRanges(device, mappedMemoryRangesCount, mappedMemoryRanges);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// draw
|
// draw
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void vulkan::draw(VkCommandBuffer commandBuffer)
|
void vulkan::draw(VkCommandBuffer commandBuffer,
|
||||||
|
uint32_t frameIndex)
|
||||||
{
|
{
|
||||||
|
VkDescriptorSet descriptorSets[2] = {
|
||||||
|
descriptorSets0[frameIndex],
|
||||||
|
};
|
||||||
|
vkCmdBindDescriptorSets(commandBuffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
pipelineLayout,
|
||||||
|
0, 1, descriptorSets,
|
||||||
|
0, nullptr);
|
||||||
|
|
||||||
vkCmdBindIndexBuffer(commandBuffer, vertexIndex.buffer, vertexIndex.indexOffset, VK_INDEX_TYPE_UINT16);
|
vkCmdBindIndexBuffer(commandBuffer, vertexIndex.buffer, vertexIndex.indexOffset, VK_INDEX_TYPE_UINT16);
|
||||||
VkBuffer vertexBuffers[2]{
|
VkBuffer vertexBuffers[2]{
|
||||||
vertexIndex.buffer,
|
vertexIndex.buffer,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user