mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Add indexed buffer support
This commit is contained in:
parent
a24b951df1
commit
ce12534ad8
@ -46,6 +46,6 @@ namespace engine::gfx {
|
|||||||
|
|
||||||
// handles (incomplete types)
|
// handles (incomplete types)
|
||||||
struct Pipeline;
|
struct Pipeline;
|
||||||
struct VertexBuffer;
|
struct Buffer;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,18 +20,19 @@ 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::Pipeline* pipeline, const gfx::VertexBuffer* vb);
|
void drawBuffer(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, uint32_t count);
|
||||||
|
|
||||||
|
void drawIndexed(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t indexCount);
|
||||||
|
|
||||||
// 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 renderFrame();
|
||||||
|
|
||||||
// creates the equivalent of an OpenGL shader program & vertex attrib configuration
|
// creates the equivalent of an OpenGL shader program & vertex attrib configuration
|
||||||
gfx::Pipeline* 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);
|
void destroyPipeline(const gfx::Pipeline* pipeline);
|
||||||
|
|
||||||
// creates a vertex array for holding mesh data
|
gfx::Buffer* createBuffer(gfx::BufferType type, uint64_t size, const void* data);
|
||||||
gfx::VertexBuffer* createVertexBuffer(uint32_t size, const void* vertices, const void* indices);
|
void destroyBuffer(const gfx::Buffer* buffer);
|
||||||
void destroyVertexBuffer(const gfx::VertexBuffer* buffer);
|
|
||||||
|
|
||||||
// wait until all the active GPU queues have finished working
|
// wait until all the active GPU queues have finished working
|
||||||
void waitIdle();
|
void waitIdle();
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
static engine::gfx::Pipeline* pipeline;
|
static engine::gfx::Pipeline* pipeline;
|
||||||
static engine::gfx::VertexBuffer* buffer;
|
static engine::gfx::Buffer* vb;
|
||||||
|
static engine::gfx::Buffer* ib;
|
||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
|
|
||||||
@ -30,20 +31,23 @@ namespace engine {
|
|||||||
pipeline = m_gfx->createPipeline(resMan.getFilePath("shader.vert.spv").string().c_str(), resMan.getFilePath("shader.frag.spv").string().c_str(), vertFormat);
|
pipeline = 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.5f, -0.5f}, {1.0f, 0.0f, 0.0f} },
|
||||||
{ { 0.5f, 0.5f}, {0.0f, 1.0f, 0.0f} },
|
{ { 0.5f, 0.5f}, {0.0f, 1.0f, 0.0f} },
|
||||||
{ {-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f} }
|
{ {-0.5f, -0.5f}, {0.0f, 0.0f, 1.0f} },
|
||||||
|
{ {-0.5f, 0.5f}, {0.0f, 1.0f, 1.0f} },
|
||||||
};
|
};
|
||||||
const std::vector<uint16_t> indices{
|
vb = m_gfx->createBuffer(gfx::BufferType::VERTEX, sizeof(Vertex) * vertices.size(), vertices.data());
|
||||||
0, 1, 2,
|
const std::vector<uint16_t> indices = {
|
||||||
|
0, 1, 2, 2, 1, 3,
|
||||||
};
|
};
|
||||||
buffer = m_gfx->createVertexBuffer(sizeof(Vertex) * vertices.size(), vertices.data(), indices.data());
|
ib = m_gfx->createBuffer(gfx::BufferType::INDEX, sizeof(uint16_t) * indices.size(), indices.data());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application()
|
Application::~Application()
|
||||||
{
|
{
|
||||||
m_gfx->destroyVertexBuffer(buffer);
|
m_gfx->destroyBuffer(vb);
|
||||||
|
m_gfx->destroyBuffer(ib);
|
||||||
m_gfx->destroyPipeline(pipeline);
|
m_gfx->destroyPipeline(pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,9 +80,9 @@ namespace engine {
|
|||||||
|
|
||||||
/* draw */
|
/* draw */
|
||||||
|
|
||||||
m_gfx->drawBuffer(pipeline, buffer);
|
m_gfx->drawIndexed(pipeline, vb, ib, 6);
|
||||||
|
|
||||||
m_gfx->draw();
|
m_gfx->renderFrame();
|
||||||
|
|
||||||
/* poll events */
|
/* poll events */
|
||||||
m_win->getInputAndEvents();
|
m_win->getInputAndEvents();
|
||||||
|
@ -57,19 +57,41 @@ namespace engine {
|
|||||||
GFXDevice::~GFXDevice()
|
GFXDevice::~GFXDevice()
|
||||||
{
|
{
|
||||||
TRACE("Destroying GFXDevice...");
|
TRACE("Destroying GFXDevice...");
|
||||||
|
|
||||||
|
SDL_GL_DeleteContext(pimpl->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::draw()
|
void GFXDevice::drawBuffer(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, uint32_t count)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath)
|
void GFXDevice::drawIndexed(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t indexCount)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GFXDevice::createBuffer(const gfx::BufferDesc& desc, const void* data, gfx::BufferHandle* out)
|
void GFXDevice::renderFrame()
|
||||||
{
|
{
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Pipeline* GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXDevice::destroyPipeline(const gfx::Pipeline* pipeline)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Buffer* GFXDevice::createBuffer(gfx::BufferType type, uint64_t size, const void* data)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXDevice::destroyBuffer(const gfx::Buffer* buffer)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::waitIdle()
|
void GFXDevice::waitIdle()
|
||||||
|
@ -66,6 +66,12 @@ namespace engine {
|
|||||||
VkSemaphore releaseSemaphore = VK_NULL_HANDLE; // waits until rendering finishes
|
VkSemaphore releaseSemaphore = VK_NULL_HANDLE; // waits until rendering finishes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DrawCall {
|
||||||
|
const gfx::Buffer* vertexBuffer = nullptr;
|
||||||
|
const gfx::Buffer* indexBuffer = nullptr; // if this is nullptr, don't use indexed
|
||||||
|
uint32_t count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
enum class QueueFlags : uint32_t {
|
enum class QueueFlags : uint32_t {
|
||||||
GRAPHICS = (1 << 0),
|
GRAPHICS = (1 << 0),
|
||||||
TRANSFER = (1 << 1),
|
TRANSFER = (1 << 1),
|
||||||
@ -74,10 +80,11 @@ namespace engine {
|
|||||||
|
|
||||||
// handles
|
// handles
|
||||||
|
|
||||||
struct gfx::VertexBuffer {
|
struct gfx::Buffer {
|
||||||
|
gfx::BufferType type;
|
||||||
VkBuffer buffer = VK_NULL_HANDLE;
|
VkBuffer buffer = VK_NULL_HANDLE;
|
||||||
VmaAllocation allocation = nullptr;
|
VmaAllocation allocation = nullptr;
|
||||||
uint32_t size;
|
VkDeviceSize size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gfx::Pipeline {
|
struct gfx::Pipeline {
|
||||||
@ -101,6 +108,18 @@ namespace engine {
|
|||||||
}
|
}
|
||||||
throw std::runtime_error("Unknown vertex attribute format");
|
throw std::runtime_error("Unknown vertex attribute format");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case gfx::BufferType::VERTEX:
|
||||||
|
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||||
|
case gfx::BufferType::INDEX:
|
||||||
|
return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Unknown buffer type");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
@ -596,7 +615,7 @@ namespace engine {
|
|||||||
|
|
||||||
VkFence inFlightFence = VK_NULL_HANDLE;
|
VkFence inFlightFence = VK_NULL_HANDLE;
|
||||||
|
|
||||||
std::map<const gfx::Pipeline*, std::queue<const gfx::VertexBuffer*>> drawQueues{};
|
std::map<const gfx::Pipeline*, std::queue<DrawCall>> drawQueues{};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1016,12 +1035,34 @@ namespace engine {
|
|||||||
vkDestroyInstance(pimpl->instance, nullptr);
|
vkDestroyInstance(pimpl->instance, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::drawBuffer(const gfx::Pipeline* pipeline, const gfx::VertexBuffer* vb)
|
void GFXDevice::drawBuffer(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, uint32_t count)
|
||||||
{
|
{
|
||||||
pimpl->drawQueues[pipeline].push(vb);
|
assert(vertexBuffer->type == gfx::BufferType::VERTEX);
|
||||||
|
|
||||||
|
DrawCall call{
|
||||||
|
.vertexBuffer = vertexBuffer,
|
||||||
|
.indexBuffer = nullptr, // don't use indexed drawing
|
||||||
|
.count = count,
|
||||||
|
};
|
||||||
|
|
||||||
|
pimpl->drawQueues[pipeline].push(call);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::draw()
|
void GFXDevice::drawIndexed(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t count)
|
||||||
|
{
|
||||||
|
assert(vertexBuffer->type == gfx::BufferType::VERTEX);
|
||||||
|
assert(indexBuffer->type == gfx::BufferType::INDEX);
|
||||||
|
|
||||||
|
DrawCall call{
|
||||||
|
.vertexBuffer = vertexBuffer,
|
||||||
|
.indexBuffer = indexBuffer, // don't use indexed drawing
|
||||||
|
.count = count,
|
||||||
|
};
|
||||||
|
|
||||||
|
pimpl->drawQueues[pipeline].push(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXDevice::renderFrame()
|
||||||
{
|
{
|
||||||
VkResult res;
|
VkResult res;
|
||||||
|
|
||||||
@ -1086,9 +1127,15 @@ namespace engine {
|
|||||||
for (auto& [pipeline, queue] : pimpl->drawQueues) {
|
for (auto& [pipeline, queue] : pimpl->drawQueues) {
|
||||||
vkCmdBindPipeline(pimpl->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
|
vkCmdBindPipeline(pimpl->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
|
||||||
while (queue.empty() == false) {
|
while (queue.empty() == false) {
|
||||||
const gfx::VertexBuffer* buffer = queue.front();
|
DrawCall call = queue.front();
|
||||||
vkCmdBindVertexBuffers(pimpl->commandBuffer, 0, 1, &buffer->buffer, offsets);
|
vkCmdBindVertexBuffers(pimpl->commandBuffer, 0, 1, &call.vertexBuffer->buffer, offsets);
|
||||||
vkCmdDraw(pimpl->commandBuffer, buffer->size, 1, 0, 0);
|
if (call.indexBuffer == nullptr) {
|
||||||
|
// do a simple draw call
|
||||||
|
vkCmdDraw(pimpl->commandBuffer, call.count, 1, 0, 0);
|
||||||
|
} else {
|
||||||
|
vkCmdBindIndexBuffer(pimpl->commandBuffer, call.indexBuffer->buffer, 0, VK_INDEX_TYPE_UINT16);
|
||||||
|
vkCmdDrawIndexed(pimpl->commandBuffer, call.count, 1, 0, 0, 0);
|
||||||
|
}
|
||||||
queue.pop();
|
queue.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1318,13 +1365,15 @@ namespace engine {
|
|||||||
delete pipeline;
|
delete pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::VertexBuffer* GFXDevice::createVertexBuffer(uint32_t size, const void* vertices, const void* indices)
|
gfx::Buffer* GFXDevice::createBuffer(gfx::BufferType type, uint64_t size, const void* data)
|
||||||
{
|
{
|
||||||
VkResult res;
|
VkResult res;
|
||||||
|
|
||||||
auto out = new gfx::VertexBuffer{};
|
auto out = new gfx::Buffer{};
|
||||||
out->size = size;
|
out->size = size;
|
||||||
|
|
||||||
|
out->type = type;
|
||||||
|
|
||||||
VkBuffer stagingBuffer;
|
VkBuffer stagingBuffer;
|
||||||
VmaAllocation stagingAllocation;
|
VmaAllocation stagingAllocation;
|
||||||
|
|
||||||
@ -1344,10 +1393,10 @@ namespace engine {
|
|||||||
res = vmaCreateBuffer(pimpl->allocator, &stagingBufferInfo, &stagingAllocInfo, &stagingBuffer, &stagingAllocation, nullptr);
|
res = vmaCreateBuffer(pimpl->allocator, &stagingBufferInfo, &stagingAllocInfo, &stagingBuffer, &stagingAllocation, nullptr);
|
||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
void* data;
|
void* dataDest;
|
||||||
res = vmaMapMemory(pimpl->allocator, stagingAllocation, &data);
|
res = vmaMapMemory(pimpl->allocator, stagingAllocation, &dataDest);
|
||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
memcpy(data, vertices, out->size);
|
memcpy(dataDest, data, out->size);
|
||||||
vmaUnmapMemory(pimpl->allocator, stagingAllocation);
|
vmaUnmapMemory(pimpl->allocator, stagingAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1355,7 +1404,7 @@ namespace engine {
|
|||||||
{
|
{
|
||||||
VkBufferCreateInfo gpuBufferInfo{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
VkBufferCreateInfo gpuBufferInfo{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||||
gpuBufferInfo.size = out->size;
|
gpuBufferInfo.size = out->size;
|
||||||
gpuBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
gpuBufferInfo.usage = vkinternal::getBufferUsageFlag(type) | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
gpuBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
gpuBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
gpuBufferInfo.flags = 0;
|
gpuBufferInfo.flags = 0;
|
||||||
|
|
||||||
@ -1376,7 +1425,7 @@ namespace engine {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::destroyVertexBuffer(const gfx::VertexBuffer* buffer)
|
void GFXDevice::destroyBuffer(const gfx::Buffer* buffer)
|
||||||
{
|
{
|
||||||
vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation);
|
vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation);
|
||||||
delete buffer;
|
delete buffer;
|
||||||
|
Loading…
Reference in New Issue
Block a user