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
option(ENGINE_BUILD_TEST "Compile the test program" ON)
SET(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo")
project(engine LANGUAGES CXX
VERSION "0.1.0"
)

View File

@ -65,6 +65,8 @@ namespace engine {
InputManager* inputManager() { return m_inputManager.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(); }
private:
@ -77,7 +79,7 @@ namespace engine {
bool m_enableFrameLimiter = true;
gfx::CommandBuffer *m_drawCommandBuffer;
gfx::DrawBuffer *m_drawBuffer;
/* resource stuff */

View File

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

View File

@ -19,12 +19,15 @@ namespace engine {
void getViewportSize(uint32_t *w, uint32_t *h);
gfx::CommandBuffer* beginRender();
void finishRender(gfx::CommandBuffer* commandBuffer);
gfx::DrawBuffer* beginRender();
void finishRender(gfx::DrawBuffer* drawBuffer);
void cmdBindPipeline(gfx::CommandBuffer* commandBuffer, const gfx::Pipeline* pipeline);
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);
void cmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline);
void cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer);
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
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
layout( push_constant ) uniform Constants {
mat4 model;
mat4 view;
} constants;
layout(location = 0) in vec3 inPosition;
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()) {
/* begin rendering */
m_drawCommandBuffer = m_gfx->beginRender();
m_drawBuffer = m_gfx->beginRender();
/* logic */
m_sceneManager->updateActiveScene(m_window->dt());
@ -149,7 +149,7 @@ namespace engine {
}
/* draw */
m_gfx->finishRender(m_drawCommandBuffer);
m_gfx->finishRender(m_drawBuffer);
/* poll events */
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 size_t PUSH_CONSTANT_MAX_SIZE = 128; // bytes
static constexpr VkIndexType INDEX_TYPE = VK_INDEX_TYPE_UINT32;
// structures and enums
struct DepthBuffer {
VkImage image;
VmaAllocation allocation;
VkImageView view;
};
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;
struct FrameData {
VkFence renderFence = VK_NULL_HANDLE;
VkSemaphore presentSemaphore = VK_NULL_HANDLE;
VkSemaphore renderSemaphore = VK_NULL_HANDLE;
VkCommandBuffer drawBuf = VK_NULL_HANDLE;
};
// handles
@ -85,8 +78,8 @@ namespace engine {
uint32_t mipLevels;
};
struct gfx::CommandBuffer {
uint32_t frameIndex; // needed to identify correct command buffer, fences and semaphores
struct gfx::DrawBuffer {
FrameData frameData;
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; }
throw std::runtime_error("MSAA is not supported");
}
#endif
static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
{
[[maybe_unused]] VkResult res;
@ -373,6 +366,8 @@ namespace engine {
}
#if 0
static VkCommandBuffer beginOneTimeCommands(VkDevice device, VkCommandPool commandPool)
{
[[maybe_unused]] VkResult res;
@ -528,6 +523,7 @@ namespace engine {
0, nullptr,
1, &barrier);
}
#endif
// class definitions
@ -547,11 +543,8 @@ namespace engine {
uint64_t FRAMECOUNT = 0;
// temp
VkFence renderFence = VK_NULL_HANDLE;
VkSemaphore presentSemaphore = VK_NULL_HANDLE;
VkSemaphore renderSemaphore = VK_NULL_HANDLE;
VkCommandBuffer drawBuf = VK_NULL_HANDLE;
FrameData frameData[FRAMES_IN_FLIGHT] = {};
bool swapchainIsOutOfDate = false;
};
@ -579,7 +572,13 @@ namespace engine {
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) {
throw std::runtime_error("Unable to create window surface");
@ -603,12 +602,13 @@ namespace engine {
/* the following is temporary setup */
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
VkFenceCreateInfo fenceInfo{
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr,
.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!");
VkSemaphoreCreateInfo smphInfo{
@ -616,12 +616,11 @@ namespace engine {
.pNext = nullptr,
.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!");
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!");
// Create the command buffer for rendering:
VkCommandBufferAllocateInfo cmdAllocInfo{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.pNext = nullptr,
@ -629,16 +628,19 @@ namespace engine {
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1
};
VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->drawBuf));
VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->frameData[i].drawBuf));
}
}
GFXDevice::~GFXDevice()
{
vkFreeCommandBuffers(pimpl->device.device, pimpl->device.commandPools.draw, 1, &pimpl->drawBuf);
vkDestroySemaphore(pimpl->device.device, pimpl->renderSemaphore, nullptr);
vkDestroySemaphore(pimpl->device.device, pimpl->presentSemaphore, nullptr);
vkDestroyFence(pimpl->device.device, pimpl->renderFence, nullptr);
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
vkFreeCommandBuffers(pimpl->device.device, pimpl->device.commandPools.draw, 1, &pimpl->frameData[i].drawBuf);
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].renderSemaphore, nullptr);
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].presentSemaphore, nullptr);
vkDestroyFence(pimpl->device.device, pimpl->frameData[i].renderFence, nullptr);
}
destroySwapchain(pimpl->swapchain);
destroyAllocator(pimpl->allocator);
@ -661,12 +663,14 @@ namespace engine {
}
}
gfx::CommandBuffer* GFXDevice::beginRender()
gfx::DrawBuffer* GFXDevice::beginRender()
{
VkResult res;
uint32_t swapchainImageIndex;
FrameData frameData = pimpl->frameData[pimpl->FRAMECOUNT % FRAMES_IN_FLIGHT];
do {
if (pimpl->swapchainIsOutOfDate) {
// re-create swapchain
@ -677,19 +681,19 @@ namespace engine {
// THIS FUNCTION BLOCKS UNTIL AN IMAGE IS AVAILABLE (it waits for vsync)
res = vkAcquireNextImageKHR(
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_SUCCESS) pimpl->swapchainIsOutOfDate = false;
} while (pimpl->swapchainIsOutOfDate);
/* 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);
res = vkResetFences(pimpl->device.device, 1, &pimpl->renderFence);
res = vkResetFences(pimpl->device.device, 1, &frameData.renderFence);
VKCHECK(res);
/* record command buffer */
res = vkResetCommandBuffer(pimpl->drawBuf, 0);
res = vkResetCommandBuffer(frameData.drawBuf, 0);
VKCHECK(res);
VkCommandBufferBeginInfo beginInfo{
@ -698,7 +702,7 @@ namespace engine {
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
.pInheritanceInfo = nullptr // ignored
};
res = vkBeginCommandBuffer(pimpl->drawBuf, &beginInfo);
res = vkBeginCommandBuffer(frameData.drawBuf, &beginInfo);
VKCHECK(res);
{ // RECORDING
@ -719,7 +723,7 @@ namespace engine {
passBegin.renderArea.offset = { 0, 0 };
passBegin.clearValueCount = 1;
passBegin.pClearValues = &clearValue;
vkCmdBeginRenderPass(pimpl->drawBuf, &passBegin, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBeginRenderPass(frameData.drawBuf, &passBegin, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport{};
viewport.x = 0.0f;
@ -728,33 +732,34 @@ namespace engine {
viewport.height = -(float)pimpl->swapchain.extent.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(pimpl->drawBuf, 0, 1, &viewport);
vkCmdSetViewport(frameData.drawBuf, 0, 1, &viewport);
VkRect2D scissor{};
scissor.offset = { 0, 0 };
scissor.extent = pimpl->swapchain.extent;
vkCmdSetScissor(pimpl->drawBuf, 0, 1, &scissor);
vkCmdSetScissor(frameData.drawBuf, 0, 1, &scissor);
}
// hand command buffer over to caller
gfx::CommandBuffer* commandBuffer = new gfx::CommandBuffer;
commandBuffer->imageIndex = swapchainImageIndex;
return commandBuffer;
gfx::DrawBuffer* drawBuffer = new gfx::DrawBuffer;
drawBuffer->frameData = frameData;
drawBuffer->imageIndex = swapchainImageIndex;
return drawBuffer;
}
void GFXDevice::finishRender(gfx::CommandBuffer* commandBuffer)
void GFXDevice::finishRender(gfx::DrawBuffer* drawBuffer)
{
if (commandBuffer == nullptr) {
if (drawBuffer == nullptr) {
return;
}
uint32_t swapchainImageIndex = commandBuffer->imageIndex;
uint32_t swapchainImageIndex = drawBuffer->imageIndex;
VkResult res;
vkCmdEndRenderPass(pimpl->drawBuf);
vkCmdEndRenderPass(drawBuffer->frameData.drawBuf);
res = vkEndCommandBuffer(pimpl->drawBuf);
res = vkEndCommandBuffer(drawBuffer->frameData.drawBuf);
VKCHECK(res);
// SUBMIT
@ -765,15 +770,15 @@ namespace engine {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = nullptr,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &pimpl->presentSemaphore,
.pWaitSemaphores = &drawBuffer->frameData.presentSemaphore,
.pWaitDstStageMask = &waitStage,
.commandBufferCount = 1,
.pCommandBuffers = &pimpl->drawBuf,
.pCommandBuffers = &drawBuffer->frameData.drawBuf,
.signalSemaphoreCount = 1,
.pSignalSemaphores = &pimpl->renderSemaphore,
.pSignalSemaphores = &drawBuffer->frameData.renderSemaphore,
};
res = vkQueueSubmit(pimpl->device.queues.drawQueues[0], 1, &submitInfo, pimpl->renderFence);
VKCHECK(res);
res = vkQueueSubmit(pimpl->device.queues.drawQueues[0], 1, &submitInfo, drawBuffer->frameData.renderFence);
// VKCHECK(res); // expensive operation for some reason
// PRESENT
@ -781,7 +786,7 @@ namespace engine {
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.pNext = nullptr,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &pimpl->renderSemaphore,
.pWaitSemaphores = &drawBuffer->frameData.renderSemaphore,
.swapchainCount = 1,
.pSwapchains = &pimpl->swapchain.swapchain,
.pImageIndices = &swapchainImageIndex,
@ -796,7 +801,36 @@ namespace engine {
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)
@ -1037,8 +1071,6 @@ namespace engine {
out->type = type;
#if 0
VkBuffer stagingBuffer;
VmaAllocation stagingAllocation;
@ -1084,20 +1116,17 @@ namespace engine {
}
// 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
vmaDestroyBuffer(pimpl->allocator, stagingBuffer, stagingAllocation);
#endif
return out;
}
void GFXDevice::destroyBuffer(const gfx::Buffer* buffer)
{
#if 0
vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation);
#endif
delete buffer;
}

View File

@ -26,6 +26,7 @@ namespace engine {
GFXDevice* const gfx = m_scene->app()->gfx();
gfx::DrawBuffer* drawBuffer = m_scene->app()->getDrawBuffer();
/* camera stuff */
const auto cameraTransform = m_scene->getComponent<TransformComponent>(m_camera.camEntity);
@ -56,7 +57,7 @@ namespace engine {
assert(r->material != nullptr);
assert(r->mesh != nullptr);
assert(r->material->m_texture != nullptr);
//assert(r->material->m_texture != nullptr);
struct {
glm::mat4 proj;
@ -76,6 +77,11 @@ namespace engine {
pushConsts.model = t->worldMatrix;
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(
r->material->getShader()->getPipeline(),

View File

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

View File

@ -11,7 +11,14 @@ namespace engine {
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);
}

View File

@ -44,6 +44,7 @@ void playGame(bool enableFrameLimiter)
engine::gfx::GraphicsSettings graphicsSettings{};
graphicsSettings.vsync = true;
graphicsSettings.waitForPresent = false;
graphicsSettings.msaaLevel = engine::gfx::MSAALevel::MSAA_OFF;
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");
engine::resources::Shader::VertexParams vertexParams{};
vertexParams.hasColor = false;
vertexParams.hasNormal = false;
vertexParams.hasNormal = true;
vertexParams.hasTangent = false;
vertexParams.hasUV0 = false;
vertexParams.hasUV0 = true;
bool alphaBlending = false;
bool cullBackFace = false;
engine::resources::Shader testShader(app.gfx(), vertPath.c_str(), fragPath.c_str(), vertexParams, alphaBlending, cullBackFace);
bool cullBackFace = true;
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

View File

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