diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index d139649b983ec3011a7366e02e7490231d9df29c..388bc0ea40950f0e73a23a280af753b79ad00da7 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -173,6 +173,18 @@ namespace vkcv Buffer<T> createBuffer(vkcv::BufferType type, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL) { return Buffer<T>::create(m_BufferManager.get(), type, count, memoryType); } + + /** + * Creates an #Image with a given format, width, height and depth. + * + * @param format Image format + * @param width Image width + * @param height Image height + * @param depth Image depth + * @return Image-Object + */ + [[nodiscard]] + Image createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth = 1); /** TODO: * @param setDescriptions diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp index 1c162cdc4a9494d484d97ab39613144571a26283..5050513b6fd612605b7c83d18d2d3beaaef9a8a0 100644 --- a/include/vkcv/Image.hpp +++ b/include/vkcv/Image.hpp @@ -12,9 +12,8 @@ namespace vkcv { class ImageManager; class Image { + friend class Core; public: - static Image create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth); - [[nodiscard]] vk::Format getFormat() const; @@ -43,6 +42,9 @@ namespace vkcv { vk::ImageLayout m_layout; Image(ImageManager* manager, const ImageHandle& handle, vk::Format format, uint32_t width, uint32_t height, uint32_t depth); + + static Image create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth); + }; } diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index e1cbc40e747f9f68e44db6ea9ca3dcd556148a4b..ced7867ee26e4b3d9d700eb3a7a46ec326b966e2 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -83,6 +83,10 @@ int main(int argc, const char** argv) { std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; return EXIT_FAILURE; } + + vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, mesh.texture_hack.w, mesh.texture_hack.h); + + texture.fill(mesh.texture_hack.img); auto start = std::chrono::system_clock::now(); while (window.isWindowOpen()) { @@ -97,5 +101,6 @@ int main(int argc, const char** argv) { core.renderMesh(trianglePass, trianglePipeline, windowWidth, windowHeight, sizeof(mvp), &mvp, vertexBuffer.getHandle(), indexBuffer.getHandle(), mesh.vertexGroups[0].numIndices); core.endFrame(); } + return 0; } diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp index a6ec80085424a25a6f4285254253829fc5b59257..740e89993860a7f71ac78aedae5cf3ed946c7b49 100644 --- a/src/vkcv/BufferManager.cpp +++ b/src/vkcv/BufferManager.cpp @@ -328,10 +328,12 @@ namespace vkcv { if (buffer.m_memory) { device.freeMemory(buffer.m_memory); + buffer.m_memory = nullptr; } if (buffer.m_handle) { device.destroyBuffer(buffer.m_handle); + buffer.m_handle = nullptr; } } diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index ecadba04f1230e6d0531851e862b44aca978bdb6..5c924743c95f67f00095264f9d99308b1403b017 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -266,6 +266,11 @@ namespace vkcv finish(); } } + + Image Core::createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth) + { + return Image::create(m_ImageManager.get(), format, width, height, depth); + } ResourcesHandle Core::createResourceDescription(const std::vector<DescriptorSet> &descriptorSets) { diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index 188bbebd0ddc64dc0fad72a1bc93c2ed89fffeee..39cca04b3ba5fa9842a225272cf6a8732838a938 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -47,22 +47,49 @@ namespace vkcv { ImageHandle ImageManager::createImage(uint32_t width, uint32_t height, uint32_t depth, vk::Format format) { - vk::ImageCreateFlags createFlags; - vk::ImageUsageFlags imageUsageFlags = (vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst); + const vk::PhysicalDevice& physicalDevice = m_core->getContext().getPhysicalDevice(); + + const vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(format); - format = vk::Format::eR8G8B8A8Unorm; // TODO + vk::ImageCreateFlags createFlags; + vk::ImageUsageFlags imageUsageFlags = ( + vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst + ); const vk::Device& device = m_core->getContext().getDevice(); + vk::ImageType imageType = vk::ImageType::e3D; + + if (depth <= 1) { + if (height <= 1) { + imageType = vk::ImageType::e1D; + } else { + imageType = vk::ImageType::e2D; + } + } + + vk::ImageTiling imageTiling = vk::ImageTiling::eOptimal; + + if (!formatProperties.optimalTilingFeatures) { + if (!formatProperties.linearTilingFeatures) + return ImageHandle(); + + imageTiling = vk::ImageTiling::eLinear; + } + + const vk::ImageFormatProperties imageFormatProperties = physicalDevice.getImageFormatProperties( + format, imageType, imageTiling, imageUsageFlags + ); + vk::ImageCreateInfo imageCreateInfo( createFlags, - vk::ImageType::e2D, + imageType, format, - vk::Extent3D(width, height, 1), + vk::Extent3D(width, height, depth), 1, 1, vk::SampleCountFlagBits::e1, - vk::ImageTiling::eOptimal, + imageTiling, imageUsageFlags, vk::SharingMode::eExclusive, {}, @@ -72,7 +99,6 @@ namespace vkcv { vk::Image image = device.createImage(imageCreateInfo); const vk::MemoryRequirements requirements = device.getImageMemoryRequirements(image); - const vk::PhysicalDevice& physicalDevice = m_core->getContext().getPhysicalDevice(); vk::MemoryPropertyFlags memoryTypeFlags = vk::MemoryPropertyFlagBits::eDeviceLocal; @@ -102,6 +128,7 @@ namespace vkcv { (newLayout == vk::ImageLayout::eTransferDstOptimal)) { destinationAccessMask = vk::AccessFlagBits::eTransferWrite; + sourceStage = vk::PipelineStageFlagBits::eTopOfPipe; destinationStage = vk::PipelineStageFlagBits::eTransfer; } @@ -110,6 +137,7 @@ namespace vkcv { { sourceAccessMask = vk::AccessFlagBits::eTransferWrite; destinationAccessMask = vk::AccessFlagBits::eShaderRead; + sourceStage = vk::PipelineStageFlagBits::eTransfer; destinationStage = vk::PipelineStageFlagBits::eFragmentShader; } @@ -142,7 +170,7 @@ namespace vkcv { ); SubmitInfo submitInfo; - submitInfo.queueType = QueueType::Transfer; + submitInfo.queueType = QueueType::Graphics; m_core->submitCommands( submitInfo, @@ -162,10 +190,6 @@ namespace vkcv { void ImageManager::fillImage(const ImageHandle& handle, void* data, size_t size) { - if (size == 0) { - size = SIZE_MAX; - } - const uint64_t id = handle.getId(); if (id >= m_images.size()) { @@ -180,9 +204,9 @@ namespace vkcv { vk::ImageLayout::eTransferDstOptimal ); - uint32_t channels = 3; // TODO + uint32_t channels = 4; // TODO: check image.m_format const size_t image_size = ( - image.m_width * image.m_height * image.m_depth * channels * sizeof(char) + image.m_width * image.m_height * image.m_depth * channels ); const size_t max_size = std::min(size, image_size); @@ -249,10 +273,12 @@ namespace vkcv { if (image.m_memory) { device.freeMemory(image.m_memory); + image.m_memory = nullptr; } if (image.m_handle) { device.destroyImage(image.m_handle); + image.m_handle = nullptr; } }