Get rendering kind-of working again

This commit is contained in:
bailwillharr 2023-03-12 20:39:11 +00:00
parent 8abfc69154
commit 2bb75f4683
12 changed files with 192 additions and 130 deletions

View File

@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.24)
# options # options
option(ENGINE_BUILD_TEST "Compile the test program" ON) option(ENGINE_BUILD_TEST "Compile the test program" ON)
SET(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo")
project(engine LANGUAGES CXX project(engine LANGUAGES CXX
VERSION "0.1.0" VERSION "0.1.0"
) )

View File

@ -65,6 +65,8 @@ namespace engine {
InputManager* inputManager() { return m_inputManager.get(); } InputManager* inputManager() { return m_inputManager.get(); }
SceneManager* sceneManager() { return m_sceneManager.get(); } SceneManager* sceneManager() { return m_sceneManager.get(); }
gfx::DrawBuffer* getDrawBuffer() { return m_drawBuffer; }
std::string getResourcePath(const std::string relativePath) { return (m_resourcesPath / relativePath).string(); } std::string getResourcePath(const std::string relativePath) { return (m_resourcesPath / relativePath).string(); }
private: private:
@ -77,7 +79,7 @@ namespace engine {
bool m_enableFrameLimiter = true; bool m_enableFrameLimiter = true;
gfx::CommandBuffer *m_drawCommandBuffer; gfx::DrawBuffer *m_drawBuffer;
/* resource stuff */ /* resource stuff */

View File

@ -90,6 +90,6 @@ namespace engine::gfx {
struct Pipeline; struct Pipeline;
struct Buffer; struct Buffer;
struct Texture; struct Texture;
struct CommandBuffer; struct DrawBuffer;
} }

View File

@ -19,12 +19,15 @@ namespace engine {
void getViewportSize(uint32_t *w, uint32_t *h); void getViewportSize(uint32_t *w, uint32_t *h);
gfx::CommandBuffer* beginRender(); gfx::DrawBuffer* beginRender();
void finishRender(gfx::CommandBuffer* commandBuffer); void finishRender(gfx::DrawBuffer* drawBuffer);
void cmdBindPipeline(gfx::CommandBuffer* commandBuffer, const gfx::Pipeline* pipeline); void cmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline);
void cmdBindDescriptorSetTexture(gfx::CommandBuffer* commandBuffer, uint32_t set, uint32_t binding, const gfx::Texture* texture); void cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer);
void cmdBindDescriptorSetBuffer(gfx::CommandBuffer* commandBuffer, uint32_t set, uint32_t binding, const gfx::Texture* texture); void cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer);
void cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
//void cmdBindDescriptorSetTexture(gfx::CommandBuffer* commandBuffer, uint32_t set, uint32_t binding, const gfx::Texture* texture);
//void cmdBindDescriptorSetBuffer(gfx::CommandBuffer* commandBuffer, uint32_t set, uint32_t binding, const gfx::Texture* texture);
// 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, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling); gfx::Pipeline* createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling);

View File

@ -1,13 +1,8 @@
#version 450 #version 450
layout( push_constant ) uniform Constants {
mat4 model;
mat4 view;
} constants;
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 inPosition;
void main() void main()
{ {
gl_Position = constants.view * constants.model * vec4(inPosition, 1.0); gl_Position = vec4(inPosition, 1.0);
} }

View File

