Vertex buffers
- Fix RenderObject comparator for storing in set - RenderObjects get ID on register - Transfer queue family and queue - Command buffers for transfer queue - PipelineFactory constructor parameters combined in PipelineBinding structure - GPU_Vertex and GPU_Buffer structures to map GPU memory data - Vertex buffers for world and UI RenderObjects with staging
This commit is contained in:
parent
16bd65c35a
commit
2e0369ee2b
Binary file not shown.
@ -24,6 +24,7 @@ list(TRANSFORM SOURCES PREPEND "src/")
|
|||||||
find_package(Boost REQUIRED COMPONENTS lockfree)
|
find_package(Boost REQUIRED COMPONENTS lockfree)
|
||||||
find_package(xxHash CONFIG REQUIRED)
|
find_package(xxHash CONFIG REQUIRED)
|
||||||
find_package(glfw3 CONFIG REQUIRED)
|
find_package(glfw3 CONFIG REQUIRED)
|
||||||
|
find_package(glm CONFIG REQUIRED)
|
||||||
find_package(Vulkan REQUIRED)
|
find_package(Vulkan REQUIRED)
|
||||||
find_package(RmlUi CONFIG REQUIRED)
|
find_package(RmlUi CONFIG REQUIRED)
|
||||||
|
|
||||||
@ -37,6 +38,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE Boost::lockfree)
|
|||||||
target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash)
|
target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE p7)
|
target_link_libraries(${PROJECT_NAME} PRIVATE p7)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE glfw)
|
target_link_libraries(${PROJECT_NAME} PRIVATE glfw)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE glm::glm)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Vulkan::Vulkan)
|
target_link_libraries(${PROJECT_NAME} PRIVATE Vulkan::Vulkan)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE RmlUi::RmlUi)
|
target_link_libraries(${PROJECT_NAME} PRIVATE RmlUi::RmlUi)
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,19 @@
|
|||||||
#define PIPELINE_CREATE_NEW 0
|
#define PIPELINE_CREATE_NEW 0
|
||||||
#define PIPELINE_CREATE_DERIVED (1 << 0)
|
#define PIPELINE_CREATE_DERIVED (1 << 0)
|
||||||
|
|
||||||
|
struct PipelineBinding
|
||||||
|
{
|
||||||
|
const AssetMaterial *baseMaterial;
|
||||||
|
|
||||||
|
const VkRenderPass *baseRenderPass;
|
||||||
|
const VkDevice *device;
|
||||||
|
const VkExtent2D *surfaceExtent;
|
||||||
|
|
||||||
|
const VkVertexInputBindingDescription *vertexBindingConfig;
|
||||||
|
uint32_t vertexAttributesCount;
|
||||||
|
const VkVertexInputAttributeDescription *vertexAttributesConfig;
|
||||||
|
};
|
||||||
|
|
||||||
struct PipelineConfig
|
struct PipelineConfig
|
||||||
{
|
{
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputConfig;
|
VkPipelineVertexInputStateCreateInfo vertexInputConfig;
|
||||||
@ -42,19 +55,22 @@ struct Pipeline
|
|||||||
class PipelineFactory
|
class PipelineFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PipelineFactory(const AssetMaterial &baseMaterial, const VkRenderPass &baseRenderPass, VkDevice &device, VkExtent2D &surfaceExtent);
|
PipelineFactory(const PipelineBinding &binding);
|
||||||
~PipelineFactory();
|
~PipelineFactory();
|
||||||
|
|
||||||
Pipeline& Get(const AssetMaterial &material);
|
Pipeline& Get(const AssetMaterial &material);
|
||||||
void Create(const AssetMaterial &material, const VkRenderPass &renderPass, const uint32_t &flags);
|
void Create(const AssetMaterial &material, const VkRenderPass &renderPass, const uint32_t &flags);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PipelineBinding binding;
|
||||||
PipelineConfig basePipelineConfig;
|
PipelineConfig basePipelineConfig;
|
||||||
|
|
||||||
Pipeline basePipeline;
|
Pipeline basePipeline;
|
||||||
std::unordered_map<const AssetMaterial*, Pipeline> pipelines;
|
std::unordered_map<const AssetMaterial*, Pipeline> pipelines;
|
||||||
|
|
||||||
VkDevice &device;
|
const VkDevice &device;
|
||||||
VkExtent2D &surfaceExtent;
|
const VkExtent2D &surfaceExtent;
|
||||||
|
|
||||||
|
const VkVertexInputBindingDescription &vertexBindingConfig;
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -2,13 +2,14 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <Boost/lockfree/spsc_queue.hpp>
|
#include <Boost/lockfree/spsc_queue.hpp>
|
||||||
|
|
||||||
#define GLFW_INCLUDE_VULKAN
|
#define GLFW_INCLUDE_VULKAN
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <RmlUi/Core.h>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "PipelineFactory.hpp"
|
#include "PipelineFactory.hpp"
|
||||||
|
|
||||||
@ -18,6 +19,10 @@
|
|||||||
#define VALIDATION_LAYER
|
#define VALIDATION_LAYER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ATTRIBUTE_FORMAT_VEC2 VK_FORMAT_R32G32_SFLOAT
|
||||||
|
#define ATTRIBUTE_FORMAT_VEC3 VK_FORMAT_R32G32B32_SFLOAT
|
||||||
|
#define ATTRIBUTE_FORMAT_VEC4 VK_FORMAT_R32G32B32A32_SFLOAT
|
||||||
|
|
||||||
// GPU properties priority for selection
|
// GPU properties priority for selection
|
||||||
#define GPU_DISCRETE_PRIORITY 1000
|
#define GPU_DISCRETE_PRIORITY 1000
|
||||||
#define GPU_GRAPHICS_WITH_PRESENT_PRIORITY 500
|
#define GPU_GRAPHICS_WITH_PRESENT_PRIORITY 500
|
||||||
@ -34,17 +39,93 @@ struct Transform
|
|||||||
float scaleX = 1.0f, scaleY = 1.0f, scaleZ = 1.0f;
|
float scaleX = 1.0f, scaleY = 1.0f, scaleZ = 1.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GPU_Vertex
|
||||||
|
{
|
||||||
|
glm::vec2 pos;
|
||||||
|
glm::vec3 color;
|
||||||
|
|
||||||
|
static std::array<VkVertexInputAttributeDescription, 2> GetAttributes()
|
||||||
|
{
|
||||||
|
VkVertexInputAttributeDescription posAttribute = {
|
||||||
|
.location = 0,
|
||||||
|
.binding = 0,
|
||||||
|
.format = ATTRIBUTE_FORMAT_VEC2,
|
||||||
|
.offset = offsetof(GPU_Vertex, pos)
|
||||||
|
};
|
||||||
|
VkVertexInputAttributeDescription colorAttribute = {
|
||||||
|
.location = 1,
|
||||||
|
.binding = 0,
|
||||||
|
.format = ATTRIBUTE_FORMAT_VEC3,
|
||||||
|
.offset = offsetof(GPU_Vertex, color)
|
||||||
|
};
|
||||||
|
|
||||||
|
return {posAttribute, colorAttribute};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GPU_BufferSlot
|
||||||
|
{
|
||||||
|
size_t position;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO: move methods definition to the end of file
|
||||||
|
template<typename T> struct GPU_Buffer
|
||||||
|
{
|
||||||
|
T *data;
|
||||||
|
size_t size;
|
||||||
|
const size_t ELEMENT_SIZE;
|
||||||
|
std::vector<GPU_BufferSlot> freeSlots;
|
||||||
|
|
||||||
|
GPU_Buffer() : ELEMENT_SIZE(sizeof(T)) {freeSlots.push_back({.position = 0, .size = size});}
|
||||||
|
|
||||||
|
GPU_BufferSlot* FindFreeSlot(size_t size)
|
||||||
|
{
|
||||||
|
for (auto i = freeSlots.rbegin(); i != freeSlots.rend(); i++)
|
||||||
|
{
|
||||||
|
if (i->size >= size)
|
||||||
|
return &(*i);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Write(const T *elements, size_t elementsCount)
|
||||||
|
{
|
||||||
|
GPU_BufferSlot *slot = FindFreeSlot(elementsCount);
|
||||||
|
if (slot == nullptr) return 0;
|
||||||
|
|
||||||
|
memcpy(data + slot->position, elements, elementsCount * ELEMENT_SIZE);
|
||||||
|
|
||||||
|
slot->size -= elementsCount;
|
||||||
|
slot->position += elementsCount;
|
||||||
|
if (slot->size == 0)
|
||||||
|
freeSlots.pop_back();
|
||||||
|
|
||||||
|
return slot->position - elementsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void Clear(GPU_BufferSlot range)
|
||||||
|
// {
|
||||||
|
// freeSlots.push_back(range);
|
||||||
|
// //TODO: insert sorted by pos and combine intersections
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
struct Mesh
|
struct Mesh
|
||||||
{
|
{
|
||||||
uint32_t vertexCount = 0;
|
size_t verticesBufferPosition = 0;
|
||||||
|
std::vector<GPU_Vertex> vertices;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenderObject
|
struct RenderObject
|
||||||
{
|
{
|
||||||
|
uint32_t engineId = UINT32_MAX;
|
||||||
|
|
||||||
// Multiple transforms for batching
|
// Multiple transforms for batching
|
||||||
std::vector<Transform> transforms;
|
std::vector<Transform> transforms;
|
||||||
uint8_t depth = 0;
|
uint8_t depth = 0;
|
||||||
Mesh mesh; //TODO: mesh (vertex/index buffer)
|
Mesh mesh;
|
||||||
|
bool isUI = false;
|
||||||
//TODO: texture
|
//TODO: texture
|
||||||
|
|
||||||
AssetMaterial &material;
|
AssetMaterial &material;
|
||||||
@ -69,12 +150,14 @@ struct RenderCommand
|
|||||||
|
|
||||||
struct QueueFamiliesBundle
|
struct QueueFamiliesBundle
|
||||||
{
|
{
|
||||||
|
uint32_t transfer = QUEUE_FAMILY_NO_VALUE;
|
||||||
uint32_t graphics = QUEUE_FAMILY_NO_VALUE;
|
uint32_t graphics = QUEUE_FAMILY_NO_VALUE;
|
||||||
uint32_t present = QUEUE_FAMILY_NO_VALUE;
|
uint32_t present = QUEUE_FAMILY_NO_VALUE;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QueuesBundle
|
struct QueuesBundle
|
||||||
{
|
{
|
||||||
|
VkQueue transfer;
|
||||||
VkQueue graphics;
|
VkQueue graphics;
|
||||||
VkQueue present;
|
VkQueue present;
|
||||||
};
|
};
|
||||||
@ -115,6 +198,12 @@ struct DrawConfig
|
|||||||
.swapchainCount = 1,
|
.swapchainCount = 1,
|
||||||
.pResults = nullptr
|
.pResults = nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VkVertexInputBindingDescription vertexBindingConfig {
|
||||||
|
.binding = 0,
|
||||||
|
.stride = sizeof(GPU_Vertex),
|
||||||
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SurfaceInfo
|
struct SurfaceInfo
|
||||||
@ -131,7 +220,7 @@ struct SurfaceInfo
|
|||||||
class Renderer
|
class Renderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Renderer(GLFWwindow *window, const AssetMaterial& baseMaterial);
|
Renderer(GLFWwindow *window, const AssetMaterial& baseMaterial, const size_t &vertexBufferSize);
|
||||||
~Renderer();
|
~Renderer();
|
||||||
|
|
||||||
void Start();
|
void Start();
|
||||||
@ -160,8 +249,16 @@ private:
|
|||||||
VkDevice device;
|
VkDevice device;
|
||||||
VkSwapchainKHR swapchain;
|
VkSwapchainKHR swapchain;
|
||||||
VkRenderPass baseRenderPass;
|
VkRenderPass baseRenderPass;
|
||||||
VkCommandPool commandPool = nullptr;
|
VkCommandPool graphicsCommandPool = nullptr;
|
||||||
std::vector<VkCommandBuffer> commandBuffers;
|
VkCommandPool transferCommandPool = nullptr;
|
||||||
|
VkDeviceMemory worldVerticesMemory;
|
||||||
|
VkDeviceMemory stagingWorldVerticesMemory;
|
||||||
|
VkDeviceMemory uiVerticesMemory;
|
||||||
|
VkBuffer worldVertices;
|
||||||
|
VkBuffer stagingWorldVertices;
|
||||||
|
VkBuffer uiVertices;
|
||||||
|
std::vector<VkCommandBuffer> graphicsCommandBuffers;
|
||||||
|
std::vector<VkCommandBuffer> transferCommandBuffers;
|
||||||
std::vector<VkImage> frames;
|
std::vector<VkImage> frames;
|
||||||
std::vector<VkImageView> frameViews;
|
std::vector<VkImageView> frameViews;
|
||||||
std::vector<VkFramebuffer> baseFrameBuffers;
|
std::vector<VkFramebuffer> baseFrameBuffers;
|
||||||
@ -175,14 +272,20 @@ private:
|
|||||||
QueuesBundle queues;
|
QueuesBundle queues;
|
||||||
DrawConfig drawConfig;
|
DrawConfig drawConfig;
|
||||||
PipelineFactory *pipelineFactory;
|
PipelineFactory *pipelineFactory;
|
||||||
|
PipelineBinding pipelineBinding;
|
||||||
size_t currentFrame = 0;
|
size_t currentFrame = 0;
|
||||||
|
|
||||||
|
GPU_Buffer<GPU_Vertex> worldVerticesBinded;
|
||||||
|
GPU_Buffer<GPU_Vertex> uiVerticesBinded;
|
||||||
|
|
||||||
const float DEFAULT_QUEUE_PRIORITY = 1.0f;
|
const float DEFAULT_QUEUE_PRIORITY = 1.0f;
|
||||||
const AssetMaterial &baseMaterial;
|
const AssetMaterial &baseMaterial;
|
||||||
const size_t MAX_FRAMES_IN_FLIGHT = 2;
|
const size_t MAX_FRAMES_IN_FLIGHT = 2;
|
||||||
|
const size_t VERTEX_BUFFER_SIZE;
|
||||||
|
|
||||||
std::set<RenderObject> objects;
|
std::set<RenderObject> objects;
|
||||||
|
|
||||||
Rml::Context *uiContext;
|
//Rml::Context *uiContext;
|
||||||
|
|
||||||
void InitVulkan();
|
void InitVulkan();
|
||||||
void SetupDevice();
|
void SetupDevice();
|
||||||
@ -190,10 +293,13 @@ private:
|
|||||||
void RecreateSwapchain();
|
void RecreateSwapchain();
|
||||||
void ReleaseSwapchain();
|
void ReleaseSwapchain();
|
||||||
void SetupRenderPasses();
|
void SetupRenderPasses();
|
||||||
void SetupBuffers();
|
void SetupPipelines();
|
||||||
|
void SetupObjectsBuffers();
|
||||||
|
void SetupRenderBuffers();
|
||||||
void SetupSync();
|
void SetupSync();
|
||||||
|
|
||||||
void Draw();
|
void Draw();
|
||||||
|
void CopyBuffer(VkBuffer src, size_t offset, VkBuffer dst, VkDeviceSize size);
|
||||||
|
|
||||||
void Threading();
|
void Threading();
|
||||||
void Request(const RenderCommand &command);
|
void Request(const RenderCommand &command);
|
||||||
|
|||||||
@ -22,14 +22,13 @@ PipelineConfig PipelineConfig::Copy() const
|
|||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineFactory::PipelineFactory(
|
PipelineFactory::PipelineFactory(const PipelineBinding &binding) :
|
||||||
const AssetMaterial &baseMaterial,
|
device(*binding.device),
|
||||||
const VkRenderPass &baseRenderPass,
|
surfaceExtent(*binding.surfaceExtent),
|
||||||
VkDevice &device,
|
vertexBindingConfig(*binding.vertexBindingConfig)
|
||||||
VkExtent2D &surfaceExtent
|
|
||||||
) :
|
|
||||||
device(device), surfaceExtent(surfaceExtent)
|
|
||||||
{
|
{
|
||||||
|
this->binding = binding;
|
||||||
|
|
||||||
basePipelineConfig.dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
|
basePipelineConfig.dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
|
||||||
basePipelineConfig.dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
|
basePipelineConfig.dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
|
||||||
|
|
||||||
@ -47,10 +46,10 @@ PipelineFactory::PipelineFactory(
|
|||||||
basePipelineConfig.vertexInputConfig = {
|
basePipelineConfig.vertexInputConfig = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.vertexBindingDescriptionCount = 0,
|
.vertexBindingDescriptionCount = 1,
|
||||||
.pVertexBindingDescriptions = nullptr,
|
.pVertexBindingDescriptions = &vertexBindingConfig,
|
||||||
.vertexAttributeDescriptionCount = 0,
|
.vertexAttributeDescriptionCount = binding.vertexAttributesCount,
|
||||||
.pVertexAttributeDescriptions = nullptr
|
.pVertexAttributeDescriptions = binding.vertexAttributesConfig
|
||||||
};
|
};
|
||||||
|
|
||||||
basePipelineConfig.inputAssemblyConfig = {
|
basePipelineConfig.inputAssemblyConfig = {
|
||||||
@ -146,7 +145,7 @@ PipelineFactory::PipelineFactory(
|
|||||||
};
|
};
|
||||||
|
|
||||||
LOG(INFO, "Creating base material pipeline...");
|
LOG(INFO, "Creating base material pipeline...");
|
||||||
Create(baseMaterial, baseRenderPass, PIPELINE_CREATE_NEW);
|
Create(*binding.baseMaterial, *binding.baseRenderPass, PIPELINE_CREATE_NEW);
|
||||||
LOG(INFO, "Base material pipeline created");
|
LOG(INFO, "Base material pipeline created");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,13 +11,16 @@
|
|||||||
|
|
||||||
bool operator < (const RenderObject& lhs, const RenderObject& rhs)
|
bool operator < (const RenderObject& lhs, const RenderObject& rhs)
|
||||||
{
|
{
|
||||||
|
if (&lhs.material != &rhs.material)
|
||||||
return &lhs.material < &rhs.material;
|
return &lhs.material < &rhs.material;
|
||||||
|
else return lhs.engineId < rhs.engineId;
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::Renderer(GLFWwindow *window, const AssetMaterial &baseMaterial) :
|
Renderer::Renderer(GLFWwindow *window, const AssetMaterial &baseMaterial, const size_t &vertexBufferSize) :
|
||||||
isRunning(false),
|
isRunning(false),
|
||||||
isDrawing(false),
|
isDrawing(false),
|
||||||
baseMaterial(baseMaterial)
|
baseMaterial(baseMaterial),
|
||||||
|
VERTEX_BUFFER_SIZE(vertexBufferSize)
|
||||||
{
|
{
|
||||||
this->window = window;
|
this->window = window;
|
||||||
int width = -1, height = -1;
|
int width = -1, height = -1;
|
||||||
@ -180,6 +183,7 @@ void Renderer::SetupDevice()
|
|||||||
queueFamiliesBuffer.present == QUEUE_FAMILY_NO_VALUE
|
queueFamiliesBuffer.present == QUEUE_FAMILY_NO_VALUE
|
||||||
)
|
)
|
||||||
continue;
|
continue;
|
||||||
|
queueFamiliesBuffer.transfer = queueFamiliesBuffer.graphics;
|
||||||
|
|
||||||
// Check surface info
|
// Check surface info
|
||||||
SurfaceInfo surfaceInfoBuffer {};
|
SurfaceInfo surfaceInfoBuffer {};
|
||||||
@ -272,8 +276,10 @@ void Renderer::SetupDevice()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Define queues
|
// Define queues
|
||||||
|
//TODO: transfer is separate queue for async loading
|
||||||
std::vector<VkDeviceQueueCreateInfo> queuesCreateConfigs;
|
std::vector<VkDeviceQueueCreateInfo> queuesCreateConfigs;
|
||||||
std::set<uint32_t> uniqueQueueFamilies {
|
std::set<uint32_t> uniqueQueueFamilies {
|
||||||
|
queueFamilies.transfer,
|
||||||
queueFamilies.graphics,
|
queueFamilies.graphics,
|
||||||
queueFamilies.present
|
queueFamilies.present
|
||||||
};
|
};
|
||||||
@ -315,6 +321,7 @@ void Renderer::SetupDevice()
|
|||||||
else LOG(INFO, "%hs is selected for render with %d priority score", deviceProperties.deviceName, best_priority);
|
else LOG(INFO, "%hs is selected for render with %d priority score", deviceProperties.deviceName, best_priority);
|
||||||
|
|
||||||
// Save queues descriptor
|
// Save queues descriptor
|
||||||
|
vkGetDeviceQueue(device, queueFamilies.transfer, 0, &queues.transfer);
|
||||||
vkGetDeviceQueue(device, queueFamilies.graphics, 0, &queues.graphics);
|
vkGetDeviceQueue(device, queueFamilies.graphics, 0, &queues.graphics);
|
||||||
vkGetDeviceQueue(device, queueFamilies.present, 0, &queues.present);
|
vkGetDeviceQueue(device, queueFamilies.present, 0, &queues.present);
|
||||||
}
|
}
|
||||||
@ -430,8 +437,8 @@ void Renderer::RecreateSwapchain()
|
|||||||
|
|
||||||
SetupSwapchain();
|
SetupSwapchain();
|
||||||
SetupRenderPasses();
|
SetupRenderPasses();
|
||||||
pipelineFactory = Allocate<PipelineFactory>(baseMaterial, baseRenderPass, device, surfaceInfo.extent);
|
SetupPipelines();
|
||||||
SetupBuffers();
|
SetupRenderBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::ReleaseSwapchain()
|
void Renderer::ReleaseSwapchain()
|
||||||
@ -442,9 +449,15 @@ void Renderer::ReleaseSwapchain()
|
|||||||
}
|
}
|
||||||
vkFreeCommandBuffers(
|
vkFreeCommandBuffers(
|
||||||
device,
|
device,
|
||||||
commandPool,
|
graphicsCommandPool,
|
||||||
static_cast<uint32_t>(commandBuffers.size()),
|
static_cast<uint32_t>(graphicsCommandBuffers.size()),
|
||||||
commandBuffers.data()
|
graphicsCommandBuffers.data()
|
||||||
|
);
|
||||||
|
vkFreeCommandBuffers(
|
||||||
|
device,
|
||||||
|
transferCommandPool,
|
||||||
|
static_cast<uint32_t>(transferCommandBuffers.size()),
|
||||||
|
transferCommandBuffers.data()
|
||||||
);
|
);
|
||||||
|
|
||||||
vkDestroyRenderPass(device, baseRenderPass, nullptr);
|
vkDestroyRenderPass(device, baseRenderPass, nullptr);
|
||||||
@ -509,7 +522,162 @@ void Renderer::SetupRenderPasses()
|
|||||||
LOG(CRITICAL, "Failed to create base render pass. Code: %d", vkResult);
|
LOG(CRITICAL, "Failed to create base render pass. Code: %d", vkResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetupBuffers()
|
void Renderer::SetupPipelines()
|
||||||
|
{
|
||||||
|
std::array vertexAttributes = GPU_Vertex::GetAttributes();
|
||||||
|
|
||||||
|
pipelineBinding = {
|
||||||
|
.baseMaterial = &baseMaterial,
|
||||||
|
.baseRenderPass = &baseRenderPass,
|
||||||
|
.device = &device,
|
||||||
|
.surfaceExtent = &surfaceInfo.extent,
|
||||||
|
|
||||||
|
.vertexBindingConfig = &drawConfig.vertexBindingConfig,
|
||||||
|
.vertexAttributesCount = static_cast<uint32_t>(vertexAttributes.size()),
|
||||||
|
.vertexAttributesConfig = vertexAttributes.data()
|
||||||
|
};
|
||||||
|
|
||||||
|
pipelineFactory = Allocate<PipelineFactory>(pipelineBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::SetupObjectsBuffers()
|
||||||
|
{
|
||||||
|
VkResult vkResult;
|
||||||
|
|
||||||
|
VkBufferCreateInfo worldVertexBufferConfig {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.size = sizeof(GPU_Vertex) * VERTEX_BUFFER_SIZE,
|
||||||
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||||
|
};
|
||||||
|
worldVerticesBinded.size = VERTEX_BUFFER_SIZE;
|
||||||
|
vkResult = vkCreateBuffer(device, &worldVertexBufferConfig, nullptr, &worldVertices);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to create buffer for world vertices. Code: %d", vkResult);
|
||||||
|
|
||||||
|
VkBufferCreateInfo stagingWorldVertexBufferConfig {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.size = sizeof(GPU_Vertex) * VERTEX_BUFFER_SIZE,
|
||||||
|
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||||
|
};
|
||||||
|
vkResult = vkCreateBuffer(device, &stagingWorldVertexBufferConfig, nullptr, &stagingWorldVertices);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to create buffer for staging world vertices. Code: %d", vkResult);
|
||||||
|
|
||||||
|
VkBufferCreateInfo uiVertexBufferConfig {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.size = sizeof(GPU_Vertex) * VERTEX_BUFFER_SIZE,
|
||||||
|
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||||
|
};
|
||||||
|
uiVerticesBinded.size = VERTEX_BUFFER_SIZE;
|
||||||
|
vkResult = vkCreateBuffer(device, &uiVertexBufferConfig, nullptr, &uiVertices);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to create buffer for UI vertices. Code: %d", vkResult);
|
||||||
|
|
||||||
|
VkMemoryRequirements worldMemoryRequirements;
|
||||||
|
vkGetBufferMemoryRequirements(device, worldVertices, &worldMemoryRequirements);
|
||||||
|
VkMemoryRequirements stagingWorldMemoryRequirements;
|
||||||
|
vkGetBufferMemoryRequirements(device, stagingWorldVertices, &stagingWorldMemoryRequirements);
|
||||||
|
VkMemoryRequirements uiMemoryRequirements;
|
||||||
|
vkGetBufferMemoryRequirements(device, uiVertices, &uiMemoryRequirements);
|
||||||
|
|
||||||
|
VkPhysicalDeviceMemoryProperties memoryProps;
|
||||||
|
vkGetPhysicalDeviceMemoryProperties(gpu, &memoryProps);
|
||||||
|
uint32_t optimizedMemTypeIndex = UINT32_MAX, cpuAccessMemTypeIndex = UINT32_MAX;
|
||||||
|
VkMemoryPropertyFlags optimizedMemoryProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||||
|
VkMemoryPropertyFlags cpuAccessMemoryProps = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
||||||
|
for (uint32_t i = 0; i < memoryProps.memoryTypeCount; i++)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
optimizedMemTypeIndex == UINT32_MAX &&
|
||||||
|
worldMemoryRequirements.memoryTypeBits & (1 << i) &&
|
||||||
|
(memoryProps.memoryTypes[i].propertyFlags & optimizedMemoryProps) == optimizedMemoryProps
|
||||||
|
)
|
||||||
|
optimizedMemTypeIndex = i;
|
||||||
|
if (
|
||||||
|
cpuAccessMemTypeIndex == UINT32_MAX &&
|
||||||
|
stagingWorldMemoryRequirements.memoryTypeBits & (1 << i) &&
|
||||||
|
uiMemoryRequirements.memoryTypeBits & (1 << i) &&
|
||||||
|
(memoryProps.memoryTypes[i].propertyFlags & cpuAccessMemoryProps) == cpuAccessMemoryProps
|
||||||
|
)
|
||||||
|
cpuAccessMemTypeIndex = i;
|
||||||
|
}
|
||||||
|
if (optimizedMemTypeIndex == UINT32_MAX)
|
||||||
|
LOG(CRITICAL, "Failed to find GPU memory available for local data. Code: %d", vkResult);
|
||||||
|
if (cpuAccessMemTypeIndex == UINT32_MAX)
|
||||||
|
LOG(CRITICAL, "Failed to find GPU memory available for transfering data. Code: %d", vkResult);
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo allocateWorldVertices {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.allocationSize = worldMemoryRequirements.size,
|
||||||
|
.memoryTypeIndex = optimizedMemTypeIndex
|
||||||
|
};
|
||||||
|
VkMemoryAllocateInfo allocateStagingWorldVertices {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.allocationSize = stagingWorldMemoryRequirements.size,
|
||||||
|
.memoryTypeIndex = cpuAccessMemTypeIndex
|
||||||
|
};
|
||||||
|
VkMemoryAllocateInfo allocateUiVertices {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.allocationSize = uiMemoryRequirements.size,
|
||||||
|
.memoryTypeIndex = cpuAccessMemTypeIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
vkResult = vkAllocateMemory(device, &allocateWorldVertices, nullptr, &worldVerticesMemory);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to allocate GPU memory for world vertices. Code: %d", vkResult);
|
||||||
|
vkResult = vkAllocateMemory(
|
||||||
|
device, &allocateStagingWorldVertices, nullptr, &stagingWorldVerticesMemory);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to allocate GPU memory for staging world vertices. Code: %d", vkResult);
|
||||||
|
vkResult = vkAllocateMemory(device, &allocateUiVertices, nullptr, &uiVerticesMemory);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to allocate GPU memory for UI vertices. Code: %d", vkResult);
|
||||||
|
|
||||||
|
vkResult = vkBindBufferMemory(device, worldVertices, worldVerticesMemory, 0);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to bind GPU memory for world vertices. Code: %d", vkResult);
|
||||||
|
vkResult = vkBindBufferMemory(device, stagingWorldVertices, stagingWorldVerticesMemory, 0);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to bind GPU memory for staging world vertices. Code: %d", vkResult);
|
||||||
|
vkResult = vkBindBufferMemory(device, uiVertices, uiVerticesMemory, 0);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to bind GPU memory for UI vertices. Code: %d", vkResult);
|
||||||
|
|
||||||
|
vkResult = vkMapMemory(
|
||||||
|
device,
|
||||||
|
stagingWorldVerticesMemory,
|
||||||
|
0,
|
||||||
|
stagingWorldVertexBufferConfig.size,
|
||||||
|
0,
|
||||||
|
reinterpret_cast<void**>(&(worldVerticesBinded.data))
|
||||||
|
);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to map staging world vertices buffer to CPU");
|
||||||
|
vkResult = vkMapMemory(
|
||||||
|
device,
|
||||||
|
uiVerticesMemory,
|
||||||
|
0,
|
||||||
|
uiVertexBufferConfig.size,
|
||||||
|
0,
|
||||||
|
reinterpret_cast<void**>(&uiVerticesBinded.data)
|
||||||
|
);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to map UI buffer vertices to CPU");
|
||||||
|
|
||||||
|
memset(worldVerticesBinded.data, 0, stagingWorldVertexBufferConfig.size);
|
||||||
|
memset(uiVerticesBinded.data, 0, uiVertexBufferConfig.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::SetupRenderBuffers()
|
||||||
{
|
{
|
||||||
VkResult vkResult;
|
VkResult vkResult;
|
||||||
|
|
||||||
@ -537,7 +705,7 @@ void Renderer::SetupBuffers()
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandPool == nullptr)
|
if (graphicsCommandPool == nullptr)
|
||||||
{
|
{
|
||||||
VkCommandPoolCreateInfo commandPoolConfig {
|
VkCommandPoolCreateInfo commandPoolConfig {
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
@ -546,22 +714,48 @@ void Renderer::SetupBuffers()
|
|||||||
.queueFamilyIndex = queueFamilies.graphics,
|
.queueFamilyIndex = queueFamilies.graphics,
|
||||||
};
|
};
|
||||||
|
|
||||||
vkResult = vkCreateCommandPool(device, &commandPoolConfig, nullptr, &commandPool);
|
vkResult = vkCreateCommandPool(device, &commandPoolConfig, nullptr, &graphicsCommandPool);
|
||||||
if (vkResult != VK_SUCCESS)
|
if (vkResult != VK_SUCCESS)
|
||||||
LOG(CRITICAL, "Failed to create command pool. Code: %d", vkResult);
|
LOG(CRITICAL, "Failed to create graphics command pool. Code: %d", vkResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
graphicsCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
VkCommandBufferAllocateInfo allocateConfig {
|
VkCommandBufferAllocateInfo allocateConfig {
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.commandPool = commandPool,
|
.commandPool = graphicsCommandPool,
|
||||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, //TODO: reuse some commands using SECONDARY
|
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, //TODO: reuse some commands using SECONDARY
|
||||||
.commandBufferCount = static_cast<uint32_t>(commandBuffers.size())
|
.commandBufferCount = static_cast<uint32_t>(graphicsCommandBuffers.size())
|
||||||
};
|
};
|
||||||
vkResult = vkAllocateCommandBuffers(device, &allocateConfig, commandBuffers.data());
|
vkResult = vkAllocateCommandBuffers(device, &allocateConfig, graphicsCommandBuffers.data());
|
||||||
if (vkResult != VK_SUCCESS)
|
if (vkResult != VK_SUCCESS)
|
||||||
LOG(CRITICAL, "Failed to allocate command buffers. Code: %d", vkResult);
|
LOG(CRITICAL, "Failed to allocate graphics command buffers. Code: %d", vkResult);
|
||||||
|
|
||||||
|
if (transferCommandPool == nullptr)
|
||||||
|
{
|
||||||
|
VkCommandPoolCreateInfo commandPoolConfig {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
|
||||||
|
.queueFamilyIndex = queueFamilies.transfer,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkResult = vkCreateCommandPool(device, &commandPoolConfig, nullptr, &transferCommandPool);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to create transfer command pool. Code: %d", vkResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
transferCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
allocateConfig = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.commandPool = transferCommandPool,
|
||||||
|
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, //TODO: reuse some commands using SECONDARY
|
||||||
|
.commandBufferCount = static_cast<uint32_t>(transferCommandBuffers.size())
|
||||||
|
};
|
||||||
|
vkResult = vkAllocateCommandBuffers(device, &allocateConfig, transferCommandBuffers.data());
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Failed to allocate transfer command buffers. Code: %d", vkResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Draw()
|
void Renderer::Draw()
|
||||||
@ -604,10 +798,10 @@ void Renderer::Draw()
|
|||||||
}
|
}
|
||||||
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
|
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
|
||||||
|
|
||||||
vkResult = vkResetCommandBuffer(commandBuffers[currentFrame], 0);
|
vkResult = vkResetCommandBuffer(graphicsCommandBuffers[currentFrame], 0);
|
||||||
if (vkResult != VK_SUCCESS)
|
if (vkResult != VK_SUCCESS)
|
||||||
LOG(ERROR, "Failed to reset command buffer. Code: %d", vkResult);
|
LOG(ERROR, "Failed to reset command buffer. Code: %d", vkResult);
|
||||||
vkResult = vkBeginCommandBuffer(commandBuffers[currentFrame], &drawConfig.commandBeginConfig);
|
vkResult = vkBeginCommandBuffer(graphicsCommandBuffers[currentFrame], &drawConfig.commandBeginConfig);
|
||||||
if (vkResult != VK_SUCCESS)
|
if (vkResult != VK_SUCCESS)
|
||||||
LOG(ERROR, "Failed to begin command buffer. Code: %d", vkResult);
|
LOG(ERROR, "Failed to begin command buffer. Code: %d", vkResult);
|
||||||
|
|
||||||
@ -619,7 +813,7 @@ void Renderer::Draw()
|
|||||||
};
|
};
|
||||||
|
|
||||||
vkCmdBeginRenderPass(
|
vkCmdBeginRenderPass(
|
||||||
commandBuffers[currentFrame],
|
graphicsCommandBuffers[currentFrame],
|
||||||
&drawConfig.renderPassBeginConfig,
|
&drawConfig.renderPassBeginConfig,
|
||||||
VK_SUBPASS_CONTENTS_INLINE
|
VK_SUBPASS_CONTENTS_INLINE
|
||||||
);
|
);
|
||||||
@ -632,26 +826,41 @@ void Renderer::Draw()
|
|||||||
if (pipeline != lastPipeline)
|
if (pipeline != lastPipeline)
|
||||||
{
|
{
|
||||||
vkCmdBindPipeline(
|
vkCmdBindPipeline(
|
||||||
commandBuffers[currentFrame],
|
graphicsCommandBuffers[currentFrame],
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
pipeline->instance
|
pipeline->instance
|
||||||
);
|
);
|
||||||
vkCmdSetViewport(commandBuffers[currentFrame], 0, 1, &pipeline->viewport);
|
vkCmdSetViewport(graphicsCommandBuffers[currentFrame], 0, 1, &pipeline->viewport);
|
||||||
vkCmdSetScissor(commandBuffers[currentFrame], 0, 1, &pipeline->scissors);
|
vkCmdSetScissor(graphicsCommandBuffers[currentFrame], 0, 1, &pipeline->scissors);
|
||||||
lastPipeline = pipeline;
|
lastPipeline = pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<VkBuffer> vertexBuffers;
|
||||||
|
vertexBuffers.reserve(1);
|
||||||
|
if (object.isUI)
|
||||||
|
vertexBuffers.push_back(uiVertices);
|
||||||
|
else
|
||||||
|
vertexBuffers.push_back(worldVertices);
|
||||||
|
VkDeviceSize offsets[] = {object.mesh.verticesBufferPosition};
|
||||||
|
vkCmdBindVertexBuffers(
|
||||||
|
graphicsCommandBuffers[currentFrame],
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
vertexBuffers.data(),
|
||||||
|
offsets
|
||||||
|
);
|
||||||
|
|
||||||
vkCmdDraw(
|
vkCmdDraw(
|
||||||
commandBuffers[currentFrame],
|
graphicsCommandBuffers[currentFrame],
|
||||||
object.mesh.vertexCount,
|
static_cast<uint32_t>(object.mesh.vertices.size()),
|
||||||
static_cast<uint32_t>(object.transforms.size()),
|
static_cast<uint32_t>(object.transforms.size()),
|
||||||
0, // TODO: batching
|
0, // TODO: batching
|
||||||
0 // TODO: batching
|
0 // TODO: batching
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdEndRenderPass(commandBuffers[currentFrame]);
|
vkCmdEndRenderPass(graphicsCommandBuffers[currentFrame]);
|
||||||
vkResult = vkEndCommandBuffer(commandBuffers[currentFrame]);
|
vkResult = vkEndCommandBuffer(graphicsCommandBuffers[currentFrame]);
|
||||||
if (vkResult != VK_SUCCESS)
|
if (vkResult != VK_SUCCESS)
|
||||||
LOG(ERROR, "Failed to end command buffer. Code: %d", vkResult);
|
LOG(ERROR, "Failed to end command buffer. Code: %d", vkResult);
|
||||||
|
|
||||||
@ -662,7 +871,7 @@ void Renderer::Draw()
|
|||||||
drawConfig.submitConfig.pWaitSemaphores = waitSemaphores;
|
drawConfig.submitConfig.pWaitSemaphores = waitSemaphores;
|
||||||
//drawConfig.submitConfig.pSignalSemaphores = &renderFinished[currentFrame];
|
//drawConfig.submitConfig.pSignalSemaphores = &renderFinished[currentFrame];
|
||||||
drawConfig.submitConfig.pSignalSemaphores =signalSemaphores;
|
drawConfig.submitConfig.pSignalSemaphores =signalSemaphores;
|
||||||
drawConfig.submitConfig.pCommandBuffers = &commandBuffers[currentFrame];
|
drawConfig.submitConfig.pCommandBuffers = &graphicsCommandBuffers[currentFrame];
|
||||||
drawConfig.submitConfig.pWaitDstStageMask = waitStages;
|
drawConfig.submitConfig.pWaitDstStageMask = waitStages;
|
||||||
|
|
||||||
vkResult = vkResetFences(device, 1, &inFlightFences[currentFrame]);
|
vkResult = vkResetFences(device, 1, &inFlightFences[currentFrame]);
|
||||||
@ -699,6 +908,54 @@ void Renderer::Draw()
|
|||||||
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::CopyBuffer(VkBuffer src, size_t offset, VkBuffer dst, VkDeviceSize size)
|
||||||
|
{
|
||||||
|
VkResult vkResult;
|
||||||
|
|
||||||
|
VkCommandBufferAllocateInfo bufferAllocateConfig {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
|
.commandPool = transferCommandPool,
|
||||||
|
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkCommandBuffer commandBuffer;
|
||||||
|
vkResult = vkAllocateCommandBuffers(device, &bufferAllocateConfig, &commandBuffer);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(ERROR, "Failed to allocate temporary command buffer for copy operation. Code: %d", vkResult);
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo commandBeginConfig {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
||||||
|
};
|
||||||
|
vkResult = vkBeginCommandBuffer(commandBuffer, &commandBeginConfig);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(ERROR, "Failed to begin command for copy operation. Code: %d", vkResult);
|
||||||
|
|
||||||
|
VkBufferCopy copyRegion {
|
||||||
|
.srcOffset = offset,
|
||||||
|
.dstOffset = offset,
|
||||||
|
.size = size
|
||||||
|
};
|
||||||
|
vkCmdCopyBuffer(commandBuffer, src, dst, 1, ©Region);
|
||||||
|
|
||||||
|
vkResult = vkEndCommandBuffer(commandBuffer);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(ERROR, "Failed to end command for copy operation. Code: %d", vkResult);
|
||||||
|
|
||||||
|
VkSubmitInfo submitConfig {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
.pCommandBuffers = &commandBuffer
|
||||||
|
};
|
||||||
|
vkQueueSubmit(queues.transfer, 1, &submitConfig, VK_NULL_HANDLE); //TODO: use fence for optimizatoin
|
||||||
|
vkQueueWaitIdle(queues.transfer);
|
||||||
|
|
||||||
|
vkFreeCommandBuffers(device, transferCommandPool, 1, &commandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::SetupSync()
|
void Renderer::SetupSync()
|
||||||
{
|
{
|
||||||
VkResult vkResult;
|
VkResult vkResult;
|
||||||
@ -764,10 +1021,10 @@ void Renderer::Init()
|
|||||||
SetupDevice();
|
SetupDevice();
|
||||||
SetupSwapchain();
|
SetupSwapchain();
|
||||||
SetupRenderPasses();
|
SetupRenderPasses();
|
||||||
|
SetupPipelines();
|
||||||
pipelineFactory = Allocate<PipelineFactory>(baseMaterial, baseRenderPass, device, surfaceInfo.extent);
|
SetupObjectsBuffers();
|
||||||
|
SetupRenderBuffers();
|
||||||
SetupBuffers();
|
CopyBuffer(stagingWorldVertices, 0, worldVertices, worldVerticesBinded.size * worldVerticesBinded.ELEMENT_SIZE);
|
||||||
SetupSync();
|
SetupSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,7 +1060,23 @@ void Renderer::ProcessCommand(const RenderCommand &command)
|
|||||||
|
|
||||||
for (size_t i = 0; i < command.objectsSize; i++)
|
for (size_t i = 0; i < command.objectsSize; i++)
|
||||||
{
|
{
|
||||||
objects.insert(command.objects[i]);
|
RenderObject &object = command.objects[i];
|
||||||
|
object.engineId = static_cast<uint32_t>(objects.size());
|
||||||
|
if (objects.contains(object)) continue;
|
||||||
|
|
||||||
|
// TODO: combine vertices data and write with one Write out of loop
|
||||||
|
size_t verticesPos = worldVerticesBinded.Write(
|
||||||
|
object.mesh.vertices.data(),
|
||||||
|
object.mesh.vertices.size()
|
||||||
|
) * worldVerticesBinded.ELEMENT_SIZE;
|
||||||
|
object.mesh.verticesBufferPosition = verticesPos;
|
||||||
|
CopyBuffer(
|
||||||
|
stagingWorldVertices,
|
||||||
|
verticesPos,
|
||||||
|
worldVertices,
|
||||||
|
object.mesh.vertices.size() * worldVerticesBinded.ELEMENT_SIZE
|
||||||
|
);
|
||||||
|
objects.insert(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -864,6 +1137,17 @@ void Renderer::Release()
|
|||||||
|
|
||||||
ReleaseSwapchain();
|
ReleaseSwapchain();
|
||||||
|
|
||||||
|
vkUnmapMemory(device, stagingWorldVerticesMemory);
|
||||||
|
vkUnmapMemory(device, uiVerticesMemory);
|
||||||
|
|
||||||
|
vkDestroyBuffer(device, worldVertices, nullptr);
|
||||||
|
vkDestroyBuffer(device, stagingWorldVertices, nullptr);
|
||||||
|
vkDestroyBuffer(device, uiVertices, nullptr);
|
||||||
|
|
||||||
|
vkFreeMemory(device, worldVerticesMemory, nullptr);
|
||||||
|
vkFreeMemory(device, stagingWorldVerticesMemory, nullptr);
|
||||||
|
vkFreeMemory(device, uiVerticesMemory, nullptr);
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||||
{
|
{
|
||||||
vkDestroySemaphore(device, renderFinished[i], nullptr);
|
vkDestroySemaphore(device, renderFinished[i], nullptr);
|
||||||
@ -871,7 +1155,8 @@ void Renderer::Release()
|
|||||||
vkDestroyFence(device, inFlightFences[i], nullptr);
|
vkDestroyFence(device, inFlightFences[i], nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkDestroyCommandPool(device, commandPool, nullptr);
|
vkDestroyCommandPool(device, graphicsCommandPool, nullptr);
|
||||||
|
vkDestroyCommandPool(device, transferCommandPool, nullptr);
|
||||||
|
|
||||||
vkDestroyDevice(device, nullptr);
|
vkDestroyDevice(device, nullptr);
|
||||||
vkDestroySurfaceKHR(vulkan, surface, nullptr);
|
vkDestroySurfaceKHR(vulkan, surface, nullptr);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ int main(int argc, char **argv)
|
|||||||
assetManager.LoadAsync(AssetInfo::MATERIAL, "assets/materials/helloworld.mat");
|
assetManager.LoadAsync(AssetInfo::MATERIAL, "assets/materials/helloworld.mat");
|
||||||
AssetHandle baseMaterialHandle = assetManager.Find("assets/materials/helloworld.mat");
|
AssetHandle baseMaterialHandle = assetManager.Find("assets/materials/helloworld.mat");
|
||||||
AssetMaterial baseMaterial = assetManager.Get<AssetMaterial>(baseMaterialHandle);
|
AssetMaterial baseMaterial = assetManager.Get<AssetMaterial>(baseMaterialHandle);
|
||||||
Renderer renderer(window, baseMaterial);
|
Renderer renderer(window, baseMaterial, 1000000); //TODO: buffer sizes
|
||||||
renderer.Start();
|
renderer.Start();
|
||||||
|
|
||||||
//Setup Engine
|
//Setup Engine
|
||||||
@ -49,11 +49,30 @@ int main(int argc, char **argv)
|
|||||||
// Test render obj
|
// Test render obj
|
||||||
RenderObject triangle {
|
RenderObject triangle {
|
||||||
.transforms = {{.x = 0, .y = 0}},
|
.transforms = {{.x = 0, .y = 0}},
|
||||||
.mesh = {.vertexCount = 3},
|
.mesh = {
|
||||||
|
.vertices = {
|
||||||
|
{.pos = {-0.5f, -0.5f}, .color = {1.0f, 0.0f, 0.0f}},
|
||||||
|
{.pos = {0.0f, 0.5f}, .color = {0.0f, 0.0f, 0.0f}},
|
||||||
|
{.pos = {-1.0f, 0.5f}, .color = {1.0f, 1.0f, 1.0f}}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
.material = baseMaterial,
|
.material = baseMaterial,
|
||||||
};
|
};
|
||||||
renderer.RegisterObjects(&triangle, 1);
|
RenderObject triangle2 {
|
||||||
|
.transforms = {{.x = 0, .y = 0}},
|
||||||
|
.mesh = {
|
||||||
|
.vertices = {
|
||||||
|
{.pos = {0.0f, -0.5f}, .color = {1.0f, 0.0f, 0.0f}},
|
||||||
|
{.pos = {0.5f, 0.5f}, .color = {0.0f, 1.0f, 0.0f}},
|
||||||
|
{.pos = {-0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.material = baseMaterial,
|
||||||
|
};
|
||||||
|
RenderObject objs[] = {triangle, triangle2};
|
||||||
|
renderer.RegisterObjects(objs, 2);
|
||||||
|
|
||||||
// Process GLFW events
|
// Process GLFW events
|
||||||
while(!glfwWindowShouldClose(window))
|
while(!glfwWindowShouldClose(window))
|
||||||
|
|||||||
@ -1,21 +1,12 @@
|
|||||||
#version 450
|
#version 450
|
||||||
#extension GL_ARB_separate_shader_objects : enable
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 inPosition;
|
||||||
|
layout(location = 1) in vec3 inColor;
|
||||||
|
|
||||||
layout(location = 0) out vec3 fragColor;
|
layout(location = 0) out vec3 fragColor;
|
||||||
|
|
||||||
vec2 positions[3] = vec2[](
|
|
||||||
vec2(0.0, -0.5),
|
|
||||||
vec2(0.5, 0.5),
|
|
||||||
vec2(-0.5, 0.5)
|
|
||||||
);
|
|
||||||
|
|
||||||
vec3 colors[3] = vec3[](
|
|
||||||
vec3(1.0, 0.0, 0.0),
|
|
||||||
vec3(0.0, 1.0, 0.0),
|
|
||||||
vec3(0.0, 0.0, 1.0)
|
|
||||||
);
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
gl_Position = vec4(inPosition, 0.0, 1.0);
|
||||||
fragColor = colors[gl_VertexIndex];
|
fragColor = inColor;
|
||||||
}
|
}
|
||||||
@ -6,6 +6,7 @@
|
|||||||
"entt",
|
"entt",
|
||||||
"vulkan",
|
"vulkan",
|
||||||
"glfw3",
|
"glfw3",
|
||||||
|
"glm",
|
||||||
"rmlui",
|
"rmlui",
|
||||||
"gtest"
|
"gtest"
|
||||||
]
|
]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user