diff --git a/include/gfx.hpp b/include/gfx.hpp index 4e233e9..f8c66b0 100644 --- a/include/gfx.hpp +++ b/include/gfx.hpp @@ -76,7 +76,7 @@ namespace engine::gfx { location(location), format(format), offset(offset) {} - uint32_t location; + uint32_t location; // the index to use in the shader VertexAttribFormat format; uint32_t offset; }; diff --git a/res/engine/shaders/test.frag b/res/engine/shaders/test.frag new file mode 100644 index 0000000..df80621 --- /dev/null +++ b/res/engine/shaders/test.frag @@ -0,0 +1,9 @@ +#version 450 + +layout(location = 0) out vec4 outColor; + +void main() +{ + outColor = vec4(0.0, 0.0, 1.0, 1.0); +} + diff --git a/res/engine/shaders/test.vert b/res/engine/shaders/test.vert new file mode 100644 index 0000000..ebc5f11 --- /dev/null +++ b/res/engine/shaders/test.vert @@ -0,0 +1,13 @@ +#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); +} diff --git a/src/application.cpp b/src/application.cpp index 1238a2f..3d09f4b 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -73,6 +73,7 @@ namespace engine { registerResourceManager(); // default resources +#if 0 { resources::Shader::VertexParams vertParams{}; vertParams.hasNormal = true; @@ -101,6 +102,7 @@ namespace engine { ); getResourceManager()->addPersistent("builtin.skybox", std::move(texturedShader)); } +#endif { auto whiteTexture = std::make_unique( gfx(), diff --git a/src/gfx_device_vulkan.cpp b/src/gfx_device_vulkan.cpp index fe71b3d..4ad5bd4 100644 --- a/src/gfx_device_vulkan.cpp +++ b/src/gfx_device_vulkan.cpp @@ -26,6 +26,18 @@ #include "log.hpp" #include "util/files.hpp" +inline static void checkVulkanError(VkResult errorCode, int lineNo) +{ + if (errorCode != VK_SUCCESS) { + const std::string message("VULKAN ERROR ON LINE " + std::to_string(lineNo)); + throw std::runtime_error(message.c_str()); + } +} + +#undef VKCHECK +#define VKCHECK(ErrCode) \ + checkVulkanError(ErrCode, __LINE__) + namespace engine { static constexpr uint32_t FRAMES_IN_FLIGHT = 2; // This improved FPS by 5x! (on Intel IGPU) @@ -61,9 +73,6 @@ namespace engine { struct gfx::Pipeline { VkPipelineLayout layout = VK_NULL_HANDLE; VkPipeline handle = VK_NULL_HANDLE; - std::vector uniformBuffers{}; - VkDescriptorPool descriptorPool = VK_NULL_HANDLE; - std::array descriptorSets{}; }; struct gfx::Texture { @@ -148,7 +157,6 @@ namespace engine { // functions -#if 0 static VkShaderModule compileShader(VkDevice device, shaderc_shader_kind kind, const std::string& source, const char* filename) { @@ -195,6 +203,8 @@ namespace engine { } +#if 0 + static Swapchain::MSTarget createMSAATarget(VkSampleCountFlagBits msaaSamples, VkExtent2D extent, VkFormat colorFormat, VkDevice device, VmaAllocator allocator) { Swapchain::MSTarget target{}; @@ -619,8 +629,7 @@ namespace engine { .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, .commandBufferCount = 1 }; - res = vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->drawBuf); - assert(res == VK_SUCCESS); + VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->drawBuf)); } @@ -669,20 +678,19 @@ namespace engine { res = vkAcquireNextImageKHR( pimpl->device.device, pimpl->swapchain.swapchain, 1000000000LL, pimpl->presentSemaphore, VK_NULL_HANDLE, &swapchainImageIndex); - assert(res == VK_SUCCESS || res == VK_SUBOPTIMAL_KHR || res == VK_ERROR_OUT_OF_DATE_KHR); + 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); - if (res == VK_TIMEOUT) throw std::runtime_error("Render fence timed out!"); - assert(res == VK_SUCCESS); + VKCHECK(res); res = vkResetFences(pimpl->device.device, 1, &pimpl->renderFence); - assert(res == VK_SUCCESS); + VKCHECK(res); /* record command buffer */ res = vkResetCommandBuffer(pimpl->drawBuf, 0); - assert(res == VK_SUCCESS); + VKCHECK(res); VkCommandBufferBeginInfo beginInfo{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -691,7 +699,7 @@ namespace engine { .pInheritanceInfo = nullptr // ignored }; res = vkBeginCommandBuffer(pimpl->drawBuf, &beginInfo); - assert(res == VK_SUCCESS); + VKCHECK(res); { // RECORDING @@ -747,7 +755,7 @@ namespace engine { vkCmdEndRenderPass(pimpl->drawBuf); res = vkEndCommandBuffer(pimpl->drawBuf); - assert(res == VK_SUCCESS); + VKCHECK(res); // SUBMIT @@ -765,7 +773,7 @@ namespace engine { .pSignalSemaphores = &pimpl->renderSemaphore, }; res = vkQueueSubmit(pimpl->device.queues.drawQueues[0], 1, &submitInfo, pimpl->renderFence); - assert(res == VK_SUCCESS); + VKCHECK(res); // PRESENT @@ -798,80 +806,11 @@ namespace engine { gfx::Pipeline* pipeline = new gfx::Pipeline; -#if 0 auto vertShaderCode = util::readTextFile(vertShaderPath); auto fragShaderCode = util::readTextFile(fragShaderPath); VkShaderModule vertShaderModule = compileShader(pimpl->device.device, shaderc_vertex_shader, vertShaderCode->data(), vertShaderPath); VkShaderModule fragShaderModule = compileShader(pimpl->device.device, shaderc_fragment_shader, fragShaderCode->data(), fragShaderPath); - - // create uniform buffers - pipeline->uniformBuffers.resize(FRAMES_IN_FLIGHT); - for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { - auto buf = new gfx::Buffer{}; - buf->size = uniformBufferSize; - buf->type = gfx::BufferType::UNIFORM; - - VkBufferCreateInfo bufferInfo{}; - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = buf->size; - bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VmaAllocationCreateInfo allocInfo{}; - allocInfo.usage = VMA_MEMORY_USAGE_AUTO; - allocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; - allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - - VmaAllocationInfo resultingAlloc; - res = vmaCreateBuffer(pimpl->allocator, &bufferInfo, &allocInfo, &buf->buffer, &buf->allocation, &resultingAlloc); - assert(res == VK_SUCCESS); - - pipeline->uniformBuffers[i] = buf; - } - - // create descriptor pools - VkDescriptorPoolSize poolSize{}; - poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - poolSize.descriptorCount = FRAMES_IN_FLIGHT; - - VkDescriptorPoolCreateInfo poolInfo{}; - poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - poolInfo.poolSizeCount = 1; - poolInfo.pPoolSizes = &poolSize; - poolInfo.maxSets = FRAMES_IN_FLIGHT; - res = vkCreateDescriptorPool(pimpl->device.device, &poolInfo, nullptr, &pipeline->descriptorPool); - assert(res == VK_SUCCESS); - - std::array layouts; - layouts.fill(pimpl->descriptorSetLayout); - VkDescriptorSetAllocateInfo dSetAllocInfo{}; - dSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - dSetAllocInfo.descriptorPool = pipeline->descriptorPool; - dSetAllocInfo.descriptorSetCount = FRAMES_IN_FLIGHT; - dSetAllocInfo.pSetLayouts = layouts.data(); - res = vkAllocateDescriptorSets(pimpl->device, &dSetAllocInfo, pipeline->descriptorSets.data()); - assert(res == VK_SUCCESS); - - for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { - VkDescriptorBufferInfo bufferInfo{}; - bufferInfo.buffer = pipeline->uniformBuffers[i]->buffer; - bufferInfo.offset = 0; - bufferInfo.range = uniformBufferSize; - - VkWriteDescriptorSet descriptorWrite{}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = pipeline->descriptorSets[i]; - descriptorWrite.dstBinding = 0; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = &bufferInfo; - descriptorWrite.pImageInfo = nullptr; - descriptorWrite.pTexelBufferView = nullptr; - - vkUpdateDescriptorSets(pimpl->device, 1, &descriptorWrite, 0, nullptr); - } // get vertex attrib layout: VkVertexInputBindingDescription bindingDescription{ }; @@ -906,7 +845,7 @@ namespace engine { VkPipelineShaderStageCreateInfo shaderStages[2] = { vertShaderStageInfo, fragShaderStageInfo }; - // this sets "vertex attribute pointers" + // set the vertex input layout VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertexInputInfo.vertexBindingDescriptionCount = 1; @@ -931,6 +870,7 @@ namespace engine { scissor.offset = { 0, 0 }; scissor.extent = pimpl->swapchain.extent; + // Dynamic states removes the need to re-create pipelines whenever the window size changes std::vector dynamicStates = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR @@ -968,8 +908,8 @@ namespace engine { VkPipelineMultisampleStateCreateInfo multisampling{}; multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = pimpl->swapchain.msaaSamples; multisampling.minSampleShading = 1.0f; // ignored multisampling.pSampleMask = nullptr; // ignored multisampling.alphaToCoverageEnable = VK_FALSE; // ignored @@ -1022,16 +962,14 @@ namespace engine { pushConstantRange.size = PUSH_CONSTANT_MAX_SIZE; pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - std::array setLayouts{ pimpl->descriptorSetLayout, pimpl->samplerSetLayout}; - VkPipelineLayoutCreateInfo layoutInfo{}; layoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - layoutInfo.setLayoutCount = (uint32_t)setLayouts.size(); - layoutInfo.pSetLayouts = setLayouts.data(); + layoutInfo.setLayoutCount = 0; + layoutInfo.pSetLayouts = nullptr; layoutInfo.pushConstantRangeCount = 1; layoutInfo.pPushConstantRanges = &pushConstantRange; - res = vkCreatePipelineLayout(pimpl->device, &layoutInfo, nullptr, &pipeline->layout); + res = vkCreatePipelineLayout(pimpl->device.device, &layoutInfo, nullptr, &pipeline->layout); assert(res == VK_SUCCESS); VkGraphicsPipelineCreateInfo createInfo{}; @@ -1040,7 +978,7 @@ namespace engine { createInfo.pStages = shaderStages; createInfo.pVertexInputState = &vertexInputInfo; createInfo.pInputAssemblyState = &inputAssembly; - createInfo.pViewportState = &viewportState; + createInfo.pViewportState = &viewportState; // TODO: maybe this isn't needed? createInfo.pRasterizationState = &rasterizer; createInfo.pMultisampleState = &multisampling; createInfo.pDepthStencilState = &depthStencil; @@ -1052,13 +990,11 @@ namespace engine { createInfo.basePipelineHandle = VK_NULL_HANDLE; createInfo.basePipelineIndex = -1; - res = vkCreateGraphicsPipelines(pimpl->device, VK_NULL_HANDLE, 1, &createInfo, nullptr, &pipeline->handle); + res = vkCreateGraphicsPipelines(pimpl->device.device, VK_NULL_HANDLE, 1, &createInfo, nullptr, &pipeline->handle); assert(res == VK_SUCCESS); - vkDestroyShaderModule(pimpl->device, fragShaderModule, nullptr); - vkDestroyShaderModule(pimpl->device, vertShaderModule, nullptr); - -#endif + vkDestroyShaderModule(pimpl->device.device, fragShaderModule, nullptr); + vkDestroyShaderModule(pimpl->device.device, vertShaderModule, nullptr); return pipeline; @@ -1067,16 +1003,8 @@ namespace engine { void GFXDevice::destroyPipeline(const gfx::Pipeline* pipeline) { -#if 0 - vkDestroyPipeline(pimpl->device, pipeline->handle, nullptr); - vkDestroyPipelineLayout(pimpl->device, pipeline->layout, nullptr); - - vkDestroyDescriptorPool(pimpl->device, pipeline->descriptorPool, nullptr); - - for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { - destroyBuffer(pipeline->uniformBuffers[i]); - } -#endif + vkDestroyPipeline(pimpl->device.device, pipeline->handle, nullptr); + vkDestroyPipelineLayout(pimpl->device.device, pipeline->layout, nullptr); delete pipeline; } diff --git a/src/systems/render.cpp b/src/systems/render.cpp index e993f44..ea8db8a 100644 --- a/src/systems/render.cpp +++ b/src/systems/render.cpp @@ -83,8 +83,7 @@ namespace engine { r->mesh->getIB(), r->mesh->getCount(), &pushConsts, - sizeof(pushConsts), - r->material->m_texture->getHandle() + sizeof(pushConsts) );*/ } diff --git a/test/src/game.cpp b/test/src/game.cpp index 49062b3..c181e04 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -56,6 +56,17 @@ void playGame(bool enableFrameLimiter) auto myScene = app.sceneManager()->createEmptyScene(); + const std::string vertPath = app.getResourcePath("engine/shaders/test.vert"); + const std::string fragPath = app.getResourcePath("engine/shaders/test.frag"); + engine::resources::Shader::VertexParams vertexParams{}; + vertexParams.hasColor = false; + vertexParams.hasNormal = false; + vertexParams.hasTangent = false; + vertexParams.hasUV0 = false; + bool alphaBlending = false; + bool cullBackFace = false; + engine::resources::Shader testShader(app.gfx(), vertPath.c_str(), fragPath.c_str(), vertexParams, alphaBlending, cullBackFace); + #if 0 /* create camera */