diff --git a/CMakeLists.txt b/CMakeLists.txt index c449caa..d6a0a17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,7 +177,7 @@ function (add_chapter CHAPTER_NAME) target_link_libraries (${CHAPTER_NAME} ${CHAPTER_LIBS}) endif () if (DEFINED CHAPTER_MODELS) - list(TRANSFORM CHAPTER_MODELS PREPEND "${CMAKE_SOURCE_DIR}/assets/") + list(TRANSFORM CHAPTER_MODELS PREPEND "${CMAKE_SOURCE_DIR}/models/") file (COPY ${CHAPTER_MODELS} DESTINATION ${CMAKE_BINARY_DIR}/${CHAPTER_NAME}/models) endif () if (DEFINED CHAPTER_TEXTURES) diff --git a/src/main.cpp b/src/main.cpp index 713a5fb..74f6947 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -107,14 +107,14 @@ struct UniformBufferObject { class HelloTriangleApplication { public: void run() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Global initialisation...\n"; #endif initWindow(); initVulkan(); mainLoop(); cleanup(); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Bye Bye !\n"; #endif @@ -151,7 +151,7 @@ class HelloTriangleApplication { vk::raii::DeviceMemory vertexBufferMemory = nullptr; // Index - Buffers vk::raii::Buffer indexBuffer = nullptr; - vk::raii::DeviceMemory indexBufferMemory = nullptr;s + vk::raii::DeviceMemory indexBufferMemory = nullptr; // Uniform Buffers - Buffers std::vector uniformBuffers; std::vector uniformBuffersMemory; @@ -186,7 +186,7 @@ class HelloTriangleApplication { //========== Inits ========== void initWindow() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating GLFW window...\n"; #endif glfwInit(); @@ -198,13 +198,13 @@ class HelloTriangleApplication { window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); glfwSetWindowUserPointer(window, this); glfwSetFramebufferSizeCallback(window, framebufferResizeCallback); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Window created !\n"; #endif } void initVulkan() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "\tInitialing Vulkan...\n"; #endif createInstance(); @@ -221,6 +221,7 @@ class HelloTriangleApplication { createTextureImage(); createTextureImageView(); createTextureSampler(); + loadModel(); createVertexBuffer(); createIndexBuffer(); createUniformBuffers(); @@ -228,13 +229,13 @@ class HelloTriangleApplication { createDescriptorSets(); createCommandBuffers(); createSyncObjects(); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "\tVulkan is initialised !\n"; #endif } void mainLoop() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Main Loop...\n"; #endif while (!glfwWindowShouldClose(window)) { @@ -250,14 +251,14 @@ class HelloTriangleApplication { } void cleanup() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Cleaning up...\n"; #endif cleanupSwapChain(); surface = nullptr; glfwDestroyWindow(window); glfwTerminate(); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Done !\n"; #endif } @@ -265,7 +266,7 @@ class HelloTriangleApplication { //========== UTILS ========== void createInstance() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a Vulkan Instance...\n"; #endif constexpr vk::ApplicationInfo appInfo{ @@ -315,7 +316,7 @@ class HelloTriangleApplication { .ppEnabledExtensionNames = requiredExtensions.data()}; instance = vk::raii::Instance(context, createInfo); - #ifdef DEBUG + #ifndef NDEBUG std::cout << requiredExtensions.size() << " extensions loaded !\n"; std::cout << requiredLayers.size() << " layers loaded !\n"; @@ -324,7 +325,7 @@ class HelloTriangleApplication { } void setupDebugMessenger () { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Setting up the messenger !\n"; #endif if (!enableValidationLayers) { @@ -339,13 +340,13 @@ class HelloTriangleApplication { .pfnUserCallback = &debugCallback }; debugMessenger = instance.createDebugUtilsMessengerEXT(debugUtilsMessengerCreateInfoEXT); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Messenger set up !\n"; #endif } void pickPhysicalDevice() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Selecting the GPU...\n"; #endif std::vector devices = instance.enumeratePhysicalDevices(); @@ -362,7 +363,7 @@ class HelloTriangleApplication { }); if (devIter != devices.end()) { physicalDevice = *devIter; - #ifdef DEBUG + #ifndef NDEBUG std::cout << "GPU selected !\n"; #endif } @@ -373,7 +374,7 @@ class HelloTriangleApplication { void createLogicalDevice() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a logical device !\n"; #endif @@ -412,13 +413,13 @@ class HelloTriangleApplication { device = vk::raii::Device( physicalDevice, deviceCreateInfo ); queue = vk::raii::Queue( device, queueIndex, 0 ); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Logical device created\n"; #endif } void createSurface() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a surface !\n"; #endif VkSurfaceKHR _surface; @@ -426,13 +427,13 @@ class HelloTriangleApplication { throw std::runtime_error("Failed to create Window surface !\nAborting..."); } surface = vk::raii::SurfaceKHR(instance, _surface); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Surface created !\n"; #endif } void createSwapChain() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating Swap Chain...\n"; #endif auto surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(*surface); @@ -460,13 +461,13 @@ class HelloTriangleApplication { swapChain = vk::raii::SwapchainKHR(device, swapChainCreateInfo); swapChainImages = swapChain.getImages(); swapChainImageFormat = swapChainSurfaceFormat.format; - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Swap Chain Created !\n"; #endif } void createImageViews() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating Image View...\n"; #endif swapChainImageViews.clear(); @@ -478,13 +479,13 @@ class HelloTriangleApplication { vk::ImageAspectFlagBits::eColor )); } - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Image View created !\n"; #endif } void createDescriptorSetLayout() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating the descriptor set...\n"; #endif std::array bindings = { @@ -510,13 +511,13 @@ class HelloTriangleApplication { descriptorSetLayout = vk::raii::DescriptorSetLayout(device, layoutInfo); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Descriptor set created !\n"; #endif } void createGraphicsPipeline() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating the Graphics Pipeline...\n"; #endif vk::raii::ShaderModule shaderModule = createShaderModule(readFile("shaders/slang.spv")); @@ -640,13 +641,13 @@ class HelloTriangleApplication { graphicsPipeline = vk::raii::Pipeline(device, nullptr, pipelineInfo); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Pipeline created !\n"; #endif } void createCommandPool() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a command pool\n"; #endif vk::CommandPoolCreateInfo poolInfo { @@ -655,13 +656,13 @@ class HelloTriangleApplication { }; commandPool = vk::raii::CommandPool(device, poolInfo); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Command pool created\n"; #endif } void createDepthResources() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a depth ressouce...\n"; #endif vk::Format depthFormat = findDepthFormat(); @@ -681,13 +682,13 @@ class HelloTriangleApplication { depthFormat, vk::ImageAspectFlagBits::eDepth ); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Depth ressouce created !\n"; #endif } void createTextureImage(){ - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a texture image...\n"; #endif int texWidth, texHeight, texChannels; @@ -728,13 +729,13 @@ class HelloTriangleApplication { copyBufferToImage(stagingBuffer, textureImage, static_cast(texWidth), static_cast(texHeight)); transitionImageLayout(textureImage, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Texture image created !\n"; #endif } void createTextureImageView() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating the texture image...\n"; #endif textureImageView = createImageView( @@ -742,7 +743,7 @@ class HelloTriangleApplication { vk::Format::eR8G8B8A8Srgb, vk::ImageAspectFlagBits::eColor ); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Texture Image created !\n"; #endif } @@ -757,7 +758,7 @@ class HelloTriangleApplication { vk::raii::Image &image, vk::raii::DeviceMemory &imageMemory ) { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating an image with usage " << vk::to_string(usage) << '\n'; #endif vk::ImageCreateInfo imageInfo { @@ -782,13 +783,13 @@ class HelloTriangleApplication { imageMemory = vk::raii::DeviceMemory(device, allocInfo); image.bindMemory(imageMemory, 0); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Created image with usage " << vk::to_string(usage) << '\n'; #endif } void createTextureSampler() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a texture sampler...\n"; #endif vk::PhysicalDeviceProperties properties = physicalDevice.getProperties(); @@ -812,13 +813,13 @@ class HelloTriangleApplication { textureSampler = vk::raii::Sampler(device, samplerInfo); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Texture sampler created !\n"; #endif } void loadModel() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Loading the 3D model...\n"; #endif @@ -827,17 +828,39 @@ class HelloTriangleApplication { std::vector materials; std::string warn, err; - if (!tinyobj::LoadObj(&attrib, &matrials, &warn, &err, MODEL_PATH.c_str())) { + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, MODEL_PATH.c_str())) { throw std::runtime_error(warn + err); } - #ifdef DEBUG + for (const auto& shape : shapes) { + for (const auto& index : shape.mesh.indices) { + Vertex vertex; + + vertex.pos = { + attrib.vertices[3 * index.vertex_index + 0], + attrib.vertices[3 * index.vertex_index + 1], + attrib.vertices[3 * index.vertex_index + 2] + }; + + vertex.texCoord = { + attrib.texcoords[2 * index.texcoord_index + 0], + 1.0f - attrib.texcoords[2 * index.texcoord_index + 1] + }; + + vertex.color = {1.0f, 1.0f, 1.0f}; + + vertices.push_back(vertex); + indices.push_back(indices.size()); + } + } + + #ifndef NDEBUG std::cout << "3D model loaded !\n"; #endif } void createVertexBuffer() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a vertex buffer...\n"; #endif vk::raii::Buffer stagingBuffer = nullptr; @@ -864,7 +887,7 @@ class HelloTriangleApplication { vertexBufferMemory ); copyBuffer(stagingBuffer, vertexBuffer, bufferSize); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Vertex buffer created !\n"; #endif } @@ -874,7 +897,7 @@ class HelloTriangleApplication { vk::raii::Buffer & dstBuffer, vk::DeviceSize size ) { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Copying buffer " << vk::to_string(srcBuffer.objectType) << " to " << vk::to_string(dstBuffer.objectType) << "...\n"; #endif vk::raii::CommandBuffer commandCopyBuffer = beginSingleTimeCommands(); @@ -883,13 +906,13 @@ class HelloTriangleApplication { endSingleTimeCommands(commandCopyBuffer); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Copied buffer " << vk::to_string(srcBuffer.objectType) << " to " << vk::to_string(dstBuffer.objectType) << "!\n"; #endif } void createIndexBuffer() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating an index buffer...\n"; #endif vk::DeviceSize bufferSize = sizeof( indices[0] ) * indices.size(); @@ -917,13 +940,13 @@ class HelloTriangleApplication { ); copyBuffer(stagingBuffer, indexBuffer, bufferSize); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Index buffer created !\n"; #endif } void createUniformBuffers() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating uniform buffers...\n"; #endif uniformBuffers.clear(); @@ -946,13 +969,13 @@ class HelloTriangleApplication { uniformBuffersMemory.emplace_back(std::move(bufferMem)); uniformBuffersMapped.emplace_back( uniformBuffersMemory[i].mapMemory(0, bufferSize)); } - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Uniform buffers created !\n"; #endif } void createDescriptorPool() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a descriptor pool...\n"; #endif std::array poolSize { @@ -974,13 +997,13 @@ class HelloTriangleApplication { descriptorPool = vk::raii::DescriptorPool(device, poolInfo); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Descriptor pool created !\n"; #endif } void createDescriptorSets() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a descriptor set...\n"; #endif std::vector layouts( MAX_FRAMES_IN_FLIGHT, *descriptorSetLayout ); @@ -1026,13 +1049,13 @@ class HelloTriangleApplication { device.updateDescriptorSets(descriptorWrites, {}); } - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Descriptor sets created !\n"; #endif } void createCommandBuffers() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a command buffers\n"; #endif @@ -1043,7 +1066,7 @@ class HelloTriangleApplication { }; commandBuffers = vk::raii::CommandBuffers(device, allocInfo); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Command buffer created\n"; #endif } @@ -1269,11 +1292,11 @@ class HelloTriangleApplication { auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); if (result == vk::Result::eErrorOutOfDateKHR) { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "SwapChain out of date ! \n"; #endif recreateSwapChain(); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Fixed the swapchain !\n"; #endif return; @@ -1338,7 +1361,7 @@ class HelloTriangleApplication { } void recreateSwapChain() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Re-creating the SwapChain...\n"; #endif @@ -1358,7 +1381,7 @@ class HelloTriangleApplication { createImageViews(); createDepthResources(); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "SwapChain re-created sucessfully !\n"; #endif } @@ -1370,7 +1393,7 @@ class HelloTriangleApplication { vk::raii::Buffer& buffer, vk::raii::DeviceMemory& bufferMemory ) { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating a buffer of type: " << vk::to_string(usage) << '\n'; #endif @@ -1389,7 +1412,7 @@ class HelloTriangleApplication { bufferMemory = vk::raii::DeviceMemory(device, allocInfo); buffer.bindMemory(*bufferMemory, 0); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Buffer of type: " << vk::to_string(usage) << " sucessfully created !\n"; #endif } @@ -1401,7 +1424,7 @@ class HelloTriangleApplication { void * ){ if (severity == vk::DebugUtilsMessageSeverityFlagBitsEXT::eError || severity == vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning) { - #ifdef DEBUG + #ifndef NDEBUG std::cerr << "Validation layer: type " << to_string(type) << " msg: " << pCallbackData->pMessage << std::endl; #endif } @@ -1437,7 +1460,7 @@ class HelloTriangleApplication { } uint32_t findQueueFamilies(vk::raii::PhysicalDevice physicalDevice) { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Selecting a queue...\n"; #endif // Get the index of the first queue that support graphics @@ -1446,7 +1469,7 @@ class HelloTriangleApplication { for (uint32_t qfpIndex = 0; qfpIndex < queueFamilyProperties.size(); qfpIndex++) { if ((queueFamilyProperties[qfpIndex].queueFlags & vk::QueueFlagBits::eGraphics) && physicalDevice.getSurfaceSupportKHR(qfpIndex, *surface)) { // The queue has both graphics and present - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Found a graphics and present queue !\n"; #endif queueIndex = qfpIndex; @@ -1489,7 +1512,7 @@ class HelloTriangleApplication { } static std::vector readFile(const std::string& filename) { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Loading " << filename << " from disk...\n"; #endif std::ifstream file(filename, std::ios::ate | std::ios::binary); @@ -1502,14 +1525,14 @@ class HelloTriangleApplication { file.seekg(0, std::ios::beg); file.read(buffer.data(), static_cast(buffer.size())); file.close(); - #ifdef DEBUG + #ifndef NDEBUG std::cout << "File loaded with size of " << buffer.size() << '\n'; #endif return buffer; } [[nodiscard]] vk::raii::ShaderModule createShaderModule(const std::vector& code) const { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Creating shader module\n"; #endif vk::ShaderModuleCreateInfo createInfo{ @@ -1517,7 +1540,7 @@ class HelloTriangleApplication { .pCode = reinterpret_cast(code.data()) }; vk::raii::ShaderModule shaderModule { device, createInfo }; - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Shader module created\n"; #endif return shaderModule; @@ -1608,7 +1631,7 @@ class HelloTriangleApplication { }; int main() { - #ifdef DEBUG + #ifndef NDEBUG std::cout << "Starting the app...\n"; #endif HelloTriangleApplication app;