@ -132,7 +132,7 @@ namespace engine {
while (m_window->isRunning()) { while (m_window->isRunning()) {
/* begin rendering */ /* begin rendering */
m_drawCommandBuffer = m_gfx->beginRender(); m_drawBuffer = m_gfx->beginRender();
/* logic */ /* logic */
m_sceneManager->updateActiveScene(m_window->dt()); m_sceneManager->updateActiveScene(m_window->dt());
@ -149,7 +149,7 @@ namespace engine {
} }
/* draw */ /* draw */
m_gfx->finishRender(m_drawCommandBuffer); m_gfx->finishRender(m_drawBuffer);
/* poll events */ /* poll events */
m_window->getInputAndEvents(); m_window->getInputAndEvents();

View File

@ -43,22 +43,15 @@ namespace engine {
static constexpr uint32_t FRAMES_IN_FLIGHT = 2; // This improved FPS by 5x! (on Intel IGPU) static constexpr uint32_t FRAMES_IN_FLIGHT = 2; // This improved FPS by 5x! (on Intel IGPU)
static constexpr size_t PUSH_CONSTANT_MAX_SIZE = 128; // bytes static constexpr size_t PUSH_CONSTANT_MAX_SIZE = 128; // bytes
static constexpr VkIndexType INDEX_TYPE = VK_INDEX_TYPE_UINT32;
// structures and enums // structures and enums
struct DepthBuffer { struct FrameData {
VkImage image; VkFence renderFence = VK_NULL_HANDLE;
VmaAllocation allocation; VkSemaphore presentSemaphore = VK_NULL_HANDLE;
VkImageView view; VkSemaphore renderSemaphore = VK_NULL_HANDLE;
}; VkCommandBuffer drawBuf = VK_NULL_HANDLE;
struct DrawCall {
const gfx::Pipeline* pipeline = nullptr; // for performance, keep this the same for consecutive draw calls
const gfx::Buffer* vertexBuffer = nullptr;
const gfx::Buffer* indexBuffer = nullptr; // if this is nullptr, don't use indexed
uint32_t count = 0;
uint8_t pushConstantData[PUSH_CONSTANT_MAX_SIZE];
const gfx::Texture* texture = nullptr;
}; };
// handles // handles
@ -85,8 +78,8 @@ namespace engine {
uint32_t mipLevels; uint32_t mipLevels;
}; };
struct gfx::CommandBuffer { struct gfx::DrawBuffer {
uint32_t frameIndex; // needed to identify correct command buffer, fences and semaphores FrameData frameData;
uint32_t imageIndex; // for swapchain present uint32_t imageIndex; // for swapchain present
}; };
@ -325,7 +318,7 @@ namespace engine {
if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; } if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }
throw std::runtime_error("MSAA is not supported"); throw std::runtime_error("MSAA is not supported");
} }
#endif
static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
{ {
[[maybe_unused]] VkResult res; [[maybe_unused]] VkResult res;
@ -373,6 +366,8 @@ namespace engine {
} }
#if 0
static VkCommandBuffer beginOneTimeCommands(VkDevice device, VkCommandPool commandPool) static VkCommandBuffer beginOneTimeCommands(VkDevice device, VkCommandPool commandPool)
{ {
[[maybe_unused]] VkResult res; [[maybe_unused]] VkResult res;
@ -528,6 +523,7 @@ namespace engine {
0, nullptr, 0, nullptr,
1, &barrier); 1, &barrier);
} }
#endif #endif
// class definitions // class definitions
@ -547,11 +543,8 @@ namespace engine {
uint64_t FRAMECOUNT = 0; uint64_t FRAMECOUNT = 0;
// temp FrameData frameData[FRAMES_IN_FLIGHT] = {};
VkFence renderFence = VK_NULL_HANDLE;
VkSemaphore presentSemaphore = VK_NULL_HANDLE;
VkSemaphore renderSemaphore = VK_NULL_HANDLE;
VkCommandBuffer drawBuf = VK_NULL_HANDLE;
bool swapchainIsOutOfDate = false; bool swapchainIsOutOfDate = false;
}; };
@ -579,7 +572,13 @@ namespace engine {
throw std::runtime_error("The loaded Vulkan version must be at least 1.3"); throw std::runtime_error("The loaded Vulkan version must be at least 1.3");
} }
pimpl->instance = createVulkanInstance(pimpl->window, appName, appVersion); #ifdef NDEBUG
bool useValidation = false;
#else
bool useValidation = true;
#endif
pimpl->instance = createVulkanInstance(pimpl->window, appName, appVersion, useValidation, MessageSeverity::SEV_WARNING);
if (SDL_Vulkan_CreateSurface(pimpl->window, pimpl->instance.instance, &pimpl->surface) == false) { if (SDL_Vulkan_CreateSurface(pimpl->window, pimpl->instance.instance, &pimpl->surface) == false) {
throw std::runtime_error("Unable to create window surface"); throw std::runtime_error("Unable to create window surface");
@ -603,42 +602,45 @@ namespace engine {
/* the following is temporary setup */ /* the following is temporary setup */
VkFenceCreateInfo fenceInfo{ for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
VkFenceCreateInfo fenceInfo{
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = VK_FENCE_CREATE_SIGNALED_BIT .flags = VK_FENCE_CREATE_SIGNALED_BIT
}; };
res = vkCreateFence(pimpl->device.device, &fenceInfo, nullptr, &pimpl->renderFence); res = vkCreateFence(pimpl->device.device, &fenceInfo, nullptr, &pimpl->frameData[i].renderFence);
if (res != VK_SUCCESS) throw std::runtime_error("Failed to create fence!"); if (res != VK_SUCCESS) throw std::runtime_error("Failed to create fence!");
VkSemaphoreCreateInfo smphInfo{ VkSemaphoreCreateInfo smphInfo{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0 .flags = 0
}; };
res = vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->presentSemaphore); res = vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->frameData[i].presentSemaphore);
if (res != VK_SUCCESS) throw std::runtime_error("Failed to create semaphore!"); if (res != VK_SUCCESS) throw std::runtime_error("Failed to create semaphore!");
res = vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->renderSemaphore); res = vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->frameData[i].renderSemaphore);
if (res != VK_SUCCESS) throw std::runtime_error("Failed to create semaphore!"); if (res != VK_SUCCESS) throw std::runtime_error("Failed to create semaphore!");
// Create the command buffer for rendering: VkCommandBufferAllocateInfo cmdAllocInfo{
VkCommandBufferAllocateInfo cmdAllocInfo{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .pNext = nullptr,
.pNext = nullptr, .commandPool = pimpl->device.commandPools.draw,
.commandPool = pimpl->device.commandPools.draw, .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, .commandBufferCount = 1
.commandBufferCount = 1 };
}; VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->frameData[i].drawBuf));
VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->drawBuf)); }
} }
GFXDevice::~GFXDevice() GFXDevice::~GFXDevice()
{ {
vkFreeCommandBuffers(pimpl->device.device, pimpl->device.commandPools.draw, 1, &pimpl->drawBuf); for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
vkDestroySemaphore(pimpl->device.device, pimpl->renderSemaphore, nullptr); vkFreeCommandBuffers(pimpl->device.device, pimpl->device.commandPools.draw, 1, &pimpl->frameData[i].drawBuf);
vkDestroySemaphore(pimpl->device.device, pimpl->presentSemaphore, nullptr); vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].renderSemaphore, nullptr);
vkDestroyFence(pimpl->device.device, pimpl->renderFence, nullptr); vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].presentSemaphore, nullptr);
vkDestroyFence(pimpl->device.device, pimpl->frameData[i].renderFence, nullptr);
}
destroySwapchain(pimpl->swapchain); destroySwapchain(pimpl->swapchain);
destroyAllocator(pimpl->allocator); destroyAllocator(pimpl->allocator);
@ -661,12 +663,14 @@ namespace engine {
} }
} }
gfx::CommandBuffer* GFXDevice::beginRender() gfx::DrawBuffer* GFXDevice::beginRender()
{ {
VkResult res; VkResult res;
uint32_t swapchainImageIndex; uint32_t swapchainImageIndex;
FrameData frameData = pimpl->frameData[pimpl->FRAMECOUNT % FRAMES_IN_FLIGHT];
do { do {
if (pimpl->swapchainIsOutOfDate) { if (pimpl->swapchainIsOutOfDate) {
// re-create swapchain // re-create swapchain
@ -677,19 +681,19 @@ namespace engine {
// THIS FUNCTION BLOCKS UNTIL AN IMAGE IS AVAILABLE (it waits for vsync) // THIS FUNCTION BLOCKS UNTIL AN IMAGE IS AVAILABLE (it waits for vsync)
res = vkAcquireNextImageKHR( res = vkAcquireNextImageKHR(
pimpl->device.device, pimpl->swapchain.swapchain, 1000000000LL, pimpl->device.device, pimpl->swapchain.swapchain, 1000000000LL,
pimpl->presentSemaphore, VK_NULL_HANDLE, &swapchainImageIndex); frameData.presentSemaphore, VK_NULL_HANDLE, &swapchainImageIndex);
if (res != VK_SUBOPTIMAL_KHR && res != VK_ERROR_OUT_OF_DATE_KHR) VKCHECK(res); if (res != VK_SUBOPTIMAL_KHR && res != VK_ERROR_OUT_OF_DATE_KHR) VKCHECK(res);
if (res == VK_SUCCESS) pimpl->swapchainIsOutOfDate = false; if (res == VK_SUCCESS) pimpl->swapchainIsOutOfDate = false;
} while (pimpl->swapchainIsOutOfDate); } while (pimpl->swapchainIsOutOfDate);
/* wait until the previous frame RENDERING has finished */ /* wait until the previous frame RENDERING has finished */
res = vkWaitForFences(pimpl->device.device, 1, &pimpl->renderFence, VK_TRUE, 1000000000LL); res = vkWaitForFences(pimpl->device.device, 1, &frameData.renderFence, VK_TRUE, 1000000000LL);
VKCHECK(res); VKCHECK(res);
res = vkResetFences(pimpl->device.device, 1, &pimpl->renderFence); res = vkResetFences(pimpl->device.device, 1, &frameData.renderFence);
VKCHECK(res); VKCHECK(res);
/* record command buffer */ /* record command buffer */
res = vkResetCommandBuffer(pimpl->drawBuf, 0); res = vkResetCommandBuffer(frameData.drawBuf, 0);
VKCHECK(res); VKCHECK(res);
VkCommandBufferBeginInfo beginInfo{ VkCommandBufferBeginInfo beginInfo{
@ -698,7 +702,7 @@ namespace engine {
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
.pInheritanceInfo = nullptr // ignored .pInheritanceInfo = nullptr // ignored
}; };
res = vkBeginCommandBuffer(pimpl->drawBuf, &beginInfo); res = vkBeginCommandBuffer(frameData.drawBuf, &beginInfo);
VKCHECK(res); VKCHECK(res);
{ // RECORDING { // RECORDING
@ -719,7 +723,7 @@ namespace engine {
passBegin.renderArea.offset = { 0, 0 }; passBegin.renderArea.offset = { 0, 0 };
passBegin.clearValueCount = 1; passBegin.clearValueCount = 1;
passBegin.pClearValues = &clearValue; passBegin.pClearValues = &clearValue;
vkCmdBeginRenderPass(pimpl->drawBuf, &passBegin, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(frameData.drawBuf, &passBegin, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport{}; VkViewport viewport{};
viewport.x = 0.0f; viewport.x = 0.0f;
@ -728,33 +732,34 @@ namespace engine {
viewport.height = -(float)pimpl->swapchain.extent.height; viewport.height = -(float)pimpl->swapchain.extent.height;
viewport.minDepth = 0.0f; viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f; viewport.maxDepth = 1.0f;
vkCmdSetViewport(pimpl->drawBuf, 0, 1, &viewport); vkCmdSetViewport(frameData.drawBuf, 0, 1, &viewport);
VkRect2D scissor{}; VkRect2D scissor{};
scissor.offset = { 0, 0 }; scissor.offset = { 0, 0 };
scissor.extent = pimpl->swapchain.extent; scissor.extent = pimpl->swapchain.extent;
vkCmdSetScissor(pimpl->drawBuf, 0, 1, &scissor); vkCmdSetScissor(frameData.drawBuf, 0, 1, &scissor);
} }
// hand command buffer over to caller // hand command buffer over to caller
gfx::CommandBuffer* commandBuffer = new gfx::CommandBuffer; gfx::DrawBuffer* drawBuffer = new gfx::DrawBuffer;
commandBuffer->imageIndex = swapchainImageIndex; drawBuffer->frameData = frameData;
return commandBuffer; drawBuffer->imageIndex = swapchainImageIndex;
return drawBuffer;
} }
void GFXDevice::finishRender(gfx::CommandBuffer* commandBuffer) void GFXDevice::finishRender(gfx::DrawBuffer* drawBuffer)
{ {
if (commandBuffer == nullptr) { if (drawBuffer == nullptr) {
return; return;
} }
uint32_t swapchainImageIndex = commandBuffer->imageIndex; uint32_t swapchainImageIndex = drawBuffer->imageIndex;
VkResult res; VkResult res;
vkCmdEndRenderPass(pimpl->drawBuf); vkCmdEndRenderPass(drawBuffer->frameData.drawBuf);
res = vkEndCommandBuffer(pimpl->drawBuf); res = vkEndCommandBuffer(drawBuffer->frameData.drawBuf);
VKCHECK(res); VKCHECK(res);
// SUBMIT // SUBMIT
@ -765,15 +770,15 @@ namespace engine {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = nullptr, .pNext = nullptr,
.waitSemaphoreCount = 1, .waitSemaphoreCount = 1,
.pWaitSemaphores = &pimpl->presentSemaphore, .pWaitSemaphores = &drawBuffer->frameData.presentSemaphore,
.pWaitDstStageMask = &waitStage, .pWaitDstStageMask = &waitStage,
.commandBufferCount = 1, .commandBufferCount = 1,
.pCommandBuffers = &pimpl->drawBuf, .pCommandBuffers = &drawBuffer->frameData.drawBuf,
.signalSemaphoreCount = 1, .signalSemaphoreCount = 1,
.pSignalSemaphores = &pimpl->renderSemaphore, .pSignalSemaphores = &drawBuffer->frameData.renderSemaphore,
}; };
res = vkQueueSubmit(pimpl->device.queues.drawQueues[0], 1, &submitInfo, pimpl->renderFence); res = vkQueueSubmit(pimpl->device.queues.drawQueues[0], 1, &submitInfo, drawBuffer->frameData.renderFence);
VKCHECK(res); // VKCHECK(res); // expensive operation for some reason
// PRESENT // PRESENT
@ -781,7 +786,7 @@ namespace engine {
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.pNext = nullptr, .pNext = nullptr,
.waitSemaphoreCount = 1, .waitSemaphoreCount = 1,
.pWaitSemaphores = &pimpl->renderSemaphore, .pWaitSemaphores = &drawBuffer->frameData.renderSemaphore,
.swapchainCount = 1, .swapchainCount = 1,
.pSwapchains = &pimpl->swapchain.swapchain, .pSwapchains = &pimpl->swapchain.swapchain,
.pImageIndices = &swapchainImageIndex, .pImageIndices = &swapchainImageIndex,
@ -796,7 +801,36 @@ namespace engine {
pimpl->FRAMECOUNT++; pimpl->FRAMECOUNT++;
delete commandBuffer; delete drawBuffer;
}
void GFXDevice::cmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline)
{
assert(drawBuffer != nullptr);
vkCmdBindPipeline(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
}
void GFXDevice::cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer)
{
assert(drawBuffer != nullptr);
assert(buffer != nullptr);
assert(buffer->type == gfx::BufferType::VERTEX);
const VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(drawBuffer->frameData.drawBuf, binding, 1, &buffer->buffer, &offset);
}
void GFXDevice::cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer)
{
assert(drawBuffer != nullptr);
assert(buffer != nullptr);
assert(buffer->type == gfx::BufferType::INDEX);
vkCmdBindIndexBuffer(drawBuffer->frameData.drawBuf, buffer->buffer, 0, INDEX_TYPE);
}
void GFXDevice::cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
{
assert(drawBuffer != nullptr);
vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
} }
gfx::Pipeline* GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling) gfx::Pipeline* GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling)
@ -1037,8 +1071,6 @@ namespace engine {
out->type = type; out->type = type;
#if 0
VkBuffer stagingBuffer; VkBuffer stagingBuffer;
VmaAllocation stagingAllocation; VmaAllocation stagingAllocation;
@ -1084,20 +1116,17 @@ namespace engine {
} }
// copy the data from the staging buffer to the gpu buffer // copy the data from the staging buffer to the gpu buffer
copyBuffer(pimpl->device, pimpl->commandPool, pimpl->gfxQueue.handle, stagingBuffer, out->buffer, out->size); copyBuffer(pimpl->device.device, pimpl->device.commandPools.transfer, pimpl->device.queues.transferQueues[0], stagingBuffer, out->buffer, out->size);
// destroy staging buffer // destroy staging buffer
vmaDestroyBuffer(pimpl->allocator, stagingBuffer, stagingAllocation); vmaDestroyBuffer(pimpl->allocator, stagingBuffer, stagingAllocation);
#endif
return out; return out;
} }
void GFXDevice::destroyBuffer(const gfx::Buffer* buffer) void GFXDevice::destroyBuffer(const gfx::Buffer* buffer)
{ {
#if 0
vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation); vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation);
#endif
delete buffer; delete buffer;
} }

