mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Add support for multiple pipelines
This commit is contained in:
parent
d6522730ae
commit
a24b951df1
@ -45,7 +45,7 @@ namespace engine::gfx {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// handles (incomplete types)
|
// handles (incomplete types)
|
||||||
|
struct Pipeline;
|
||||||
struct VertexBuffer;
|
struct VertexBuffer;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,14 @@ namespace engine {
|
|||||||
~GFXDevice();
|
~GFXDevice();
|
||||||
|
|
||||||
// adds a vertex buffer draw call to the queue
|
// adds a vertex buffer draw call to the queue
|
||||||
void drawBuffer(const gfx::VertexBuffer* vb);
|
void drawBuffer(const gfx::Pipeline* pipeline, const gfx::VertexBuffer* vb);
|
||||||
|
|
||||||
// Call once per frame. Executes all queued draw calls and renders to the screen.
|
// Call once per frame. Executes all queued draw calls and renders to the screen.
|
||||||
void draw();
|
void draw();
|
||||||
|
|
||||||
// creates the equivalent of an OpenGL shader program & vertex attrib configuration
|
// creates the equivalent of an OpenGL shader program & vertex attrib configuration
|
||||||
void createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat);
|
gfx::Pipeline* createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat);
|
||||||
|
void destroyPipeline(const gfx::Pipeline* pipeline);
|
||||||
|
|
||||||
// creates a vertex array for holding mesh data
|
// creates a vertex array for holding mesh data
|
||||||
gfx::VertexBuffer* createVertexBuffer(uint32_t size, const void* vertices, const void* indices);
|
gfx::VertexBuffer* createVertexBuffer(uint32_t size, const void* vertices, const void* indices);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
static engine::gfx::Pipeline* pipeline;
|
||||||
static engine::gfx::VertexBuffer* buffer;
|
static engine::gfx::VertexBuffer* buffer;
|
||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
@ -17,22 +18,16 @@ namespace engine {
|
|||||||
m_gfx = std::make_unique<GFXDevice>(appName, appVersion, m_win->getHandle());
|
m_gfx = std::make_unique<GFXDevice>(appName, appVersion, m_win->getHandle());
|
||||||
|
|
||||||
engine::ResourceManager resMan{};
|
engine::ResourceManager resMan{};
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
glm::vec2 pos;
|
glm::vec2 pos;
|
||||||
glm::vec3 col;
|
glm::vec3 col;
|
||||||
};
|
};
|
||||||
|
|
||||||
gfx::VertexFormat vertFormat{
|
gfx::VertexFormat vertFormat{
|
||||||
.stride = (uint32_t)sizeof(Vertex),
|
.stride = (uint32_t)sizeof(Vertex),
|
||||||
};
|
};
|
||||||
|
|
||||||
vertFormat.attributeDescriptions.push_back({0, gfx::VertexAttribFormat::VEC2, 0});
|
vertFormat.attributeDescriptions.push_back({0, gfx::VertexAttribFormat::VEC2, 0});
|
||||||
vertFormat.attributeDescriptions.push_back({1, gfx::VertexAttribFormat::VEC3, offsetof(Vertex, col)});
|
vertFormat.attributeDescriptions.push_back({1, gfx::VertexAttribFormat::VEC3, offsetof(Vertex, col)});
|
||||||
|
pipeline = m_gfx->createPipeline(resMan.getFilePath("shader.vert.spv").string().c_str(), resMan.getFilePath("shader.frag.spv").string().c_str(), vertFormat);
|
||||||
m_gfx->createPipeline(resMan.getFilePath("shader.vert.spv").string().c_str(), resMan.getFilePath("shader.frag.spv").string().c_str(), vertFormat);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const std::vector<Vertex> vertices = {
|
const std::vector<Vertex> vertices = {
|
||||||
{ { 0.0f, -0.5f}, {1.0f, 0.0f, 0.0f} },
|
{ { 0.0f, -0.5f}, {1.0f, 0.0f, 0.0f} },
|
||||||
@ -44,17 +39,12 @@ namespace engine {
|
|||||||
};
|
};
|
||||||
buffer = m_gfx->createVertexBuffer(sizeof(Vertex) * vertices.size(), vertices.data(), indices.data());
|
buffer = m_gfx->createVertexBuffer(sizeof(Vertex) * vertices.size(), vertices.data(), indices.data());
|
||||||
|
|
||||||
const std::vector<Vertex> vertices2 = {
|
|
||||||
{ { 0.9f, -0.9f}, {1.0f, 0.0f, 0.0f} },
|
|
||||||
{ { 0.9f, -0.8f}, {1.0f, 0.0f, 0.0f} },
|
|
||||||
{ { 0.8f, -0.9f}, {1.0f, 0.0f, 0.0f} }
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application()
|
Application::~Application()
|
||||||
{
|
{
|
||||||
m_gfx->destroyVertexBuffer(buffer);
|
m_gfx->destroyVertexBuffer(buffer);
|
||||||
|
m_gfx->destroyPipeline(pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::gameLoop()
|
void Application::gameLoop()
|
||||||
@ -86,7 +76,7 @@ namespace engine {
|
|||||||
|
|
||||||
/* draw */
|
/* draw */
|
||||||
|
|
||||||
m_gfx->drawBuffer(buffer);
|
m_gfx->drawBuffer(pipeline, buffer);
|
||||||
|
|
||||||
m_gfx->draw();
|
m_gfx->draw();
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
|
|
||||||
@ -65,11 +66,6 @@ namespace engine {
|
|||||||
VkSemaphore releaseSemaphore = VK_NULL_HANDLE; // waits until rendering finishes
|
VkSemaphore releaseSemaphore = VK_NULL_HANDLE; // waits until rendering finishes
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Pipeline {
|
|
||||||
VkPipelineLayout layout = VK_NULL_HANDLE;
|
|
||||||
VkPipeline handle = VK_NULL_HANDLE;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class QueueFlags : uint32_t {
|
enum class QueueFlags : uint32_t {
|
||||||
GRAPHICS = (1 << 0),
|
GRAPHICS = (1 << 0),
|
||||||
TRANSFER = (1 << 1),
|
TRANSFER = (1 << 1),
|
||||||
@ -84,6 +80,11 @@ namespace engine {
|
|||||||
uint32_t size;
|
uint32_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct gfx::Pipeline {
|
||||||
|
VkPipelineLayout layout = VK_NULL_HANDLE;
|
||||||
|
VkPipeline handle = VK_NULL_HANDLE;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// enum converters
|
// enum converters
|
||||||
@ -595,9 +596,7 @@ namespace engine {
|
|||||||
|
|
||||||
VkFence inFlightFence = VK_NULL_HANDLE;
|
VkFence inFlightFence = VK_NULL_HANDLE;
|
||||||
|
|
||||||
Pipeline pipeline{};
|
std::map<const gfx::Pipeline*, std::queue<const gfx::VertexBuffer*>> drawQueues{};
|
||||||
|
|
||||||
std::queue<const gfx::VertexBuffer*> drawQueue{};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -995,11 +994,6 @@ namespace engine {
|
|||||||
{
|
{
|
||||||
TRACE("Destroying GFXDevice...");
|
TRACE("Destroying GFXDevice...");
|
||||||
|
|
||||||
if (pimpl->pipeline.handle != VK_NULL_HANDLE) {
|
|
||||||
vkDestroyPipeline(pimpl->device, pimpl->pipeline.handle, nullptr);
|
|
||||||
vkDestroyPipelineLayout(pimpl->device, pimpl->pipeline.layout, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
vkDestroyFence(pimpl->device, pimpl->inFlightFence, nullptr);
|
vkDestroyFence(pimpl->device, pimpl->inFlightFence, nullptr);
|
||||||
|
|
||||||
vkDestroySemaphore(pimpl->device, pimpl->swapchain.releaseSemaphore, nullptr);
|
vkDestroySemaphore(pimpl->device, pimpl->swapchain.releaseSemaphore, nullptr);
|
||||||
@ -1022,9 +1016,9 @@ namespace engine {
|
|||||||
vkDestroyInstance(pimpl->instance, nullptr);
|
vkDestroyInstance(pimpl->instance, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::drawBuffer(const gfx::VertexBuffer* vb)
|
void GFXDevice::drawBuffer(const gfx::Pipeline* pipeline, const gfx::VertexBuffer* vb)
|
||||||
{
|
{
|
||||||
pimpl->drawQueue.push(vb);
|
pimpl->drawQueues[pipeline].push(vb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::draw()
|
void GFXDevice::draw()
|
||||||
@ -1087,19 +1081,20 @@ namespace engine {
|
|||||||
|
|
||||||
// run queued draw calls
|
// run queued draw calls
|
||||||
|
|
||||||
vkCmdBindPipeline(pimpl->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pimpl->pipeline.handle);
|
|
||||||
VkDeviceSize offsets[] = { 0 };
|
VkDeviceSize offsets[] = { 0 };
|
||||||
while (pimpl->drawQueue.empty() == false) {
|
|
||||||
|
|
||||||
const auto* buffer = pimpl->drawQueue.front();
|
|
||||||
|
|
||||||
vkCmdBindVertexBuffers(pimpl->commandBuffer, 0, 1, &buffer->buffer, offsets);
|
|
||||||
vkCmdDraw(pimpl->commandBuffer, buffer->size, 1, 0, 0);
|
|
||||||
|
|
||||||
pimpl->drawQueue.pop();
|
|
||||||
|
|
||||||
|
for (auto& [pipeline, queue] : pimpl->drawQueues) {
|
||||||
|
vkCmdBindPipeline(pimpl->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
|
||||||
|
while (queue.empty() == false) {
|
||||||
|
const gfx::VertexBuffer* buffer = queue.front();
|
||||||
|
vkCmdBindVertexBuffers(pimpl->commandBuffer, 0, 1, &buffer->buffer, offsets);
|
||||||
|
vkCmdDraw(pimpl->commandBuffer, buffer->size, 1, 0, 0);
|
||||||
|
queue.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pimpl->drawQueues.clear();
|
||||||
|
|
||||||
vkCmdEndRenderPass(pimpl->commandBuffer);
|
vkCmdEndRenderPass(pimpl->commandBuffer);
|
||||||
|
|
||||||
res = vkEndCommandBuffer(pimpl->commandBuffer);
|
res = vkEndCommandBuffer(pimpl->commandBuffer);
|
||||||
@ -1141,11 +1136,13 @@ namespace engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat)
|
gfx::Pipeline* GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat)
|
||||||
{
|
{
|
||||||
|
|
||||||
VkResult res;
|
VkResult res;
|
||||||
|
|
||||||
|
gfx::Pipeline* pipeline = new gfx::Pipeline;
|
||||||
|
|
||||||
// get vertex attrib layout:
|
// get vertex attrib layout:
|
||||||
VkVertexInputBindingDescription bindingDescription{ };
|
VkVertexInputBindingDescription bindingDescription{ };
|
||||||
bindingDescription.binding = 0;
|
bindingDescription.binding = 0;
|
||||||
@ -1281,7 +1278,7 @@ namespace engine {
|
|||||||
layoutInfo.pushConstantRangeCount = 0;
|
layoutInfo.pushConstantRangeCount = 0;
|
||||||
layoutInfo.pPushConstantRanges = nullptr;
|
layoutInfo.pPushConstantRanges = nullptr;
|
||||||
|
|
||||||
res = vkCreatePipelineLayout(pimpl->device, &layoutInfo, nullptr, &pimpl->pipeline.layout);
|
res = vkCreatePipelineLayout(pimpl->device, &layoutInfo, nullptr, &pipeline->layout);
|
||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo createInfo{};
|
VkGraphicsPipelineCreateInfo createInfo{};
|
||||||
@ -1296,18 +1293,29 @@ namespace engine {
|
|||||||
createInfo.pDepthStencilState = nullptr;
|
createInfo.pDepthStencilState = nullptr;
|
||||||
createInfo.pColorBlendState = &colorBlending;
|
createInfo.pColorBlendState = &colorBlending;
|
||||||
createInfo.pDynamicState = &dynamicState;
|
createInfo.pDynamicState = &dynamicState;
|
||||||
createInfo.layout = pimpl->pipeline.layout;
|
createInfo.layout = pipeline->layout;
|
||||||
createInfo.renderPass = pimpl->swapchain.renderpass;
|
createInfo.renderPass = pimpl->swapchain.renderpass;
|
||||||
createInfo.subpass = 0;
|
createInfo.subpass = 0;
|
||||||
createInfo.basePipelineHandle = VK_NULL_HANDLE;
|
createInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||||
createInfo.basePipelineIndex = -1;
|
createInfo.basePipelineIndex = -1;
|
||||||
|
|
||||||
res = vkCreateGraphicsPipelines(pimpl->device, VK_NULL_HANDLE, 1, &createInfo, nullptr, &pimpl->pipeline.handle);
|
res = vkCreateGraphicsPipelines(pimpl->device, VK_NULL_HANDLE, 1, &createInfo, nullptr, &pipeline->handle);
|
||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
vkDestroyShaderModule(pimpl->device, fragShaderModule, nullptr);
|
vkDestroyShaderModule(pimpl->device, fragShaderModule, nullptr);
|
||||||
vkDestroyShaderModule(pimpl->device, vertShaderModule, nullptr);
|
vkDestroyShaderModule(pimpl->device, vertShaderModule, nullptr);
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXDevice::destroyPipeline(const gfx::Pipeline* pipeline)
|
||||||
|
{
|
||||||
|
|
||||||
|
vkDestroyPipeline(pimpl->device, pipeline->handle, nullptr);
|
||||||
|
vkDestroyPipelineLayout(pimpl->device, pipeline->layout, nullptr);
|
||||||
|
|
||||||
|
delete pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::VertexBuffer* GFXDevice::createVertexBuffer(uint32_t size, const void* vertices, const void* indices)
|
gfx::VertexBuffer* GFXDevice::createVertexBuffer(uint32_t size, const void* vertices, const void* indices)
|
||||||
|
Loading…
Reference in New Issue
Block a user