Vulkan uniform buffer object
This commit is contained in:
parent
c00f3f64a6
commit
87fc0c3f10
BIN
resource/content/shaders/Tris.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Tris.vs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.fs.geo.ins.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.fs.geo.ins.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.fs.geo.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.fs.geo.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.fs.ins.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.fs.ins.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.vs.geo.ins.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.vs.geo.ins.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.vs.geo.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.vs.geo.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.vs.ins.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.vs.ins.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.vs.spv (Stored with Git LFS)
Binary file not shown.
|
@ -1,12 +1,18 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject {
|
||||
mat4 model;
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
} ubo;
|
||||
|
||||
layout(location = 0) in vec2 inPosition;
|
||||
layout(location = 1) in vec3 inColor;
|
||||
|
||||
layout(location = 0) out vec3 fragColor;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(inPosition, 0.0, 1.0);
|
||||
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0);
|
||||
fragColor = inColor;
|
||||
}
|
|
@ -9,6 +9,12 @@ layout (constant_id = 4) const bool BLEND = true;
|
|||
// ...
|
||||
layout (constant_id = 16) const int UNIT_SIZE = 8;
|
||||
|
||||
layout (binding = 0) uniform UniformBufferObject {
|
||||
vec3 FogColor;
|
||||
float FogDepth;
|
||||
|
||||
vec3 LightInvDirection_worldspace;
|
||||
} UBO;
|
||||
layout (binding = 1) uniform sampler2DArray TextureAtlas;
|
||||
layout (binding = 2) uniform sampler2DArray NormalAtlas;
|
||||
layout (binding = 3) uniform sampler2DArray HOSAtlas;
|
||||
|
@ -22,12 +28,6 @@ layout(push_constant) uniform PushConstants {
|
|||
|
||||
vec4 SphereProj;
|
||||
float Curvature;
|
||||
|
||||
//MAYBE: extract
|
||||
vec3 FogColor;
|
||||
float FogDepth;
|
||||
|
||||
vec3 LightInvDirection_worldspace;
|
||||
} Push;
|
||||
|
||||
#ifdef GEOMETRY
|
||||
|
@ -234,7 +234,7 @@ if(PBR) {
|
|||
}
|
||||
if(FOG) {
|
||||
float ratio = exp(vs.Depth * 0.69)-1;
|
||||
color = mix(color, pow(Push.FogColor, vec3(2.2)), clamp(ratio, 0, 1));
|
||||
color = mix(color, pow(UBO.FogColor, vec3(2.2)), clamp(ratio, 0, 1));
|
||||
}
|
||||
color = pow(color, vec3(1.0 / 2.2));
|
||||
if(color.r > 1 || color.g > 1 || color.b > 1) {
|
||||
|
|
|
@ -7,8 +7,15 @@ layout (constant_id = 1) const bool PBR = true;
|
|||
layout (constant_id = 5) const bool DO_CURVATURE = false;
|
||||
layout (constant_id = 6) const bool CURV_DEPTH = true;
|
||||
|
||||
layout (binding = 0) uniform UniformBufferObject {
|
||||
vec3 FogColor;
|
||||
float FogDepth;
|
||||
|
||||
vec3 LightInvDirection_worldspace;
|
||||
} UBO;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat4 Proj;
|
||||
mat4 Proj; //MAYBE: move Proj View to UBO
|
||||
mat4 View;
|
||||
#ifndef INSTANCED
|
||||
mat4 Model;
|
||||
|
@ -16,12 +23,6 @@ layout(push_constant) uniform PushConstants {
|
|||
|
||||
vec4 SphereProj;
|
||||
float Curvature;
|
||||
|
||||
//MAYBE: extract
|
||||
vec3 FogColor;
|
||||
float FogDepth;
|
||||
|
||||
vec3 LightInvDirection_worldspace;
|
||||
} Push;
|
||||
|
||||
layout (location = 0) in vec3 Position_modelspace;
|
||||
|
@ -66,7 +67,7 @@ if(DO_CURVATURE) {
|
|||
gl_Position = Push.Proj * Position_cameraspace;
|
||||
|
||||
if(FOG) {
|
||||
vs.Depth = length(Position_cameraspace.xyz) / Push.FogDepth;
|
||||
vs.Depth = length(Position_cameraspace.xyz) / UBO.FogDepth;
|
||||
}
|
||||
|
||||
vs.Texture = Texture_model;
|
||||
|
@ -81,6 +82,6 @@ if(PBR) {
|
|||
vs.EyeDirection_cameraspace = vec3(0,0,0) - Position_cameraspace.xyz;
|
||||
|
||||
// Vector that goes from the vertex to the light, in camera space
|
||||
vs.LightDirection_cameraspace = (Push.View * vec4(Push.LightInvDirection_worldspace,0)).xyz;
|
||||
vs.LightDirection_cameraspace = (Push.View * vec4(UBO.LightInvDirection_worldspace,0)).xyz;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
#include "PhysicalDeviceInfo.hpp"
|
||||
#include <TracyVulkan.hpp>
|
||||
#include "buffer/VertexData.hpp"
|
||||
#include <memory.h>
|
||||
#include <cassert>
|
||||
|
||||
using namespace render::vk;
|
||||
|
||||
const auto NO_DELETER = Allocator::MemoryDeleter(nullptr);
|
||||
Allocator::memory_ptr get_null_ptr() { return Allocator::memory_ptr(nullptr, NO_DELETER); }
|
||||
Allocator::memory_ptr Allocator::GetNull() { return Allocator::memory_ptr(nullptr, NO_DELETER); }
|
||||
|
||||
Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info) : device(device), indexedBufferMemory(get_null_ptr()) {
|
||||
Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info) : device(device) {
|
||||
vkGetPhysicalDeviceMemoryProperties(info.device, &properties);
|
||||
|
||||
{
|
||||
|
@ -39,39 +39,8 @@ Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info) : device(d
|
|||
vkAllocateCommandBuffers(device, &allocInfo, &transferBuffer);
|
||||
tracyCtx = TracyVkContext(info.device, device, transferQueue, transferBuffer);
|
||||
}
|
||||
{
|
||||
size_t vertexSize = sizeof(buffer::vk::vertices[0]) * buffer::vk::vertices.size();
|
||||
size_t indexSize = sizeof(buffer::vk::indices[0]) * buffer::vk::indices.size();
|
||||
size_t stagingSize = std::max(vertexSize, indexSize);
|
||||
buffer_info stagingBuffer;
|
||||
if(auto stagingMemory = createBuffer(stagingSize, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, stagingBuffer)) {
|
||||
std::vector<buffer_requirement> requirements = {
|
||||
{indexSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT},
|
||||
{vertexSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT}
|
||||
};
|
||||
if(std::vector<buffer_info> out; indexedBufferMemory = createBuffers(requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, out)) {
|
||||
indexBuffer = out[0];
|
||||
vertexBuffer = out[1];
|
||||
} else {
|
||||
FATAL("Cannot allocate buffer memory");
|
||||
}
|
||||
|
||||
stagingMemory->write(buffer::vk::vertices.data(), vertexSize);
|
||||
copyBuffer(stagingBuffer, vertexBuffer, vertexSize);
|
||||
stagingMemory->write(buffer::vk::indices.data(), indexSize);
|
||||
copyBuffer(stagingBuffer, indexBuffer, indexSize);
|
||||
|
||||
vkDestroyBuffer(device, stagingBuffer.buffer, ALLOC); //TODO: move to buffer
|
||||
} else {
|
||||
FATAL("Cannot allocate staging memory");
|
||||
}
|
||||
}
|
||||
}
|
||||
Allocator::~Allocator() {
|
||||
vkDestroyBuffer(device, indexBuffer.buffer, ALLOC);
|
||||
vkDestroyBuffer(device, vertexBuffer.buffer, ALLOC);
|
||||
indexedBufferMemory.reset();
|
||||
|
||||
TracyVkDestroy(tracyCtx);
|
||||
vkFreeCommandBuffers(device, transferPool, 1, &transferBuffer);
|
||||
|
||||
|
@ -94,8 +63,9 @@ Allocator::memory_ptr Allocator::createBuffer(VkDeviceSize size, VkMemoryPropert
|
|||
|
||||
if (vkCreateBuffer(device, &bufferInfo, ALLOC, &out.buffer) != VK_SUCCESS) {
|
||||
LOG_E("Failed to create buffer");
|
||||
return get_null_ptr();
|
||||
return GetNull();
|
||||
}
|
||||
out.offset = 0;
|
||||
|
||||
VkMemoryRequirements memRequirements;
|
||||
vkGetBufferMemoryRequirements(device, out.buffer, &memRequirements);
|
||||
|
@ -105,16 +75,16 @@ Allocator::memory_ptr Allocator::createBuffer(VkDeviceSize size, VkMemoryPropert
|
|||
return memory;
|
||||
}
|
||||
LOG_E("Failed to allocate buffer memory");
|
||||
return get_null_ptr();
|
||||
return GetNull();
|
||||
}
|
||||
Allocator::memory_ptr Allocator::createBuffers(const std::vector<buffer_requirement>& requirements, VkMemoryPropertyFlags properties, std::vector<buffer_info>& out) {
|
||||
assert(!requirements.empty());
|
||||
out.resize(requirements.size());
|
||||
out.resize(requirements.size()+1);
|
||||
|
||||
// Create buffers
|
||||
VkMemoryRequirements memRequirements = {0, 0, UINT32_MAX};
|
||||
std::vector<std::pair<VkDeviceSize, VkDeviceSize>> ranges;
|
||||
ranges.resize(requirements.size());
|
||||
std::vector<VkDeviceSize> sizes;
|
||||
sizes.resize(requirements.size());
|
||||
for (size_t i = 0; i < requirements.size(); i++) {
|
||||
VkBufferCreateInfo bufferInfo{};
|
||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
|
@ -124,14 +94,14 @@ Allocator::memory_ptr Allocator::createBuffers(const std::vector<buffer_requirem
|
|||
|
||||
if (vkCreateBuffer(device, &bufferInfo, ALLOC, &out[i].buffer) != VK_SUCCESS) {
|
||||
LOG_E("Failed to create buffer");
|
||||
return get_null_ptr();
|
||||
return GetNull();
|
||||
}
|
||||
|
||||
VkMemoryRequirements individualMemRequirements;
|
||||
vkGetBufferMemoryRequirements(device, out[i].buffer, &individualMemRequirements);
|
||||
memRequirements.alignment = std::max(memRequirements.alignment, individualMemRequirements.alignment);
|
||||
memRequirements.memoryTypeBits &= individualMemRequirements.memoryTypeBits;
|
||||
ranges[i].first = individualMemRequirements.size;
|
||||
sizes[i] = individualMemRequirements.size;
|
||||
}
|
||||
|
||||
// Align blocks
|
||||
|
@ -140,24 +110,25 @@ Allocator::memory_ptr Allocator::createBuffers(const std::vector<buffer_requirem
|
|||
return offset;
|
||||
return offset + memRequirements.alignment - (offset % memRequirements.alignment);
|
||||
};
|
||||
ranges[0].second = 0;
|
||||
for (size_t i = 1; i < requirements.size(); i++) {
|
||||
ranges[i].second = aligned(ranges[i-1].second + ranges[i-1].first);
|
||||
out[0].offset = 0;
|
||||
for (size_t i = 1; i < out.size(); i++) {
|
||||
out[i].offset = aligned(out[i-1].offset + sizes[i-1]);
|
||||
}
|
||||
memRequirements.size = aligned(ranges.back().second + ranges.back().first);
|
||||
memRequirements.size = out.back().offset;
|
||||
out.pop_back();
|
||||
|
||||
// Bind memory
|
||||
if (auto memory = allocate(memRequirements, properties)) {
|
||||
for (size_t i = 0; i < requirements.size(); i++) {
|
||||
if (vkBindBufferMemory(device, out[i].buffer, memory->ref, memory->offset + ranges[i].second) != VK_SUCCESS) {
|
||||
if (vkBindBufferMemory(device, out[i].buffer, memory->ref, memory->offset + out[i].offset) != VK_SUCCESS) {
|
||||
LOG_E("Failed to bind buffer");
|
||||
return get_null_ptr();
|
||||
return GetNull();
|
||||
}
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
LOG_E("Failed to allocate buffers");
|
||||
return get_null_ptr();
|
||||
return GetNull();
|
||||
}
|
||||
|
||||
Allocator::memory_ptr Allocator::allocate(VkMemoryRequirements requirements, VkMemoryPropertyFlags properties) {
|
||||
|
@ -172,13 +143,13 @@ Allocator::memory_ptr Allocator::allocate(VkMemoryRequirements requirements, VkM
|
|||
allocInfo.memoryTypeIndex = memIdx.value();
|
||||
} else {
|
||||
LOG_E("No suitable memory heap");
|
||||
return get_null_ptr();
|
||||
return GetNull();
|
||||
}
|
||||
|
||||
VkDeviceMemory memory;
|
||||
if (vkAllocateMemory(device, &allocInfo, ALLOC, &memory) != VK_SUCCESS) {
|
||||
LOG_E("Failed to allocate memory!");
|
||||
return get_null_ptr();
|
||||
return GetNull();
|
||||
}
|
||||
|
||||
void *ptr = nullptr;
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
|
||||
struct buffer_info {
|
||||
VkBuffer buffer = nullptr;
|
||||
VkDeviceSize offset = 0;
|
||||
};
|
||||
memory_ptr createBuffer(VkDeviceSize, VkMemoryPropertyFlags, VkBufferUsageFlags, buffer_info&);
|
||||
struct buffer_requirement {
|
||||
|
@ -55,9 +56,10 @@ public:
|
|||
|
||||
void copyBuffer(buffer_info srcBuffer, buffer_info dstBuffer, VkDeviceSize size);
|
||||
|
||||
std::pair<VkBuffer, VkBuffer> getBuffer() { return {vertexBuffer.buffer, indexBuffer.buffer}; }
|
||||
void setTracyZone(const char* name);
|
||||
|
||||
static memory_ptr GetNull();
|
||||
|
||||
private:
|
||||
std::optional<uint32_t> findMemory(uint32_t, VkMemoryPropertyFlags, VkDeviceSize size = 0) const;
|
||||
|
||||
|
@ -84,9 +86,6 @@ private:
|
|||
VkCommandBuffer transferBuffer; // MAYBE: parallel upload
|
||||
TracyVkCtx tracyCtx;
|
||||
|
||||
buffer_info vertexBuffer;
|
||||
buffer_info indexBuffer;
|
||||
memory_ptr indexedBufferMemory;
|
||||
std::vector<std::unique_ptr<Allocation>> allocations;
|
||||
};
|
||||
}
|
|
@ -1,14 +1,16 @@
|
|||
#include "CommandCenter.hpp"
|
||||
|
||||
#include "PhysicalDeviceInfo.hpp"
|
||||
#include "Pipeline.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "buffer/VertexData.hpp"
|
||||
|
||||
using namespace render::vk;
|
||||
|
||||
CommandCenter::CommandCenter(VkDevice device, const std::vector<VkImageView> &views, PipelineRef pipe,
|
||||
std::pair<VkBuffer, VkBuffer> buffer, const PhysicalDeviceInfo &info, const renderOptions &opt) : device(device) {
|
||||
{
|
||||
CommandCenter::CommandCenter(VkDevice device, Allocator& alloc, const std::vector<VkImageView> &views,
|
||||
const Pipeline& pipe, const PhysicalDeviceInfo &info, const renderOptions &opt):
|
||||
device(device), indexedBufferMemory(Allocator::GetNull()), uniformBuffersMemory(Allocator::GetNull()) {
|
||||
{ // Graphics command pool
|
||||
vkGetDeviceQueue(device, info.queueIndices.graphicsFamily.value(), 0, &graphicsQueue);
|
||||
VkCommandPoolCreateInfo poolInfo{};
|
||||
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
|
@ -19,16 +21,47 @@ CommandCenter::CommandCenter(VkDevice device, const std::vector<VkImageView> &vi
|
|||
FATAL("Failed to create graphics pool!");
|
||||
}
|
||||
}
|
||||
{ // Vertex buffers (const)
|
||||
size_t vertexSize = sizeof(buffer::vk::vertices[0]) * buffer::vk::vertices.size();
|
||||
size_t indexSize = sizeof(buffer::vk::indices[0]) * buffer::vk::indices.size();
|
||||
size_t stagingSize = std::max(vertexSize, indexSize);
|
||||
Allocator::buffer_info stagingBuffer;
|
||||
if(auto stagingMemory = alloc.createBuffer(stagingSize, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, stagingBuffer)) {
|
||||
if(std::vector<Allocator::buffer_info> out; indexedBufferMemory = alloc.createBuffers({
|
||||
{indexSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT},
|
||||
{vertexSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT}
|
||||
}, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, out)) {
|
||||
indexBuffer = out[0];
|
||||
vertexBuffer = out[1];
|
||||
} else {
|
||||
FATAL("Cannot allocate buffer memory");
|
||||
}
|
||||
|
||||
allocate(views, pipe, buffer, info.swapDetails.capabilities.currentExtent, opt);
|
||||
stagingMemory->write(buffer::vk::vertices.data(), vertexSize);
|
||||
alloc.copyBuffer(stagingBuffer, vertexBuffer, vertexSize);
|
||||
stagingMemory->write(buffer::vk::indices.data(), indexSize);
|
||||
alloc.copyBuffer(stagingBuffer, indexBuffer, indexSize);
|
||||
|
||||
vkDestroyBuffer(device, stagingBuffer.buffer, ALLOC); //TODO: move to buffer
|
||||
} else {
|
||||
FATAL("Cannot allocate staging memory");
|
||||
}
|
||||
}
|
||||
|
||||
allocate(alloc, views, pipe, info.swapDetails.capabilities.currentExtent, opt);
|
||||
}
|
||||
CommandCenter::~CommandCenter() {
|
||||
if(!freed)
|
||||
free();
|
||||
|
||||
vkDestroyBuffer(device, indexBuffer.buffer, ALLOC);
|
||||
vkDestroyBuffer(device, vertexBuffer.buffer, ALLOC);
|
||||
indexedBufferMemory.reset();
|
||||
|
||||
vkDestroyCommandPool(device, graphicsPool, ALLOC);
|
||||
}
|
||||
void CommandCenter::allocate(const std::vector<VkImageView>& views, PipelineRef pipe, std::pair<VkBuffer, VkBuffer> buffer, VkExtent2D extent,
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
void CommandCenter::allocate(Allocator& alloc, const std::vector<VkImageView>& views, const Pipeline& pipe, VkExtent2D extent,
|
||||
const renderOptions& opt)
|
||||
{
|
||||
assert(freed);
|
||||
|
@ -40,7 +73,7 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, PipelineRef
|
|||
|
||||
VkFramebufferCreateInfo framebufferInfo{};
|
||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
framebufferInfo.renderPass = pipe.first;
|
||||
framebufferInfo.renderPass = pipe.getRenderPass();
|
||||
framebufferInfo.attachmentCount = 1;
|
||||
framebufferInfo.pAttachments = attachments;
|
||||
framebufferInfo.width = extent.width;
|
||||
|
@ -52,6 +85,68 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, PipelineRef
|
|||
}
|
||||
}
|
||||
|
||||
{ // Uniform buffers
|
||||
VkDeviceSize bufferSize = sizeof(buffer::vk::UniformBufferObject);
|
||||
|
||||
std::vector<Allocator::buffer_requirement> requirements;
|
||||
requirements.resize(framebuffers.size(), Allocator::buffer_requirement{bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT});
|
||||
uniformBuffersMemory = alloc.createBuffers(requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers);
|
||||
if (!uniformBuffersMemory) {
|
||||
FATAL("Failed to allocate UBO");
|
||||
}
|
||||
}
|
||||
{ // Descriptor pool
|
||||
VkDescriptorPoolSize poolSize{};
|
||||
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
poolSize.descriptorCount = framebuffers.size();
|
||||
|
||||
VkDescriptorPoolCreateInfo poolInfo{};
|
||||
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
poolInfo.poolSizeCount = 1;
|
||||
poolInfo.pPoolSizes = &poolSize;
|
||||
poolInfo.maxSets = framebuffers.size();
|
||||
poolInfo.flags = 0; //VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT
|
||||
|
||||
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
|
||||
FATAL("Failed to create descriptor pool!");
|
||||
}
|
||||
}
|
||||
{ // Descriptor sets
|
||||
std::vector<VkDescriptorSetLayout> layouts(framebuffers.size(), pipe.getDescriptorSet());
|
||||
VkDescriptorSetAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
allocInfo.descriptorPool = descriptorPool;
|
||||
allocInfo.descriptorSetCount = framebuffers.size();
|
||||
allocInfo.pSetLayouts = layouts.data();
|
||||
|
||||
descriptorSets.resize(framebuffers.size());
|
||||
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
|
||||
FATAL("Failed to allocate descriptor sets!");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < descriptorSets.size(); i++) {
|
||||
VkDescriptorBufferInfo bufferInfo{};
|
||||
bufferInfo.buffer = uniformBuffers[i].buffer;
|
||||
bufferInfo.offset = 0;
|
||||
bufferInfo.range = sizeof(buffer::vk::UniformBufferObject);
|
||||
|
||||
VkWriteDescriptorSet descriptorWrite{};
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.dstSet = descriptorSets[i];
|
||||
descriptorWrite.dstBinding = 0;
|
||||
descriptorWrite.dstArrayElement = 0;
|
||||
|
||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
descriptorWrite.descriptorCount = 1;
|
||||
|
||||
descriptorWrite.pBufferInfo = &bufferInfo;
|
||||
descriptorWrite.pImageInfo = nullptr;
|
||||
descriptorWrite.pTexelBufferView = nullptr;
|
||||
|
||||
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
graphicsBuffers.resize(framebuffers.size());
|
||||
VkCommandBufferAllocateInfo allocInfo{};
|
||||
|
@ -77,7 +172,7 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, PipelineRef
|
|||
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = pipe.first;
|
||||
renderPassInfo.renderPass = pipe.getRenderPass();
|
||||
renderPassInfo.framebuffer = framebuffers[i];
|
||||
renderPassInfo.renderArea.offset = {0, 0};
|
||||
renderPassInfo.renderArea.extent = extent;
|
||||
|
@ -87,11 +182,12 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, PipelineRef
|
|||
renderPassInfo.pClearValues = &clearColor;
|
||||
|
||||
vkCmdBeginRenderPass(graphicsBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBindPipeline(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.second);
|
||||
VkBuffer vertexBuffers[] = {buffer.first};
|
||||
vkCmdBindPipeline(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.getPipeline());
|
||||
VkBuffer vertexBuffers[] = {vertexBuffer.buffer};
|
||||
VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(graphicsBuffers[i], 0, 1, vertexBuffers, offsets);
|
||||
vkCmdBindIndexBuffer(graphicsBuffers[i], buffer.second, 0, VK_INDEX_TYPE_UINT16);
|
||||
vkCmdBindIndexBuffer(graphicsBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
||||
vkCmdBindDescriptorSets(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.getLayout(), 0, 1, &descriptorSets[i], 0, nullptr);
|
||||
vkCmdDrawIndexed(graphicsBuffers[i], static_cast<uint32_t>(buffer::vk::indices.size()), 1, 0, 0, 0);
|
||||
vkCmdEndRenderPass(graphicsBuffers[i]);
|
||||
|
||||
|
@ -100,19 +196,46 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, PipelineRef
|
|||
}
|
||||
}
|
||||
|
||||
proj = glm::perspective(glm::radians(45.0f), extent.width / (float) extent.height, 0.1f, 10.0f);
|
||||
proj[1][1] *= -1;
|
||||
|
||||
freed = false;
|
||||
}
|
||||
void CommandCenter::free() {
|
||||
assert(!freed);
|
||||
vkFreeCommandBuffers(device, graphicsPool, static_cast<uint32_t>(graphicsBuffers.size()), graphicsBuffers.data());
|
||||
|
||||
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
|
||||
|
||||
for (size_t i = 0; i < uniformBuffers.size(); i++) {
|
||||
vkDestroyBuffer(device, uniformBuffers[i].buffer, ALLOC);
|
||||
}
|
||||
uniformBuffersMemory.reset();
|
||||
|
||||
|
||||
for (size_t i = 0; i < framebuffers.size(); i++) {
|
||||
vkDestroyFramebuffer(device, framebuffers[i], nullptr);
|
||||
}
|
||||
|
||||
vkFreeCommandBuffers(device, graphicsPool, static_cast<uint32_t>(graphicsBuffers.size()), graphicsBuffers.data());
|
||||
|
||||
freed = true;
|
||||
}
|
||||
|
||||
#include <chrono>
|
||||
#include <memory.h>
|
||||
|
||||
void CommandCenter::updateUBO(uint32_t idx) {
|
||||
static auto startTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto currentTime = std::chrono::high_resolution_clock::now();
|
||||
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
|
||||
buffer::vk::UniformBufferObject ubo{};
|
||||
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
ubo.proj = proj;
|
||||
|
||||
memcpy(uniformBuffersMemory->ptr + uniformBuffers[idx].offset, &ubo, sizeof(ubo));
|
||||
}
|
||||
|
||||
void CommandCenter::submitGraphics(uint32_t idx, VkSemaphore waitSemaphore, VkSemaphore signalSemaphore, VkFence submittedFence) {
|
||||
assert(!freed);
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "forward.hpp"
|
||||
#include <vector>
|
||||
#include "Allocator.hpp"
|
||||
#include <glm/mat4x4.hpp>
|
||||
|
||||
namespace render::vk {
|
||||
class SwapChain;
|
||||
|
@ -9,12 +11,13 @@ class Pipeline;
|
|||
|
||||
class CommandCenter {
|
||||
public:
|
||||
CommandCenter(VkDevice, const std::vector<VkImageView>&, PipelineRef, std::pair<VkBuffer, VkBuffer>, const PhysicalDeviceInfo&, const renderOptions&);
|
||||
CommandCenter(VkDevice, Allocator&, const std::vector<VkImageView>&, const Pipeline&, const PhysicalDeviceInfo&, const renderOptions&);
|
||||
~CommandCenter();
|
||||
|
||||
void updateUBO(uint32_t idx);
|
||||
void submitGraphics(uint32_t, VkSemaphore, VkSemaphore, VkFence);
|
||||
|
||||
void allocate(const std::vector<VkImageView> &, PipelineRef, std::pair<VkBuffer, VkBuffer>, VkExtent2D, const renderOptions&);
|
||||
void allocate(Allocator&, const std::vector<VkImageView> &, const Pipeline&, VkExtent2D, const renderOptions&);
|
||||
void free();
|
||||
|
||||
private:
|
||||
|
@ -26,6 +29,17 @@ private:
|
|||
VkCommandPool graphicsPool;
|
||||
std::vector<VkCommandBuffer> graphicsBuffers;
|
||||
|
||||
VkDescriptorPool descriptorPool;
|
||||
std::vector<VkDescriptorSet> descriptorSets;
|
||||
|
||||
Allocator::buffer_info vertexBuffer;
|
||||
Allocator::buffer_info indexBuffer;
|
||||
Allocator::memory_ptr indexedBufferMemory;
|
||||
|
||||
glm::mat4 proj;
|
||||
std::vector<Allocator::buffer_info> uniformBuffers;
|
||||
Allocator::memory_ptr uniformBuffersMemory;
|
||||
|
||||
bool freed = true;
|
||||
};
|
||||
}
|
|
@ -57,11 +57,22 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
|||
FATAL("Failed to create render pass!");
|
||||
}
|
||||
}
|
||||
{
|
||||
VkDescriptorSetLayoutCreateInfo layoutInfo{};
|
||||
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
layoutInfo.bindingCount = 1;
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings = {buffer::vk::UniformBufferObject::getLayoutBinding()};
|
||||
layoutInfo.pBindings = bindings.data();
|
||||
|
||||
if (vkCreateDescriptorSetLayout(device, &layoutInfo, ALLOC, &descriptorSetLayout) != VK_SUCCESS) {
|
||||
FATAL("Failed to create descriptor set layout!");
|
||||
}
|
||||
}
|
||||
{
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayoutInfo.setLayoutCount = 0; // TODO: setup layouts
|
||||
pipelineLayoutInfo.pSetLayouts = nullptr;
|
||||
pipelineLayoutInfo.setLayoutCount = 1;
|
||||
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
|
||||
pipelineLayoutInfo.pushConstantRangeCount = 0;
|
||||
pipelineLayoutInfo.pPushConstantRanges = nullptr;
|
||||
|
||||
|
@ -151,7 +162,7 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
|||
rasterizer.polygonMode = options.wireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
|
||||
rasterizer.lineWidth = 1.0f;
|
||||
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
rasterizer.depthBiasEnable = VK_FALSE;
|
||||
rasterizer.depthBiasConstantFactor = 0.0f;
|
||||
rasterizer.depthBiasClamp = 0.0f;
|
||||
|
@ -235,6 +246,7 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
|||
Pipeline::~Pipeline() {
|
||||
vkDestroyPipeline(device, graphicsPipeline, ALLOC);
|
||||
vkDestroyPipelineLayout(device, pipelineLayout, ALLOC);
|
||||
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, ALLOC);
|
||||
vkDestroyRenderPass(device, renderPass, ALLOC);
|
||||
|
||||
vkDestroyShaderModule(device, fsShader, ALLOC);
|
||||
|
|
|
@ -9,7 +9,10 @@ public:
|
|||
Pipeline(VkDevice, const PhysicalDeviceInfo&, const renderOptions&);
|
||||
~Pipeline();
|
||||
|
||||
PipelineRef getRef() { return std::make_pair(renderPass, graphicsPipeline); }
|
||||
constexpr VkRenderPass getRenderPass() const { return renderPass; }
|
||||
constexpr VkPipeline getPipeline() const { return graphicsPipeline; }
|
||||
constexpr VkPipelineLayout getLayout() const { return pipelineLayout; }
|
||||
constexpr VkDescriptorSetLayout getDescriptorSet() const { return descriptorSetLayout; }
|
||||
|
||||
private:
|
||||
VkDevice device;
|
||||
|
@ -18,6 +21,7 @@ private:
|
|||
VkShaderModule fsShader;
|
||||
|
||||
VkRenderPass renderPass;
|
||||
VkDescriptorSetLayout descriptorSetLayout;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkPipeline graphicsPipeline;
|
||||
};
|
||||
|
|
|
@ -27,7 +27,7 @@ Renderer::Renderer(VkInstance instance, VkDevice device, const PhysicalDeviceInf
|
|||
allocator = std::make_unique<Allocator>(device, *physicalInfo.get());
|
||||
swapChain = std::make_unique<SwapChain>(device, *physicalInfo.get());
|
||||
pipeline = std::make_unique<Pipeline>(device, *physicalInfo.get(), options);
|
||||
commandCenter = std::make_unique<CommandCenter>(device, swapChain->getImageViews(), pipeline->getRef(), allocator->getBuffer(), *physicalInfo.get(), options);
|
||||
commandCenter = std::make_unique<CommandCenter>(device, *allocator.get(), swapChain->getImageViews(), *pipeline.get(), *physicalInfo.get(), options);
|
||||
|
||||
{
|
||||
imageAvailableSemaphores.resize(opt.inFlightFrames);
|
||||
|
@ -78,7 +78,7 @@ void Renderer::recreateSwapChain() {
|
|||
set_current_extent(physicalInfo->swapDetails.capabilities, physicalInfo->window);
|
||||
swapChain = std::make_unique<SwapChain>(device, *physicalInfo.get());
|
||||
pipeline = std::make_unique<Pipeline>(device, *physicalInfo.get(), options);
|
||||
commandCenter->allocate(swapChain->getImageViews(), pipeline->getRef(), allocator->getBuffer(), physicalInfo->swapDetails.capabilities.currentExtent, options);
|
||||
commandCenter->allocate(*allocator.get(), swapChain->getImageViews(), *pipeline.get(), physicalInfo->swapDetails.capabilities.currentExtent, options);
|
||||
}
|
||||
void Renderer::destroySwapChain() {
|
||||
commandCenter->free();
|
||||
|
@ -342,9 +342,9 @@ void Renderer::beginFrame() {
|
|||
std::function<buffer::params(glm::mat4)> Renderer::beginWorldPass() {
|
||||
assert(currentImage < swapChain->getImageViews().size());
|
||||
|
||||
commandCenter->updateUBO(currentImage);
|
||||
commandCenter->submitGraphics(currentImage, imageAvailableSemaphores[currentFrame],
|
||||
renderFinishedSemaphores[currentFrame], inFlightFences[currentFrame]);
|
||||
|
||||
/*WorldPass->useIt();
|
||||
WorldPass->start(this);*/
|
||||
return [&](glm::mat4) {
|
||||
|
|
|
@ -42,4 +42,21 @@ const std::vector<uint16_t> indices = {
|
|||
0, 1, 2, 2, 3, 0
|
||||
};
|
||||
|
||||
|
||||
struct UniformBufferObject {
|
||||
alignas(16) glm::mat4 model;
|
||||
alignas(16) glm::mat4 view;
|
||||
alignas(16) glm::mat4 proj;
|
||||
|
||||
static VkDescriptorSetLayoutBinding getLayoutBinding() {
|
||||
VkDescriptorSetLayoutBinding uboLayoutBinding{};
|
||||
uboLayoutBinding.binding = 0;
|
||||
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
uboLayoutBinding.descriptorCount = 1;
|
||||
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
uboLayoutBinding.pImmutableSamplers = nullptr;
|
||||
return uboLayoutBinding;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <volk.h>
|
||||
#include <tuple>
|
||||
namespace render { struct renderOptions; }
|
||||
namespace render::vk {
|
||||
struct PhysicalDeviceInfo;
|
||||
using PipelineRef = std::pair<VkRenderPass, VkPipeline>;
|
||||
constexpr VkAllocationCallbacks *ALLOC = nullptr;
|
||||
}
|
Loading…
Reference in New Issue