View File

@ -26,6 +26,7 @@ namespace engine {
GFXDevice* const gfx = m_scene->app()->gfx(); GFXDevice* const gfx = m_scene->app()->gfx();
gfx::DrawBuffer* drawBuffer = m_scene->app()->getDrawBuffer();
/* camera stuff */ /* camera stuff */
const auto cameraTransform = m_scene->getComponent<TransformComponent>(m_camera.camEntity); const auto cameraTransform = m_scene->getComponent<TransformComponent>(m_camera.camEntity);
@ -56,7 +57,7 @@ namespace engine {
assert(r->material != nullptr); assert(r->material != nullptr);
assert(r->mesh != nullptr); assert(r->mesh != nullptr);
assert(r->material->m_texture != nullptr); //assert(r->material->m_texture != nullptr);
struct { struct {
glm::mat4 proj; glm::mat4 proj;
@ -76,6 +77,11 @@ namespace engine {
pushConsts.model = t->worldMatrix; pushConsts.model = t->worldMatrix;
pushConsts.view = viewMatrix; pushConsts.view = viewMatrix;
gfx->cmdBindPipeline(drawBuffer, r->material->getShader()->getPipeline());
gfx->cmdBindVertexBuffer(drawBuffer, 0, r->mesh->getVB());
gfx->cmdBindIndexBuffer(drawBuffer, r->mesh->getIB());
gfx->cmdDrawIndexed(drawBuffer, r->mesh->getCount(), 1, 0, 0, 0);
/* /*
gfx->draw( gfx->draw(
r->material->getShader()->getPipeline(), r->material->getShader()->getPipeline(),

View File

@ -87,7 +87,7 @@ namespace engine {
return VK_FALSE; return VK_FALSE;
} }
static VkDebugUtilsMessengerCreateInfoEXT getDebugMessengerCreateInfo() static VkDebugUtilsMessengerCreateInfoEXT getDebugMessengerCreateInfo(MessageSeverity validationLevel)
{ {
VkDebugUtilsMessengerCreateInfoEXT debugMessengerInfo{ VkDebugUtilsMessengerCreateInfoEXT debugMessengerInfo{
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
@ -102,15 +102,7 @@ namespace engine {
.pUserData = nullptr, .pUserData = nullptr,
}; };
enum class MessageSeverity { switch (validationLevel) {
SEV_VERBOSE,
SEV_INFO,
SEV_WARNING,
SEV_ERROR // windows.h defines ERROR annoyingly
};
constexpr MessageSeverity MESSAGE_LEVEL = MessageSeverity::SEV_WARNING;
switch (MESSAGE_LEVEL) {
case MessageSeverity::SEV_VERBOSE: case MessageSeverity::SEV_VERBOSE:
debugMessengerInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; debugMessengerInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
[[fallthrough]]; [[fallthrough]];
@ -130,7 +122,7 @@ namespace engine {
return debugMessengerInfo; return debugMessengerInfo;
} }
Instance createVulkanInstance(SDL_Window* window, const char* appName, const char* appVersion) Instance createVulkanInstance(SDL_Window* window, const char* appName, const char* appVersion, bool useValidation, MessageSeverity validationLevel)
{ {
Instance instance; Instance instance;
@ -152,22 +144,31 @@ namespace engine {
const std::vector<const char*> windowExtensions = getWindowExtensions(window); const std::vector<const char*> windowExtensions = getWindowExtensions(window);
std::vector<const char*> instanceExtensionsToUse = windowExtensions; std::vector<const char*> instanceExtensionsToUse = windowExtensions;
instanceExtensionsToUse.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); if (useValidation) instanceExtensionsToUse.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
const char* const validationLayer = getValidationLayer(); const char* validationLayer = nullptr;
if (useValidation) {
const char* validationLayer = getValidationLayer();
}
VkDebugUtilsMessengerCreateInfoEXT debugMessengerInfo = getDebugMessengerCreateInfo(); VkDebugUtilsMessengerCreateInfoEXT debugMessengerInfo = getDebugMessengerCreateInfo(validationLevel);
VkInstanceCreateInfo instanceInfo{ VkInstanceCreateInfo instanceInfo{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = &debugMessengerInfo, .pNext = &debugMessengerInfo,
.flags = 0, .flags = 0
.pApplicationInfo = &applicationInfo,
.enabledLayerCount = 1,
.ppEnabledLayerNames = &validationLayer,
.enabledExtensionCount = (uint32_t)instanceExtensionsToUse.size(),
.ppEnabledExtensionNames = instanceExtensionsToUse.data(),
}; };
instanceInfo.pApplicationInfo = &applicationInfo;
if (validationLayer) {
instanceInfo.enabledLayerCount = 1;
instanceInfo.ppEnabledLayerNames = &validationLayer;
}
else {
instanceInfo.enabledLayerCount = 0;
instanceInfo.ppEnabledLayerNames = nullptr;
}
instanceInfo.enabledExtensionCount = (uint32_t)instanceExtensionsToUse.size();
instanceInfo.ppEnabledExtensionNames = instanceExtensionsToUse.data();
VkResult res; VkResult res;
res = vkCreateInstance(&instanceInfo, nullptr, &instance.instance); res = vkCreateInstance(&instanceInfo, nullptr, &instance.instance);
@ -181,11 +182,12 @@ namespace engine {
volkLoadInstanceOnly(instance.instance); volkLoadInstanceOnly(instance.instance);
// create the debug messenger // create the debug messenger
VkDebugUtilsMessengerCreateInfoEXT createInfo = getDebugMessengerCreateInfo(); if (useValidation) {
VkDebugUtilsMessengerCreateInfoEXT createInfo = getDebugMessengerCreateInfo(validationLevel);
res = vkCreateDebugUtilsMessengerEXT(instance.instance, &createInfo, nullptr, &instance.debugMessenger); res = vkCreateDebugUtilsMessengerEXT(instance.instance, &createInfo, nullptr, &instance.debugMessenger);
if (res != VK_SUCCESS) { if (res != VK_SUCCESS) {
throw std::runtime_error("vkCreateDebugUtilsMessengerExt failed: " + std::to_string(res)); throw std::runtime_error("vkCreateDebugUtilsMessengerExt failed: " + std::to_string(res));
}
} }
return instance; return instance;
@ -193,7 +195,9 @@ namespace engine {
void destroyVulkanInstance(Instance instance) void destroyVulkanInstance(Instance instance)
{ {
vkDestroyDebugUtilsMessengerEXT(instance.instance, instance.debugMessenger, nullptr); if (instance.debugMessenger != VK_NULL_HANDLE) {
vkDestroyDebugUtilsMessengerEXT(instance.instance, instance.debugMessenger, nullptr);
}
vkDestroyInstance(instance.instance, nullptr); vkDestroyInstance(instance.instance, nullptr);
} }

View File

@ -11,7 +11,14 @@ namespace engine {
VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE; VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE;
}; };
Instance createVulkanInstance(SDL_Window* window, const char* appName, const char* appVersion); enum class MessageSeverity {
SEV_VERBOSE,
SEV_INFO,
SEV_WARNING,
SEV_ERROR // windows.h defines ERROR annoyingly
};
Instance createVulkanInstance(SDL_Window* window, const char* appName, const char* appVersion, bool useValidation, MessageSeverity validationLevel = MessageSeverity::SEV_WARNING);
void destroyVulkanInstance(Instance instance); void destroyVulkanInstance(Instance instance);
} }

View File

@ -44,6 +44,7 @@ void playGame(bool enableFrameLimiter)
engine::gfx::GraphicsSettings graphicsSettings{}; engine::gfx::GraphicsSettings graphicsSettings{};
graphicsSettings.vsync = true; graphicsSettings.vsync = true;
graphicsSettings.waitForPresent = false;
graphicsSettings.msaaLevel = engine::gfx::MSAALevel::MSAA_OFF; graphicsSettings.msaaLevel = engine::gfx::MSAALevel::MSAA_OFF;
engine::Application app(PROJECT_NAME, PROJECT_VERSION, graphicsSettings); engine::Application app(PROJECT_NAME, PROJECT_VERSION, graphicsSettings);
@ -60,12 +61,25 @@ void playGame(bool enableFrameLimiter)
const std::string fragPath = app.getResourcePath("engine/shaders/test.frag"); const std::string fragPath = app.getResourcePath("engine/shaders/test.frag");
engine::resources::Shader::VertexParams vertexParams{}; engine::resources::Shader::VertexParams vertexParams{};
vertexParams.hasColor = false; vertexParams.hasColor = false;
vertexParams.hasNormal = false; vertexParams.hasNormal = true;
vertexParams.hasTangent = false; vertexParams.hasTangent = false;
vertexParams.hasUV0 = false; vertexParams.hasUV0 = true;
bool alphaBlending = false; bool alphaBlending = false;
bool cullBackFace = false; bool cullBackFace = true;
engine::resources::Shader testShader(app.gfx(), vertPath.c_str(), fragPath.c_str(), vertexParams, alphaBlending, cullBackFace); auto testShader = std::make_shared<engine::resources::Shader>(app.gfx(), vertPath.c_str(), fragPath.c_str(), vertexParams, alphaBlending, cullBackFace);
auto camera = myScene->createEntity("camera");
auto renderSystem = myScene->getSystem<engine::RenderSystem>();
renderSystem->setCameraEntity(camera);
myScene->getComponent<engine::TransformComponent>(camera)->position = { 0.0f, 10.0f, 0.0f };
/* cube */
uint32_t cube = myScene->createEntity("cube");
myScene->getComponent<engine::TransformComponent>(cube)->position = glm::vec3{ -0.5f, -0.5f, -0.5f };
auto cubeRenderable = myScene->addComponent<engine::RenderableComponent>(cube);
cubeRenderable->material = std::make_shared<engine::resources::Material>(testShader);
cubeRenderable->mesh = genCuboidMesh(app.gfx(), 1, 1.0f, 1, 1);
#if 0 #if 0

View File

@ -14,7 +14,7 @@ int main(int argc, char* argv[])
bool enableFrameLimiter = true; bool enableFrameLimiter = true;
if (argc == 2) { if (argc == 2) {
if (strcmp(argv[2], "nofpslimit") == 0) enableFrameLimiter = false; if (strcmp(argv[1], "nofpslimit") == 0) enableFrameLimiter = false;
} }
engine::setupLog(PROJECT_NAME); engine::setupLog(PROJECT_NAME);