diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 01871dd0f..9bb213b7b 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -94,6 +94,7 @@ bool GlfwApplication::tryCreateContext(const Configuration& configuration) { glfwWindowHint(GLFW_ICONIFIED, flags >= Configuration::WindowFlag::Minimized); glfwWindowHint(GLFW_FLOATING, flags >= Configuration::WindowFlag::Floating); } + glfwWindowHint(GLFW_FOCUSED, configuration.windowFlags() >= Configuration::WindowFlag::Focused); /* Context window hints */ @@ -125,6 +126,7 @@ bool GlfwApplication::tryCreateContext(const Configuration& configuration) { glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); #endif } + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); /* Set context flags */ _window = glfwCreateWindow(configuration.size().x(), configuration.size().y(), configuration.title().c_str(), monitor, nullptr); @@ -144,7 +146,7 @@ bool GlfwApplication::tryCreateContext(const Configuration& configuration) { glfwMakeContextCurrent(_window); /* Return true if the initialization succeeds */ - return _context->tryCreate(); + return true; //_context->tryCreate(); } GlfwApplication::~GlfwApplication() { diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index 368b06080..810c46be3 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -45,6 +45,8 @@ #endif #include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include namespace Magnum { namespace Platform { @@ -223,6 +225,11 @@ class GlfwApplication { #ifdef MAGNUM_TARGET_VULKAN VkSurfaceKHR createVkSurface(); + + HWND getPlatformWindow() { + return glfwGetWin32Window(_window); + } + #endif #ifdef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Magnum/Vk/Buffer.cpp b/src/Magnum/Vk/Buffer.cpp new file mode 100644 index 000000000..2c32a65a0 --- /dev/null +++ b/src/Magnum/Vk/Buffer.cpp @@ -0,0 +1,36 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Buffer.h" + + +namespace Magnum { namespace Vk { + +Buffer::~Buffer() { + vkDestroyBuffer(_device, _buffer, nullptr); +} + +}} diff --git a/src/Magnum/Vk/Buffer.h b/src/Magnum/Vk/Buffer.h new file mode 100644 index 000000000..1d8e88695 --- /dev/null +++ b/src/Magnum/Vk/Buffer.h @@ -0,0 +1,143 @@ +#ifndef Magnum_Vk_Buffer_h +#define Magnum_Vk_Buffer_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::Buffer + */ + +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/CommandBuffer.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/DeviceMemory.h" +#include "Magnum/Vk/visibility.h" + +#include "vulkan.h" + +namespace Magnum { namespace Vk { + +enum class BufferUsage: UnsignedInt { + TransferSrc = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + TransferDst = VK_BUFFER_USAGE_TRANSFER_DST_BIT, + UniformTexelBuffer = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, + StorageTexelBuffer = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, + UniformBuffer = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + StorageBuffer = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + IndexBuffer = VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + VertexBuffer = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + IndirectBuffer = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, +}; + +typedef Containers::EnumSet BufferUsageFlags; + +CORRADE_ENUMSET_OPERATORS(BufferUsageFlags) + +class MAGNUM_VK_EXPORT Buffer { + public: + + Buffer(Device& device, UnsignedInt size, BufferUsageFlags usage): + _device{device}, + _size{size} + { + VkBufferCreateInfo bufferInfo = {}; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.pNext = nullptr; + bufferInfo.size = size; + bufferInfo.usage = VkBufferUsageFlags(usage); + + VkResult err = vkCreateBuffer(_device, &bufferInfo, nullptr, &_buffer); + MAGNUM_VK_ASSERT_ERROR(err); + } + + /** @brief Copying is not allowed */ + Buffer(const Buffer&) = delete; + + /** @brief Move constructor */ + Buffer(Buffer&& other); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyBuffer} + */ + ~Buffer(); + + /** @brief Copying is not allowed */ + Buffer& operator=(const Buffer&) = delete; + + /** @brief Move assignment is not allowed */ + Buffer& operator=(Buffer&&) = delete; + + operator VkBuffer() const { + return _buffer; + } + + VkMemoryRequirements getMemoryRequirements() const { + VkMemoryRequirements memReqs; + vkGetBufferMemoryRequirements(_device, _buffer, &memReqs); + + return memReqs; + } + + UnsignedInt size() const { + return _size; + } + + Buffer& bindBufferMemory(const DeviceMemory& deviceMemory, UnsignedLong offset=0) { + VkResult err = vkBindBufferMemory(_device, _buffer, deviceMemory, offset); + MAGNUM_VK_ASSERT_ERROR(err); + + return *this; + } + + auto cmdCopyTo(Buffer& dest, std::initializer_list regions) { + const VkBuffer source = _buffer; + return [source, &dest, ®ions](VkCommandBuffer cmdBuffer){ + vkCmdCopyBuffer(cmdBuffer, source, dest, regions.size(), std::vector(regions).data()); + }; + } + + auto cmdFullCopyTo(Buffer& dest) { + const VkBuffer source = _buffer; + const UnsignedInt size = _size; + return [source, &dest, size](VkCommandBuffer cmdBuffer){ + VkBufferCopy bufferCopy = {0, 0, size}; + vkCmdCopyBuffer(cmdBuffer, source, dest, 1, &bufferCopy); + }; + } + + private: + Device& _device; + VkBuffer _buffer; + UnsignedInt _size; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index 862904385..68777ac2b 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -28,10 +28,42 @@ find_package(Vulkan REQUIRED) set(MagnumVk_SRCS - Context.cpp) + Buffer.cpp + CommandBuffer.cpp + CommandPool.cpp + Context.cpp + Device.cpp + DeviceMemory.cpp + Framebuffer.cpp + Image.cpp + ImageView.cpp + PhysicalDevice.cpp + Pipeline.cpp + Queue.cpp + RenderPass.cpp + Semaphore.cpp + Shader.cpp + Swapchain.cpp) set(MagnumVk_HEADERS + Buffer.h + Command.h + CommandBuffer.h + CommandPool.h Context.h + Device.h + DeviceMemory.h + Framebuffer.h + Image.h + ImageView.h + Math.h + PhysicalDevice.h + Pipeline.h + Queue.h + RenderPass.h + Semaphore.h + Shader.h + Swapchain.h visibility.h) @@ -45,6 +77,8 @@ set(MagnumVk_PRIVATE_HEADERS "") add_library(MagnumVk ${SHARED_OR_STATIC} ${MagnumVk_SRCS} ${MagnumVk_HEADERS} + + ${MagnumVkTest_HEADERS} ${MagnumVk_PRIVATE_HEADERS}) set_target_properties(MagnumVk PROPERTIES DEBUG_POSTFIX "-d") if(BUILD_STATIC_PIC) @@ -52,13 +86,21 @@ if(BUILD_STATIC_PIC) endif() target_link_libraries(MagnumVk Magnum Vulkan::Vulkan) +set_target_properties(MagnumVk PROPERTIES + CORRADE_CXX_STANDARD 14 + INTERFACE_CORRADE_CXX_STANDARD 14) + + install(TARGETS MagnumVk RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) + +install(FILES ${MagnumVkTest_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Vk/Test) install(FILES ${MagnumVk_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Vk) if(BUILD_TESTS) + set(VK_TEST_LIBRARIES MagnumVk) add_subdirectory(Test) endif() diff --git a/src/Magnum/Vk/Command.h b/src/Magnum/Vk/Command.h new file mode 100644 index 000000000..6ffba9e51 --- /dev/null +++ b/src/Magnum/Vk/Command.h @@ -0,0 +1,96 @@ +#ifndef Magnum_Vk_Command_h +#define Magnum_Vk_Command_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Namespace @ref Magnum::Vk::Cmd + */ + +#include "vulkan.h" + +#include +#include + +#include "Magnum/Tags.h" +#include "Magnum/Magnum.h" +#include "Magnum/Math/Range.h" +#include "Magnum/Vk/CommandBuffer.h" +#include "Magnum/Vk/Pipeline.h" +#include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Image.h" + +namespace Magnum { namespace Vk { + +template +CommandBuffer& operator << (CommandBuffer& cmdBuffer, const Lambda& lambda) { + lambda(cmdBuffer); + return cmdBuffer; +} + +namespace Cmd { + +auto setScissor(UnsignedInt firstScissor, const std::initializer_list& ranges) { + return [firstScissor, &ranges](VkCommandBuffer cmdBuffer){ + Corrade::Containers::Array vkRects(ranges.size()); + + UnsignedInt i = 0; + for(auto& range: ranges) { + vkRects[i] = {{range.left(), range.bottom()}, {range.sizeX(), range.sizeY()}}; + ++i; + } + vkCmdSetScissor(cmdBuffer, firstScissor, vkRects.size(), vkRects.data()); + }; +} + +auto setViewport(UnsignedInt firstViewport, const std::vector& viewports) { + return [firstViewport, &viewports](VkCommandBuffer cmdBuffer){ + vkCmdSetViewport(cmdBuffer, firstViewport, viewports.size(), viewports.data()); + }; +} + +auto pipelineBarrier(PipelineStageFlags srcStageMask, + PipelineStageFlags dstStageMask, + const std::vector& memoryBarriers, + const std::vector& bufferMemoryBarriers, + const std::vector& imageMemoryBarriers) { + return [&memoryBarriers, &bufferMemoryBarriers, &imageMemoryBarriers](VkCommandBuffer cmdBuffer){ + vkCmdPipelineBarrier(cmdBuffer, + VkPipelineStageFlags(srcStageFlags), VkPipelineStageFlags(dstStageMask), + 0, memoryBarriers.size(), + Containers::StaticArrayView(memoryBarriers), + bufferMemoryBarriers.size(), + Containers::StaticArrayView(bufferMemoryBarriers), + imageMemoryBarriers.size(), + Containers::StaticArrayView(imageMemoryBarriers) + + ); + } +} + +}}} + +#endif diff --git a/src/Magnum/Vk/CommandBuffer.cpp b/src/Magnum/Vk/CommandBuffer.cpp new file mode 100644 index 000000000..9b94fc88d --- /dev/null +++ b/src/Magnum/Vk/CommandBuffer.cpp @@ -0,0 +1,38 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "CommandBuffer.h" + +#include "CommandPool.h" + + +namespace Magnum { namespace Vk { + +CommandBuffer::~CommandBuffer() { + _pool.freeCommandBuffer(this); +} + +}} diff --git a/src/Magnum/Vk/CommandBuffer.h b/src/Magnum/Vk/CommandBuffer.h new file mode 100644 index 000000000..6119615a7 --- /dev/null +++ b/src/Magnum/Vk/CommandBuffer.h @@ -0,0 +1,130 @@ +#ifndef Magnum_Vk_CommandBuffer_h +#define Magnum_Vk_CommandBuffer_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::CommandBuffer + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Math/Range.h" +#include "Magnum/Vk/Context.h" +#include "Magnum/Vk/visibility.h" + +#include "vulkan.h" + +namespace Magnum { namespace Vk { + +class CommandPool; + +class MAGNUM_VK_EXPORT CommandBuffer { + public: + + enum class Level: Int { + Primary = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + Secondary = VK_COMMAND_BUFFER_LEVEL_SECONDARY + }; + + enum class SubpassContents: UnsignedInt { + Inline = VK_SUBPASS_CONTENTS_INLINE, + SecondaryCommandBuffers = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, + }; + + CommandBuffer(VkCommandBuffer buffer, CommandPool& commandPool): + _cmdBuffer{buffer}, + _pool{commandPool} + { + } + + /** @brief Copying is not allowed */ + CommandBuffer(const CommandBuffer&) = delete; + + /** @brief Move constructor */ + CommandBuffer(CommandBuffer&& other); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyCommandBuffer} + */ + ~CommandBuffer(); + + /** @brief Copying is not allowed */ + CommandBuffer& operator=(const CommandBuffer&) = delete; + + /** @brief Move assignment is not allowed */ + CommandBuffer& operator=(CommandBuffer&&) = delete; + + operator VkCommandBuffer() const { + return _cmdBuffer; + } + + CommandBuffer& begin() { + VkCommandBufferBeginInfo cmdBufInfo = {}; + cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkBeginCommandBuffer(_cmdBuffer, &cmdBufInfo); + + return *this; + } + + CommandBuffer& end() { + VkResult err = vkEndCommandBuffer(_cmdBuffer); + MAGNUM_VK_ASSERT_ERROR(err); + + return *this; + } + + CommandBuffer& beginRenderPass(SubpassContents subpassContents, VkRenderPass renderPass, + VkFramebuffer framebuffer, Range2Di renderArea, + const std::vector& clearValues) { + VkRenderPassBeginInfo renderPassBeginInfo { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + nullptr, + renderPass, + framebuffer, + VkRect2D{{renderArea.left(), renderArea.bottom()}, {renderArea.sizeX(), renderArea.sizeY()}}, + clearValues.size(), + clearValues.data()}; + + vkCmdBeginRenderPass(_cmdBuffer, &renderPassBeginInfo, VkSubpassContents(subpassContents)); + + return *this; + } + + CommandBuffer& endRenderPass() { + vkCmdEndRenderPass(_cmdBuffer); + return *this; + } + + private: + VkCommandBuffer _cmdBuffer; + CommandPool& _pool; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/CommandPool.cpp b/src/Magnum/Vk/CommandPool.cpp new file mode 100644 index 000000000..24101eb4f --- /dev/null +++ b/src/Magnum/Vk/CommandPool.cpp @@ -0,0 +1,49 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "CommandPool.h" + + +namespace Magnum { namespace Vk { + +CommandPool::~CommandPool() { + vkDestroyCommandPool(_device.vkDevice(), _pool, nullptr); +} + +std::unique_ptr CommandPool::allocateCommandBuffer(CommandBuffer::Level level) { + VkCommandBuffer cmdBuffer; + VkCommandBufferAllocateInfo commandBufferAllocateInfo = {}; + commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + commandBufferAllocateInfo.commandPool = _pool; + commandBufferAllocateInfo.level = VkCommandBufferLevel(level); + commandBufferAllocateInfo.commandBufferCount = 1; + + vkAllocateCommandBuffers(_device.vkDevice(), &commandBufferAllocateInfo, &cmdBuffer); + + return std::unique_ptr{new CommandBuffer{cmdBuffer, *this}}; +} + +}} diff --git a/src/Magnum/Vk/CommandPool.h b/src/Magnum/Vk/CommandPool.h new file mode 100644 index 000000000..1dffbe344 --- /dev/null +++ b/src/Magnum/Vk/CommandPool.h @@ -0,0 +1,93 @@ +#ifndef Magnum_Vk_CommandPool_h +#define Magnum_Vk_CommandPool_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::CommandPool + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/CommandBuffer.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/PhysicalDevice.h" +#include "Magnum/Vk/visibility.h" + +#include "vulkan.h" + +namespace Magnum { namespace Vk { + +class MAGNUM_VK_EXPORT CommandPool { + friend class CommandBuffer; + + public: + + /** @brief Copying is not allowed */ + CommandPool(const Context&) = delete; + + /** @brief Move constructor */ + CommandPool(CommandPool&& other); + + CommandPool(Device& device, QueueFamily family): _device{device} { + const VkCommandPoolCreateInfo cmdPoolInfo = { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, + _device.physicalDevice().getQueueFamilyIndex(family)}; + vkCreateCommandPool(_device, &cmdPoolInfo, nullptr, &_pool); + } + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyCommandPool} + */ + ~CommandPool(); + + /** @brief Copying is not allowed */ + CommandPool& operator=(const CommandPool&) = delete; + + /** @brief Move assignment is not allowed */ + CommandPool& operator=(CommandPool&&) = delete; + + VkCommandPool vkCommandPool() { + return _pool; + } + + std::unique_ptr allocateCommandBuffer(CommandBuffer::Level level); + + private: + VkCommandPool _pool; + Device& _device; + + void freeCommandBuffer(CommandBuffer* buffer) { + VkCommandBuffer buffers = *buffer; + vkFreeCommandBuffers(_device.vkDevice(), _pool, 1, &buffers); + } +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Context.cpp b/src/Magnum/Vk/Context.cpp index 564c64299..fc76383e3 100644 --- a/src/Magnum/Vk/Context.cpp +++ b/src/Magnum/Vk/Context.cpp @@ -30,20 +30,16 @@ #include #include "vulkan.h" -PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback; -PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback; -PFN_vkDebugReportMessageEXT dbgBreakCallback; - -VkDebugReportCallbackEXT msgCallback; - namespace Magnum { namespace Vk { +unsigned int layerCount = 2; const char *validationLayerNames[] = { // This is a meta layer that enables all of the standard // validation layers in the correct order : // threading, parameter_validation, device_limits, object_tracker, image, core_validation, swapchain, and unique_objects - "VK_LAYER_LUNARG_standard_validation" + "VK_LAYER_LUNARG_standard_validation", + "VK_LAYER_LUNARG_api_dump" }; Context* Context::_current = nullptr; @@ -79,7 +75,7 @@ Context::~Context() { } if (_flags >= Flag::EnableValidation) { - DestroyDebugReportCallback(_instance, msgCallback, nullptr); + //DestroyDebugReportCallback(_instance, msgCallback, nullptr); } vkDestroyInstance(_instance, nullptr); } @@ -89,16 +85,18 @@ void Context::create() { if(!tryCreate()) std::exit(1); } -VkBool32 messageCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, - uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData) { - - if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { - Error() << "[" << pLayerPrefix << "] Code" << msgCode << ":" << pMsg; - } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { - Warning() << "[" << pLayerPrefix << "] Code" << msgCode << ":" << pMsg; - } - - return false; +VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, + void* pUserData) +{ + Error() << pMessage; + return VK_FALSE; } bool Context::tryCreate() { @@ -108,9 +106,9 @@ bool Context::tryCreate() { appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "Vulkan Example"; appInfo.pEngineName = "Magnum"; - appInfo.apiVersion = UnsignedInt(_version); + appInfo.apiVersion = VK_API_VERSION_1_0; - std::vector enabledExtensions = { VK_KHR_SURFACE_EXTENSION_NAME, "VK_KHR_win32_surface" }; + std::vector enabledExtensions = {VK_KHR_SURFACE_EXTENSION_NAME, "VK_KHR_win32_surface"}; // Enable surface extensions depending on os // enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); @@ -120,11 +118,13 @@ bool Context::tryCreate() { instanceCreateInfo.pNext = nullptr; instanceCreateInfo.pApplicationInfo = &appInfo; if (_flags >= Flag::EnableValidation) { + Debug() << "Enabling Validation"; enabledExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); - instanceCreateInfo.enabledLayerCount = 1; + instanceCreateInfo.enabledLayerCount = layerCount; instanceCreateInfo.ppEnabledLayerNames = validationLayerNames; } + if (!enabledExtensions.empty()) { instanceCreateInfo.enabledExtensionCount = enabledExtensions.size(); instanceCreateInfo.ppEnabledExtensionNames = enabledExtensions.data(); @@ -140,21 +140,33 @@ bool Context::tryCreate() { /* setup debugging */ if (_flags >= Flag::EnableValidation) { - CreateDebugReportCallback = PFN_vkCreateDebugReportCallbackEXT(vkGetInstanceProcAddr(_instance, "vkCreateDebugReportCallbackEXT")); - DestroyDebugReportCallback = PFN_vkDestroyDebugReportCallbackEXT(vkGetInstanceProcAddr(_instance, "vkDestroyDebugReportCallbackEXT")); - dbgBreakCallback = PFN_vkDebugReportMessageEXT(vkGetInstanceProcAddr(_instance, "vkDebugReportMessageEXT")); - - VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = {}; - dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; - dbgCreateInfo.pfnCallback = PFN_vkDebugReportCallbackEXT(messageCallback); - dbgCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; - - VkResult err = CreateDebugReportCallback( - _instance, - &dbgCreateInfo, - nullptr, - &msgCallback); - assert(!err); + /* Load VK_EXT_debug_report entry points in debug builds */ + PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = + reinterpret_cast + (vkGetInstanceProcAddr(_instance, "vkCreateDebugReportCallbackEXT")); + PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT = + reinterpret_cast + (vkGetInstanceProcAddr(_instance, "vkDebugReportMessageEXT")); + PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = + reinterpret_cast + (vkGetInstanceProcAddr(_instance, "vkDestroyDebugReportCallbackEXT")); + + /* Setup callback creation information */ + VkDebugReportCallbackCreateInfoEXT callbackCreateInfo; + callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; + callbackCreateInfo.pNext = nullptr; + callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | + VK_DEBUG_REPORT_WARNING_BIT_EXT | + VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; + callbackCreateInfo.pfnCallback = &MyDebugReportCallback; + callbackCreateInfo.pUserData = nullptr; + + /* Register the callback */ + VkDebugReportCallbackEXT callback; + VkResult err = vkCreateDebugReportCallbackEXT(_instance, &callbackCreateInfo, nullptr, &callback); + if (err != VK_SUCCESS) { + Error() << "Could not setup Debug callback"; + } } return true; } diff --git a/src/Magnum/Vk/Device.cpp b/src/Magnum/Vk/Device.cpp new file mode 100644 index 000000000..4bea61d17 --- /dev/null +++ b/src/Magnum/Vk/Device.cpp @@ -0,0 +1,59 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Device.h" + +#include "Magnum/Vk/CommandPool.h" +#include "Magnum/Vk/Queue.h" + + +namespace Magnum { namespace Vk { + +Device::Device(PhysicalDevice& physicalDevice, VkDeviceQueueCreateInfo& requestedQueues): + _physicalDevice(physicalDevice) +{ + constexpr const char* enabledExtensions[]{VK_KHR_SWAPCHAIN_EXTENSION_NAME}; + constexpr const char* validationLayerNames[] = {"VK_LAYER_LUNARG_standard_validation"}; + + // TODO: Allow disabling validation layers + + VkDeviceCreateInfo deviceCreateInfo = { + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, + nullptr, + 0, /* flags */ + 1, &requestedQueues, + 1, validationLayerNames, + 1, enabledExtensions, + nullptr}; + + vkCreateDevice(physicalDevice.vkPhysicalDevice(), &deviceCreateInfo, nullptr, &_device); +} + +Device::~Device() { + vkDestroyDevice(_device, nullptr); +} + +}} diff --git a/src/Magnum/Vk/Device.h b/src/Magnum/Vk/Device.h new file mode 100644 index 000000000..1e8865fc2 --- /dev/null +++ b/src/Magnum/Vk/Device.h @@ -0,0 +1,106 @@ +#ifndef Magnum_Vk_Device_h +#define Magnum_Vk_Device_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::Device + */ + +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/Context.h" +#include "Magnum/Vk/PhysicalDevice.h" +#include "Magnum/Vk/visibility.h" + +#include "vulkan.h" + +namespace Magnum { namespace Vk { + +class CommandPool; +class Queue; + +class MAGNUM_VK_EXPORT Device { + public: + + /** @brief Copying is not allowed */ + Device(const Device&) = delete; + + /** @brief Move constructor */ + Device(Device&& other); + + Device(PhysicalDevice& physicalDevice, VkDeviceQueueCreateInfo& requestedQueues); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyDevice} + */ + ~Device(); + + /** @brief Copying is not allowed */ + Device& operator=(const Device&) = delete; + + /** @brief Move assignment is not allowed */ + Device& operator=(Device&&) = delete; + + /** + * @brief Return the underlying VkDevice handle + */ + VkDevice vkDevice() { + return _device; + } + + /** + * @return Reference to the PhysicalDevice this Device was created from + */ + PhysicalDevice& physicalDevice() { + return _physicalDevice; + } + + /** + * @brief Wait until the device is idle + * @return Reference to self (for method chaining) + */ + Device& waitIdle() { + VkResult err = vkDeviceWaitIdle(_device); + MAGNUM_VK_ASSERT_ERROR(err); + return *this; + } + + operator VkDevice() const { + return _device; + } + + private: + VkDevice _device; + PhysicalDevice& _physicalDevice; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/DeviceMemory.cpp b/src/Magnum/Vk/DeviceMemory.cpp new file mode 100644 index 000000000..9fcc47dc3 --- /dev/null +++ b/src/Magnum/Vk/DeviceMemory.cpp @@ -0,0 +1,36 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "DeviceMemory.h" + + +namespace Magnum { namespace Vk { + +DeviceMemory::~DeviceMemory() { + vkFreeMemory(_device, _deviceMemory, nullptr); +} + +}} diff --git a/src/Magnum/Vk/DeviceMemory.h b/src/Magnum/Vk/DeviceMemory.h new file mode 100644 index 000000000..b6ffd85ef --- /dev/null +++ b/src/Magnum/Vk/DeviceMemory.h @@ -0,0 +1,109 @@ +#ifndef Magnum_Vk_DeviceMemory_h +#define Magnum_Vk_DeviceMemory_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::DeviceMemory + */ + +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/visibility.h" + +#include "vulkan.h" + +namespace Magnum { namespace Vk { + +class MAGNUM_VK_EXPORT DeviceMemory { + public: + + DeviceMemory(Device& device, UnsignedLong size, UnsignedInt memoryTypeIndex): + _device{device} + { + _memAlloc = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + nullptr, + size, + memoryTypeIndex + }; + + VkResult err = vkAllocateMemory(_device, &_memAlloc, nullptr, &_deviceMemory); + MAGNUM_VK_ASSERT_ERROR(err); + } + + /** @brief Copying is not allowed */ + DeviceMemory(const DeviceMemory&) = delete; + + /** @brief Move constructor */ + DeviceMemory(DeviceMemory&& other); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyDeviceMemory} + */ + ~DeviceMemory(); + + /** @brief Copying is not allowed */ + DeviceMemory& operator=(const DeviceMemory&) = delete; + + /** @brief Move assignment is not allowed */ + DeviceMemory& operator=(DeviceMemory&&) = delete; + + operator VkDeviceMemory() const { + return _deviceMemory; + } + + Containers::Array map() { + return map(0, _memAlloc.allocationSize); + } + + Containers::Array map(UnsignedInt offset, UnsignedInt size) { + // TODO: Memory map flags (== 0) + void* data; + VkResult err = vkMapMemory(_device, _deviceMemory, offset, size, 0, &data); + MAGNUM_VK_ASSERT_ERROR(err); + + return Containers::Array(static_cast(data), size); + } + + DeviceMemory& unmap() { + vkUnmapMemory(_device, _deviceMemory); + return *this; + } + + private: + Device& _device; + VkDeviceMemory _deviceMemory; + VkMemoryAllocateInfo _memAlloc; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Framebuffer.cpp b/src/Magnum/Vk/Framebuffer.cpp new file mode 100644 index 000000000..85b8541dc --- /dev/null +++ b/src/Magnum/Vk/Framebuffer.cpp @@ -0,0 +1,36 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Framebuffer.h" + + +namespace Magnum { namespace Vk { + +Framebuffer::~Framebuffer() { + vkDestroyFramebuffer(_device, _framebuffer, nullptr); +} + +}} diff --git a/src/Magnum/Vk/Framebuffer.h b/src/Magnum/Vk/Framebuffer.h new file mode 100644 index 000000000..6105287f7 --- /dev/null +++ b/src/Magnum/Vk/Framebuffer.h @@ -0,0 +1,98 @@ +#ifndef Magnum_Vk_Framebuffer_h +#define Magnum_Vk_Framebuffer_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::Framebuffer + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/RenderPass.h" +#include "Magnum/Vk/ImageView.h" + +#include "vulkan.h" + +namespace Magnum { namespace Vk { + +class MAGNUM_VK_EXPORT Framebuffer { + public: + + Framebuffer(Device& device, RenderPass& renderPass, Vector2ui size, std::initializer_list& attachments): + _device{device} + { + std::vector vkAttachments; + vkAttachments.reserve(attachments.size()); + for (auto& imageView : attachments) { + vkAttachments.push_back(imageView); + } + + VkFramebufferCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.renderPass = renderPass; + createInfo.attachmentCount = attachments.size(); + createInfo.pAttachments = vkAttachments.data(); + createInfo.width = size.x(); + createInfo.height = size.y(); + createInfo.layers = 1; + + vkCreateFramebuffer(_device, &createInfo, nullptr, &_framebuffer); + } + + /** @brief Copying is not allowed */ + Framebuffer(const Framebuffer&) = delete; + + /** @brief Move constructor */ + Framebuffer(Framebuffer&& other); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyFramebuffer} + */ + ~Framebuffer(); + + /** @brief Copying is not allowed */ + Framebuffer& operator=(const Framebuffer&) = delete; + + /** @brief Move assignment is not allowed */ + Framebuffer& operator=(Framebuffer&&) = delete; + + operator VkFramebuffer() const { + return _framebuffer; + } + + private: + Device& _device; + VkFramebuffer _framebuffer; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Image.cpp b/src/Magnum/Vk/Image.cpp new file mode 100644 index 000000000..85ec33127 --- /dev/null +++ b/src/Magnum/Vk/Image.cpp @@ -0,0 +1,36 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Image.h" + + +namespace Magnum { namespace Vk { + +Image::~Image() { + vkDestroyImage(_device, _image, nullptr); +} + +}} diff --git a/src/Magnum/Vk/Image.h b/src/Magnum/Vk/Image.h new file mode 100644 index 000000000..33f0a9ba7 --- /dev/null +++ b/src/Magnum/Vk/Image.h @@ -0,0 +1,188 @@ +#ifndef Magnum_Vk_Image_h +#define Magnum_Vk_Image_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::Image + */ +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Math/Vector3.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/Math.h" +#include "Magnum/Vk/visibility.h" + +#include "vulkan.h" + +namespace Magnum { namespace Vk { + +class Image; + +enum class ImageUsageFlag: UnsignedInt { + TransferSrc = VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + TransferDst = VK_IMAGE_USAGE_TRANSFER_DST_BIT, + Sampled = VK_IMAGE_USAGE_SAMPLED_BIT, + Storage = VK_IMAGE_USAGE_STORAGE_BIT, + ColorAttachment = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + StencilAttachment = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + TransientAttachment = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, +}; + +typedef Corrade::Containers::EnumSet ImageUsageFlags; + +CORRADE_ENUMSET_OPERATORS(ImageUsageFlags) + +enum class Access: UnsignedInt { + IndirectCommandRead = VK_ACCESS_INDIRECT_COMMAND_READ_BIT, + IndexRead = VK_ACCESS_INDEX_READ_BIT, + VertexAttributeRead = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + UniformRead = VK_ACCESS_UNIFORM_READ_BIT, + InputAttachmentRead = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + ShaderRead = VK_ACCESS_SHADER_READ_BIT, + ShaderWrite = VK_ACCESS_SHADER_WRITE_BIT, + ColorAttachmentRead = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + ColorAttachmentWrite = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + DepthStencilAttachmentRead = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + DepthStencilAttachmentWrite = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + TransferRead = VK_ACCESS_TRANSFER_READ_BIT, + TransferWrite = VK_ACCESS_TRANSFER_WRITE_BIT, + HostRead = VK_ACCESS_HOST_READ_BIT, + HostWrite = VK_ACCESS_HOST_WRITE_BIT, + MemoryRead = VK_ACCESS_MEMORY_READ_BIT, + MemoryWrite = VK_ACCESS_MEMORY_WRITE_BIT, +}; + +typedef Containers::EnumSet AccessFlags; + +CORRADE_ENUMSET_OPERATORS(AccessFlags) + +enum class ImageLayout: UnsignedInt { + Undefined = VK_IMAGE_LAYOUT_UNDEFINED, + General = VK_IMAGE_LAYOUT_GENERAL, + ColorAttachmentOptimal = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + DepthStencilAttachmentOptimal = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + DepthStencilReadOnlyOptimal = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, + ShaderReadOnlyOptimal = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + TransferSrcOptimal = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + TransferDstOptimal = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + Preinitialized = VK_IMAGE_LAYOUT_PREINITIALIZED, + PresentSrc = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, +}; + +class MAGNUM_VK_EXPORT Image { + public: + + Image(Device& device, VkImage vkImage): + _device{device}, + _image{vkImage} + {} + + Image(Device& device, Vector3ui extent, VkFormat format, ImageUsageFlags usage): _device{device} { + VkImageCreateInfo image = {}; + image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image.flags = 0; + image.pNext = nullptr; + image.imageType = VK_IMAGE_TYPE_2D; + image.format = format; + image.extent = VkExtent3D(extent); + image.samples = VK_SAMPLE_COUNT_1_BIT; + image.mipLevels = 1; + image.arrayLayers = 1; + image.tiling = VK_IMAGE_TILING_OPTIMAL; + image.usage = UnsignedInt(usage); + + VkResult err = vkCreateImage(_device, &image, nullptr, &_image); + MAGNUM_VK_ASSERT_ERROR(err); + } + + /** @brief Copying is not allowed */ + Image(const Image&) = delete; + + /** @brief Move constructor */ + Image(Image&& other); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyImage} + */ + ~Image(); + + /** @brief Copying is not allowed */ + Image& operator=(const Image&) = delete; + + /** @brief Move assignment is not allowed */ + Image& operator=(Image&&) = delete; + + operator VkImage() const { + return _image; + } + + VkMemoryRequirements getMemoryRequirements() { + VkMemoryRequirements memReqs; + vkGetImageMemoryRequirements(_device, _image, &memReqs); + + return memReqs; + } + + private: + Device& _device; + VkImage _image; +}; + +struct ImageMemoryBarrier { + + ImageMemoryBarrier(const Image& image, ImageLayout src, ImageLayout dst, + VkImageSubresourceRange range, + AccessFlags srcAccessMask = {}, + AccessFlags destAccessMask = {}): + _imageMemoryBarrier{ + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + nullptr, + VkAccessFlags(srcAccessMask), + VkAccessFlags(destAccessMask), + VkImageLayout(src), + VkImageLayout(dst), + VK_QUEUE_FAMILY_IGNORED, + VK_QUEUE_FAMILY_IGNORED, + image, + range + } + {} + + operator VkImageMemoryBarrier() const { + return _imageMemoryBarrier; + } + +private: + VkImageMemoryBarrier _imageMemoryBarrier; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/ImageView.cpp b/src/Magnum/Vk/ImageView.cpp new file mode 100644 index 000000000..cd2bbb767 --- /dev/null +++ b/src/Magnum/Vk/ImageView.cpp @@ -0,0 +1,36 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "ImageView.h" + + +namespace Magnum { namespace Vk { + +ImageView::~ImageView() { + vkDestroyImageView(_device, _imageView, nullptr); +} + +}} diff --git a/src/Magnum/Vk/ImageView.h b/src/Magnum/Vk/ImageView.h new file mode 100644 index 000000000..50cf55ab5 --- /dev/null +++ b/src/Magnum/Vk/ImageView.h @@ -0,0 +1,110 @@ +#ifndef Magnum_Vk_ImageView_h +#define Magnum_Vk_ImageView_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::ImageView + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Image.h" + +#include "vulkan.h" + +namespace Magnum { namespace Vk { + +enum class ImageAspect: UnsignedInt { + Color = VK_IMAGE_ASPECT_COLOR_BIT, + Depth = VK_IMAGE_ASPECT_DEPTH_BIT, + Stencil = VK_IMAGE_ASPECT_STENCIL_BIT, + Metadata = VK_IMAGE_ASPECT_METADATA_BIT, +}; + +typedef Containers::EnumSet ImageAspects; + +CORRADE_ENUMSET_OPERATORS(ImageAspects) + +class MAGNUM_VK_EXPORT ImageView { + public: + + ImageView(Device& device, Image& image, VkFormat format, + VkImageViewType type, ImageAspects aspects, + VkComponentMapping components = {}): + _device{device} + { + VkImageViewCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.flags = 0; + createInfo.viewType = type; + createInfo.format = format; + createInfo.subresourceRange = { + VkImageAspectFlags(aspects), + 0, /* base mip level */ + 1, /* layer count */ + 0, /* base array layer */ + 1, /* layer count */ + }; + createInfo.image = image; + createInfo.components = components; + + VkResult err = vkCreateImageView(_device, &createInfo, nullptr, &_imageView); + MAGNUM_VK_ASSERT_ERROR(err); + } + + /** @brief Copying is not allowed */ + ImageView(const ImageView&) = delete; + + /** @brief Move constructor */ + ImageView(ImageView&& other); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyImageView} + */ + ~ImageView(); + + /** @brief Copying is not allowed */ + ImageView& operator=(const ImageView&) = delete; + + /** @brief Move assignment is not allowed */ + ImageView& operator=(ImageView&&) = delete; + + operator VkImageView() const { + return _imageView; + } + + private: + Device& _device; + VkImageView _imageView; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Math.h b/src/Magnum/Vk/Math.h new file mode 100644 index 000000000..da1443ece --- /dev/null +++ b/src/Magnum/Vk/Math.h @@ -0,0 +1,53 @@ +#ifndef Magnum_Vk_Math_h +#define Magnum_Vk_Math_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief + */ + +#include +#include +#include +#include "vulkan.h" + +namespace Magnum { namespace Math { namespace Implementation { + +/* VkExtent3D */ +template<> struct VectorConverter<3, UnsignedInt, VkExtent3D> { + static Vector<3, UnsignedInt> from(const VkExtent3D& other) { + return {other.width, other.height, other.depth}; + } + + static VkExtent3D to(const Vector<3, UnsignedInt>& other) { + return {other[0], other[1], other[2]}; + } +}; + +}}} + +#endif diff --git a/src/Magnum/Vk/PhysicalDevice.cpp b/src/Magnum/Vk/PhysicalDevice.cpp new file mode 100644 index 000000000..451a19351 --- /dev/null +++ b/src/Magnum/Vk/PhysicalDevice.cpp @@ -0,0 +1,98 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "PhysicalDevice.h" + +#include + +#include +#include + + +namespace Magnum { namespace Vk { + +PhysicalDevice::~PhysicalDevice() { +} + +VkFormat PhysicalDevice::getSupportedDepthFormat() { + // Since all depth formats may be optional, we need to find a suitable depth format to use + // Start with the highest precision packed format + std::vector depthFormats = { + VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_D32_SFLOAT, + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_D16_UNORM_S8_UINT, + VK_FORMAT_D16_UNORM + }; + + VkFormatProperties formatProps; + for(auto& format : depthFormats) { + vkGetPhysicalDeviceFormatProperties(_physicalDevice, format, &formatProps); + // Format must support depth stencil attachment for optimal tiling + if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { + return format; + } + } + + return VK_FORMAT_UNDEFINED; +} + +UnsignedInt PhysicalDevice::getQueueFamilyIndex(QueueFamily family) { + // Find a queue that supports graphics + UnsignedInt queueCount; + vkGetPhysicalDeviceQueueFamilyProperties(_physicalDevice, &queueCount, nullptr); + + if(queueCount <= 0) { // TODO I belive there allways is at least one queue of a certain specified type, lookup in spec + Error() << "Physical Device does not provide queues"; // TODO + } + + std::vector queueProps; // TODO Use NoInit Containers::Array + queueProps.resize(queueCount); + vkGetPhysicalDeviceQueueFamilyProperties(_physicalDevice, &queueCount, queueProps.data()); + + for(UnsignedInt i = 0; i < queueCount; ++i) { + if(queueProps[i].queueFlags & VkQueueFlags(family)) { + return i; + } + } + + CORRADE_ASSERT(false, "The device does not support the given queue family.", -1); // TODO +} + +UnsignedInt PhysicalDevice::getMemoryType(UnsignedInt typeBits, VkFlags properties) { + for (uint32_t i = 0; i < 32; i++) { + if((typeBits & 1) != 0) { + if((_deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { + return i; + } + } + typeBits >>= 1; + } + + CORRADE_ASSERT(false, "Physical devices does not support memory with given properties.", -1); // TODO +} + +}} diff --git a/src/Magnum/Vk/PhysicalDevice.h b/src/Magnum/Vk/PhysicalDevice.h new file mode 100644 index 000000000..fcc283f82 --- /dev/null +++ b/src/Magnum/Vk/PhysicalDevice.h @@ -0,0 +1,107 @@ +#ifndef Magnum_Vk_PhysicalDevice_h +#define Magnum_Vk_PhysicalDevice_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::PhysicalDevice + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/visibility.h" + +#include "vulkan.h" + + +namespace Magnum { namespace Vk { + +enum class QueueFamily: UnsignedInt { + Graphics = VK_QUEUE_GRAPHICS_BIT, + Compute = VK_QUEUE_COMPUTE_BIT, + Transfer = VK_QUEUE_TRANSFER_BIT, +}; + +enum class QueueFlag: UnsignedInt { + SparseBinding = VK_QUEUE_SPARSE_BINDING_BIT, +}; + + +class MAGNUM_VK_EXPORT PhysicalDevice { + public: + + /** @brief Copying is not allowed */ + PhysicalDevice(const PhysicalDevice&) = delete; + + /** @brief Move constructor */ + PhysicalDevice(PhysicalDevice&& other); + + /** + * @brief Construct from VkPhysicalDevice + */ + PhysicalDevice(const VkPhysicalDevice& device): + _physicalDevice(device) + { + // Gather physical device memory properties + vkGetPhysicalDeviceMemoryProperties(_physicalDevice, &_deviceMemoryProperties); + } + + /** @brief Destructor */ + ~PhysicalDevice(); + + /** @brief Copying is not allowed */ + PhysicalDevice& operator=(const PhysicalDevice&) = delete; + + /** @brief Move assignment is not allowed */ + PhysicalDevice& operator=(PhysicalDevice&&) = delete; + + /** + * @brief Get the underlying VkPhysicalDevice handle + */ + VkPhysicalDevice vkPhysicalDevice() { + return _physicalDevice; + } + + VkFormat getSupportedDepthFormat(); + + UnsignedInt getQueueFamilyIndex(QueueFamily family); + + VkPhysicalDeviceProperties getProperties() { + VkPhysicalDeviceProperties deviceProperties; + vkGetPhysicalDeviceProperties(_physicalDevice, &deviceProperties); + + return deviceProperties; + } + + UnsignedInt getMemoryType(UnsignedInt typeBits, VkFlags properties); + + private: + VkPhysicalDevice _physicalDevice; + VkPhysicalDeviceMemoryProperties _deviceMemoryProperties; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Pipeline.cpp b/src/Magnum/Vk/Pipeline.cpp new file mode 100644 index 000000000..df73db689 --- /dev/null +++ b/src/Magnum/Vk/Pipeline.cpp @@ -0,0 +1,100 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Pipeline.h" + + +namespace Magnum { namespace Vk { + +Pipeline::~Pipeline() { + vkDestroyPipeline(_device, _pipeline, nullptr); + vkDestroyPipelineLayout(_device, _layout, nullptr); + vkDestroyPipelineCache(_device, _cache, nullptr); +} + +std::unique_ptr GraphicsPipelineFactory::create() { + VkPipeline pipeline; + VkPipelineCache cache; + VkPipelineLayout layout; + + /* create pipeline layout */ + VkPipelineLayoutCreateInfo plInfo = { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + nullptr, + 0, + _setLayouts.size(), + _setLayouts.data(), + _pushConstantRanges.size(), + _pushConstantRanges.data() + }; + + VkResult err = vkCreatePipelineLayout(_device, &plInfo, nullptr, &layout); + MAGNUM_VK_ASSERT_ERROR(err); + + /* create pipeline cache */ + VkPipelineCacheCreateInfo pipelineCacheCreateInfo = { + VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, + nullptr, + 0, + 0, /* initial data size */ + nullptr /* initial data */ + }; + + err = vkCreatePipelineCache(_device, &pipelineCacheCreateInfo, nullptr, &cache); + MAGNUM_VK_ASSERT_ERROR(err); + + /* create pipeline itself */ + VkPipelineDynamicStateCreateInfo dynamicState = { + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + nullptr, + 0, + _dynamicStates.size(), + reinterpret_cast(_dynamicStates.data()) + }; + + VkGraphicsPipelineCreateInfo pipelineInfo = {}; + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineInfo.pNext = nullptr; + pipelineInfo.layout = layout; + pipelineInfo.renderPass = *_renderPass; + pipelineInfo.pInputAssemblyState = &_inputAssemblyState; + pipelineInfo.pVertexInputState = &_vertexInputState; + pipelineInfo.pRasterizationState = &_rasterizationState; + pipelineInfo.pColorBlendState = &_colorBlendState; + pipelineInfo.pMultisampleState = &_multisampleState; + pipelineInfo.pViewportState = &_viewportState; + pipelineInfo.pDepthStencilState = &_depthStencilState; + pipelineInfo.stageCount = _shaderStages.size(); + pipelineInfo.pStages = _shaderStages.data(); + pipelineInfo.pDynamicState = &dynamicState; + + err = vkCreateGraphicsPipelines(_device, cache, 1, &pipelineInfo, nullptr, &pipeline); + MAGNUM_VK_ASSERT_ERROR(err); + + return std::unique_ptr{new Pipeline{_device, pipeline, cache, layout}}; +} + +}} diff --git a/src/Magnum/Vk/Pipeline.h b/src/Magnum/Vk/Pipeline.h new file mode 100644 index 000000000..dbc51054e --- /dev/null +++ b/src/Magnum/Vk/Pipeline.h @@ -0,0 +1,364 @@ +#ifndef Magnum_Vk_GraphicsPipeline_h +#define Magnum_Vk_GraphicsPipeline_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::GraphicsPipeline + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/visibility.h" + +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/RenderPass.h" +#include "Magnum/Vk/Shader.h" + +#include "Magnum/Math/Vector3.h" // TEMPORARY!!! + +#include + +#include "vulkan.h" + +namespace Magnum { namespace Vk { + +enum class ShaderStage: UnsignedInt { + Vertex = VK_SHADER_STAGE_VERTEX_BIT, + TesslationControl = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, + TesslationEvaluation = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, + Geometry = VK_SHADER_STAGE_GEOMETRY_BIT, + Fragment = VK_SHADER_STAGE_FRAGMENT_BIT, + Compute = VK_SHADER_STAGE_COMPUTE_BIT, + AllGraphics = VK_SHADER_STAGE_ALL_GRAPHICS, + All = VK_SHADER_STAGE_ALL, +}; + +enum class DynamicState: UnsignedInt { + Viewport = VK_DYNAMIC_STATE_VIEWPORT, + Scissor = VK_DYNAMIC_STATE_SCISSOR, + LineWidth = VK_DYNAMIC_STATE_LINE_WIDTH, + DepthBias = VK_DYNAMIC_STATE_DEPTH_BIAS, + BlendConstant = VK_DYNAMIC_STATE_BLEND_CONSTANTS, + DepthBounds = VK_DYNAMIC_STATE_DEPTH_BOUNDS, + CompareMask = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, + WriteMask = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, + StencilReference = VK_DYNAMIC_STATE_STENCIL_REFERENCE, +}; + +enum class Topology: UnsignedInt { + PointList = VK_PRIMITIVE_TOPOLOGY_POINT_LIST, + LineList = VK_PRIMITIVE_TOPOLOGY_LINE_LIST, + LineStrip = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, + TriangleList = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + TriangleStrip = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, + TriangleFan = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, + LineListWithAdjacency = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, + LineStripWithAdjacency = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, + TriangleListWithAdjacency = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, + TriangleStripWithAdjacency = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, + PatchList = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, +}; + +enum class PipelineStage: UnsignedInt { + TopOfThePipe = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + DrawIndirect = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, + VertexInput = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + VertexShader = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + TesslationControlShader = VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, + TesslationEvaluationShader = VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, + GeometryShader = VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, + FragmentShader = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + EarlyFragmentTest = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + LateFragmentTests = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + ColorAttachmentOutput = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + ComputeShader = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + StageTransfer = VK_PIPELINE_STAGE_TRANSFER_BIT, + BottomOfPipe = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + Host = VK_PIPELINE_STAGE_HOST_BIT, + AllGraphics = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + AllCommands = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT +}; + +typedef Containers::EnumSet PipelineStageFlags; + +enum class BindPoint: UnsignedInt { + Graphics = VK_PIPELINE_BIND_POINT_GRAPHICS, + Compute = VK_PIPELINE_BIND_POINT_COMPUTE, +}; + +class MAGNUM_VK_EXPORT Pipeline { + public: + Pipeline(Device& device, VkPipeline pipeline, VkPipelineCache cache, VkPipelineLayout layout): + _device{device}, + _pipeline{pipeline}, + _cache{cache}, + _layout{layout} + {} + + /** @brief Copying is not allowed */ + Pipeline(const Pipeline&) = delete; + + /** @brief Move constructor */ + Pipeline(Pipeline&& other); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyPipeline} + */ + ~Pipeline(); + + /** @brief Copying is not allowed */ + Pipeline& operator=(const Pipeline&) = delete; + + /** @brief Move assignment is not allowed */ + Pipeline& operator=(Pipeline&&) = delete; + + operator VkPipeline() const { + return _pipeline; + } + + VkPipelineLayout layout() { + return _layout; + } + + auto bind(BindPoint bindPoint, std::initializer_list descriptorSets) { + const VkPipelineLayout pl = _layout; + return [bindPoint, &descriptorSets, pl](VkCommandBuffer cmdBuffer){ + vkCmdBindDescriptorSets(cmdBuffer, + VkPipelineBindPoint(bindPoint), + pl, 0, + descriptorSets.size(), std::vector(descriptorSets).data(), + 0, nullptr); + }; + } + + private: + Device& _device; + VkPipeline _pipeline; + VkPipelineCache _cache; + VkPipelineLayout _layout; +}; + +class MAGNUM_VK_EXPORT GraphicsPipelineFactory { + public: + + GraphicsPipelineFactory(Device& device): + _device{device} { + + _inputAssemblyState = { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + nullptr, + 0, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + 0 /* primitive restart enable */ + }; + + _multisampleState = { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, nullptr, 0, + VK_SAMPLE_COUNT_1_BIT, + VK_FALSE, + 0.0f, + nullptr, + VK_FALSE, + VK_FALSE + }; + + _depthStencilState = { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + nullptr, + 0, + VK_TRUE, /* depth test enable */ + VK_TRUE, /* depth write enable */ + VK_COMPARE_OP_LESS_OR_EQUAL, /* depth compare op */ + VK_FALSE, /* depth bounds test enable */ + VK_FALSE, /* stencil test enable */ + VkStencilOpState{VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER, 0, 0, 0}, /* front */ + VkStencilOpState{VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER, 0, 0, 0}, /* back */ + 0.0f, 0.0f /* depth bounds */ + }; + + _rasterizationState = { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + nullptr, + 0, + VK_FALSE, /* depth clamp enable */ + VK_FALSE, /* rasterizer discard enable */ + VK_POLYGON_MODE_FILL, /* poygon mode */ + VK_CULL_MODE_NONE, /* cull mode */ + VK_FRONT_FACE_COUNTER_CLOCKWISE, /* front face */ + VK_FALSE, /* depth bias enable */ + 0.0f, 0.0f, 0.0f, 0.0f + }; + + VkPipelineColorBlendAttachmentState blendAttachmentState = { + VK_FALSE, + VK_BLEND_FACTOR_ZERO, + VK_BLEND_FACTOR_ZERO, + VK_BLEND_OP_ADD, + VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, + VK_BLEND_OP_ADD, + 0xf + }; + _blendAttachments.push_back(blendAttachmentState); + + _colorBlendState = { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + nullptr, + 0, + VK_FALSE, + VK_LOGIC_OP_CLEAR, + _blendAttachments.size(), + _blendAttachments.data(), + {0.0f, 0.0f, 0.0f, 0.0f} + }; + + _viewportState = { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + nullptr, + 0, + 1, + nullptr, // TODO currently expecting dynamic state here... + 1, + nullptr + }; + + VkVertexInputBindingDescription bindingDesc; + bindingDesc.binding = 0; + bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + bindingDesc.stride = sizeof(Vector3)*2; + + _vertexInputBindings.push_back(bindingDesc); + + VkVertexInputAttributeDescription attributeDesc[2]; + attributeDesc[0].binding = 0; + attributeDesc[0].location = 0; + attributeDesc[0].format = VK_FORMAT_R32G32B32_SFLOAT; + attributeDesc[0].offset = 0; + + _vertexInputAttrbutes.push_back(attributeDesc[0]); + + // Color + attributeDesc[1].binding = 0; + attributeDesc[1].location = 1; + attributeDesc[1].format = VK_FORMAT_R32G32B32_SFLOAT; + attributeDesc[1].offset = sizeof(Vector3); + + _vertexInputAttrbutes.push_back(attributeDesc[1]); + + _vertexInputState = { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + nullptr, + 0, + _vertexInputBindings.size(), + _vertexInputBindings.data(), + _vertexInputAttrbutes.size(), + _vertexInputAttrbutes.data(), + }; + } + + /** @brief Copying is not allowed */ + GraphicsPipelineFactory(const GraphicsPipelineFactory&) = delete; + + /** @brief Move constructor */ + GraphicsPipelineFactory(GraphicsPipelineFactory&& other); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyPipeline} + */ + ~GraphicsPipelineFactory() { + } + + /** @brief Copying is not allowed */ + GraphicsPipelineFactory& operator=(const GraphicsPipelineFactory&) = delete; + + /** @brief Move assignment is not allowed */ + GraphicsPipelineFactory& operator=(GraphicsPipelineFactory&&) = delete; + + GraphicsPipelineFactory& addShader(ShaderStage stage, Shader& shader) { + VkPipelineShaderStageCreateInfo shaderStage = { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + nullptr, + 0, + VkShaderStageFlagBits(stage), + shader.vkShaderModule(), + "main", + nullptr // TODO: SpecializationInfo? + }; + _shaderStages.push_back(shaderStage); + return *this; + } + + std::unique_ptr create(); + + GraphicsPipelineFactory& setRenderPass(RenderPass& renderPass) { + _renderPass = &renderPass; + return *this; + } + + GraphicsPipelineFactory& setTopology(Topology topology) { + _inputAssemblyState.topology = VkPrimitiveTopology(topology); + return *this; + } + + GraphicsPipelineFactory& setDynamicStates(std::initializer_list states) { + _dynamicStates = std::vector(states); + return *this; + } + + GraphicsPipelineFactory& addDescriptorSetLayout(const VkDescriptorSetLayout& layout) { + _setLayouts.push_back(layout); + return *this; + } + + private: + Device& _device; + VkGraphicsPipelineCreateInfo _createInfo; + + VkPipelineInputAssemblyStateCreateInfo _inputAssemblyState; + VkPipelineVertexInputStateCreateInfo _vertexInputState; + VkPipelineRasterizationStateCreateInfo _rasterizationState; + VkPipelineColorBlendStateCreateInfo _colorBlendState; + VkPipelineMultisampleStateCreateInfo _multisampleState; + VkPipelineViewportStateCreateInfo _viewportState; + VkPipelineDepthStencilStateCreateInfo _depthStencilState; + + std::vector _dynamicStates; + std::vector _blendAttachments; + std::vector _setLayouts; + std::vector _vertexInputBindings; + std::vector _vertexInputAttrbutes; + std::vector _pushConstantRanges; + + RenderPass* _renderPass; + std::vector _shaderStages; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Queue.cpp b/src/Magnum/Vk/Queue.cpp new file mode 100644 index 000000000..ac5e34d36 --- /dev/null +++ b/src/Magnum/Vk/Queue.cpp @@ -0,0 +1,83 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Queue.h" + + +namespace Magnum { namespace Vk { + +Queue::~Queue() { +} + +Queue& Queue::submit(const CommandBuffer& cmdBuffer) { + const VkCommandBuffer cb = cmdBuffer; + + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &cb; + + VkResult err = vkQueueSubmit(_queue, 1, &submitInfo, VK_NULL_HANDLE); + MAGNUM_VK_ASSERT_ERROR(err); + + return *this; +} + +Queue& Queue::submit(const CommandBuffer& cmdBuffer, + std::vector> waitSemaphores, + std::vector> signalSemaphores) { + const VkCommandBuffer cb = cmdBuffer; + + VkPipelineStageFlags pipelineDstStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; // TODO: Expose + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pWaitDstStageMask = &pipelineDstStage; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &cb; + + std::vector waitSems; + waitSems.reserve(waitSemaphores.size()); + for(Semaphore& sem : waitSemaphores) { + waitSems.push_back(sem.vkSemaphore()); + } + + std::vector sigSems; + sigSems.reserve(waitSemaphores.size()); + for(Semaphore& sem : signalSemaphores) { + sigSems.push_back(sem.vkSemaphore()); + } + submitInfo.waitSemaphoreCount = waitSemaphores.size(); + submitInfo.pWaitSemaphores = waitSems.data(); + submitInfo.signalSemaphoreCount = signalSemaphores.size(); + submitInfo.pSignalSemaphores = sigSems.data(); + + VkResult err = vkQueueSubmit(_queue, 1, &submitInfo, VK_NULL_HANDLE); + MAGNUM_VK_ASSERT_ERROR(err); + + return *this; +} + +}} diff --git a/src/Magnum/Vk/Queue.h b/src/Magnum/Vk/Queue.h new file mode 100644 index 000000000..c7f156394 --- /dev/null +++ b/src/Magnum/Vk/Queue.h @@ -0,0 +1,90 @@ +#ifndef Magnum_Vk_Queue_h +#define Magnum_Vk_Queue_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::Queue + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/CommandBuffer.h" +#include "Magnum/Vk/Context.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/Semaphore.h" +#include "Magnum/Vk/visibility.h" + + +namespace Magnum { namespace Vk { + +class MAGNUM_VK_EXPORT Queue { + public: + + /** @brief Copying is not allowed */ + Queue(const Context&) = delete; + + /** @brief Move constructor */ + Queue(Queue&& other); + + Queue(Device& device, UnsignedInt familyIndex, UnsignedInt queueIndex): _device{device} { + vkGetDeviceQueue(_device, familyIndex, queueIndex, &_queue); + } + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyQueue} + */ + ~Queue(); + + /** @brief Copying is not allowed */ + Queue& operator=(const Queue&) = delete; + + /** @brief Move assignment is not allowed */ + Queue& operator=(Queue&&) = delete; + + VkQueue vkQueue() { + return _queue; + } + + Queue& waitIdle() { + VkResult err = vkQueueWaitIdle(_queue); + MAGNUM_VK_ASSERT_ERROR(err); + + return *this; + } + + Queue& submit(const CommandBuffer& cmdBuffer); + Queue& submit(const CommandBuffer& cmdBuffer, std::vector> waitSemaphores, std::vector> signalSemaphores); + + private: + VkQueue _queue; + Device& _device; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/RenderPass.cpp b/src/Magnum/Vk/RenderPass.cpp new file mode 100644 index 000000000..acb84fb78 --- /dev/null +++ b/src/Magnum/Vk/RenderPass.cpp @@ -0,0 +1,37 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "RenderPass.h" + + +namespace Magnum { namespace Vk { + +RenderPass::~RenderPass() { + if (_device != nullptr) + vkDestroyRenderPass(*_device, _renderPass, nullptr); +} + +}} diff --git a/src/Magnum/Vk/RenderPass.h b/src/Magnum/Vk/RenderPass.h new file mode 100644 index 000000000..d9e2257bf --- /dev/null +++ b/src/Magnum/Vk/RenderPass.h @@ -0,0 +1,139 @@ +#ifndef Magnum_Vk_RenderPass_h +#define Magnum_Vk_RenderPass_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::RenderPass + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/visibility.h" + +#include "vulkan.h" + +namespace Magnum { namespace Vk { + +class MAGNUM_VK_EXPORT RenderPass { + public: + + RenderPass(NoCreateT) noexcept: _device{nullptr} { + } + + RenderPass(Device& device, VkFormat depthFormat): _device{&device} { + VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; + + VkAttachmentDescription attachments[2]; + attachments[0].format = VK_FORMAT_B8G8R8A8_UNORM; + attachments[0].samples = sampleCount; + attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + attachments[1].format = depthFormat; + attachments[1].samples = sampleCount; + attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentReference colorReference = {}; + colorReference.attachment = 0; + colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depthReference = {}; + depthReference.attachment = 1; + depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.flags = 0; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorReference; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = &depthReference; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkRenderPassCreateInfo renderPassInfo = {}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassInfo.pNext = nullptr; + renderPassInfo.attachmentCount = 2; + renderPassInfo.pAttachments = attachments; + renderPassInfo.subpassCount = 1; + renderPassInfo.pSubpasses = &subpass; + renderPassInfo.dependencyCount = 0; + renderPassInfo.pDependencies = nullptr; + + VkResult err = vkCreateRenderPass(*_device, &renderPassInfo, nullptr, &_renderPass); + MAGNUM_VK_ASSERT_ERROR(err); + } + + /** @brief Copying is not allowed */ + RenderPass(const RenderPass&) = delete; + + /** @brief Move constructor */ + RenderPass(RenderPass&& other): _device{other._device}, _renderPass{other._renderPass}{ + other._renderPass = VK_NULL_HANDLE; + } + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyRenderPass} + */ + ~RenderPass(); + + /** @brief Copying is not allowed */ + RenderPass& operator=(const RenderPass&) = delete; + + RenderPass& operator=(RenderPass&& sem) noexcept { + std::swap(_renderPass, sem._renderPass); + std::swap(_device, sem._device); + + return *this; + } + + operator VkRenderPass() const { + return _renderPass; + } + + private: + Device* _device; + VkRenderPass _renderPass; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Semaphore.cpp b/src/Magnum/Vk/Semaphore.cpp new file mode 100644 index 000000000..9c2b75fe3 --- /dev/null +++ b/src/Magnum/Vk/Semaphore.cpp @@ -0,0 +1,34 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Semaphore.h" + + +namespace Magnum { namespace Vk { + +Semaphore::Semaphore(NoCreateT) noexcept: _semaphore(VK_NULL_HANDLE), _device{nullptr} {} + +}} diff --git a/src/Magnum/Vk/Semaphore.h b/src/Magnum/Vk/Semaphore.h new file mode 100644 index 000000000..e8c5f2914 --- /dev/null +++ b/src/Magnum/Vk/Semaphore.h @@ -0,0 +1,94 @@ +#ifndef Magnum_Vk_Semaphore_h +#define Magnum_Vk_Semaphore_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::Semaphore + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/Device.h" + + +namespace Magnum { namespace Vk { + +class MAGNUM_VK_EXPORT Semaphore { + public: + + explicit Semaphore(NoCreateT) noexcept; + + /** @brief Constructor */ + explicit Semaphore(Device& device): + _semaphore(VK_NULL_HANDLE), + _device(&device) + { + constexpr VkSemaphoreCreateInfo semaphoreCreateInfo{VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, 0}; + VkResult err = vkCreateSemaphore(_device->vkDevice(), &semaphoreCreateInfo, nullptr, &_semaphore); + MAGNUM_VK_ASSERT_ERROR(err); + } + + /** + * @brief Destructor + * + * @see @fn_vk{DestroySemaphore} + */ + ~Semaphore() { + /* NoCreate constructor initializes _device with nullptr */ + if (_device != nullptr) { + vkDestroySemaphore(_device->vkDevice(), _semaphore, nullptr); + } + } + + /** @brief Copying is not allowed */ + Semaphore(const Semaphore& sem) = delete; + + /** @brief Move assignment */ + Semaphore& operator=(Semaphore&& sem) noexcept { + std::swap(_semaphore, sem._semaphore); + std::swap(_device, sem._device); + + return *this; + } + + /** @brief Move constructor */ + Semaphore(Semaphore&& sem): _semaphore{sem.vkSemaphore()}, _device{sem._device} { + sem._semaphore = VK_NULL_HANDLE; + } + + /** @brief Get the underlying VkSemaphore handle */ + VkSemaphore& vkSemaphore() { + return _semaphore; + } + + private: + VkSemaphore _semaphore; + Device* _device; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Shader.cpp b/src/Magnum/Vk/Shader.cpp new file mode 100644 index 000000000..51599fcef --- /dev/null +++ b/src/Magnum/Vk/Shader.cpp @@ -0,0 +1,36 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Shader.h" + + +namespace Magnum { namespace Vk { + +Shader::~Shader() { + vkDestroyShaderModule(_device, _shaderModule, nullptr); +} + +}} diff --git a/src/Magnum/Vk/Shader.h b/src/Magnum/Vk/Shader.h new file mode 100644 index 000000000..1b2e72708 --- /dev/null +++ b/src/Magnum/Vk/Shader.h @@ -0,0 +1,88 @@ +#ifndef Magnum_Vk_Shader_h +#define Magnum_Vk_Shader_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::Shader + */ + +#include +#include "Magnum/Magnum.h" +#include "Magnum/Vk/visibility.h" + +#include "Magnum/Vk/Device.h" + +#include + +namespace Magnum { namespace Vk { + +class MAGNUM_VK_EXPORT Shader { + public: + + Shader(Device& device, const Containers::Array& shaderCode): _device{device} { + VkShaderModuleCreateInfo moduleCreateInfo; + moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + moduleCreateInfo.pNext = nullptr; + moduleCreateInfo.codeSize = shaderCode.size(); + moduleCreateInfo.pCode = reinterpret_cast(shaderCode.data()); + moduleCreateInfo.flags = 0; + + const VkResult err = vkCreateShaderModule(device.vkDevice(), &moduleCreateInfo, nullptr, &_shaderModule); + MAGNUM_VK_ASSERT_ERROR(err); + } + + /** @brief Copying is not allowed */ + Shader(const Shader&) = delete; + + /** @brief Move constructor */ + Shader(Shader&& other); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroyShader} + */ + ~Shader(); + + /** @brief Copying is not allowed */ + Shader& operator=(const Shader&) = delete; + + /** @brief Move assignment is not allowed */ + Shader& operator=(Shader&&) = delete; + + VkShaderModule vkShaderModule() { + return _shaderModule; + } + + private: + VkShaderModule _shaderModule; + Device& _device; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Swapchain.cpp b/src/Magnum/Vk/Swapchain.cpp new file mode 100644 index 000000000..12e56d8b1 --- /dev/null +++ b/src/Magnum/Vk/Swapchain.cpp @@ -0,0 +1,316 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Swapchain.h" + +#include "Magnum/Vk/Queue.h" + +#include "Magnum/Vk/ImageView.h" + +namespace Magnum { namespace Vk { + +// TODO Wrap surface +Swapchain::Swapchain(Device& device, CommandBuffer& cb, VkSurfaceKHR surface): + _device{device}, + _surface{surface}, + _swapchain{VK_NULL_HANDLE}, + _currentIndex{0} +{ + VkDevice vkDevice = _device.vkDevice(); + VkPhysicalDevice vkPhysicalDevice = _device.physicalDevice().vkPhysicalDevice(); + + #define GET_INSTANCE_PROC_ADDR(entrypoint) vk##entrypoint = PFN_vk##entrypoint(vkGetInstanceProcAddr(Vk::Context::current().vkInstance(), "vk"#entrypoint)); do{if(vk##entrypoint == nullptr) { Error() << "Failed to get function pointer.";} }while(false) + #define GET_DEVICE_PROC_ADDR(entrypoint) vk##entrypoint = PFN_vk##entrypoint(vkGetDeviceProcAddr(vkDevice, "vk"#entrypoint)); do{ if(vk##entrypoint == nullptr) { Error() << "Failed to get function pointer.";} }while(false) + + GET_INSTANCE_PROC_ADDR(GetPhysicalDeviceSurfaceSupportKHR); + GET_INSTANCE_PROC_ADDR(GetPhysicalDeviceSurfaceCapabilitiesKHR); + GET_INSTANCE_PROC_ADDR(GetPhysicalDeviceSurfaceFormatsKHR); + GET_INSTANCE_PROC_ADDR(GetPhysicalDeviceSurfacePresentModesKHR); + + GET_DEVICE_PROC_ADDR(CreateSwapchainKHR); + GET_DEVICE_PROC_ADDR(DestroySwapchainKHR); + GET_DEVICE_PROC_ADDR(GetSwapchainImagesKHR); + GET_DEVICE_PROC_ADDR(AcquireNextImageKHR); + GET_DEVICE_PROC_ADDR(QueuePresentKHR); + + #undef GET_INSTANCE_PROC_ADDR + #undef GET_DEVICE_PROC_ADDR + + VkResult err; + + // Get available queue family properties + uint32_t queueCount; + vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, + &queueCount, nullptr); + assert(queueCount >= 1); + + std::vector queueProps(queueCount); + vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, + &queueCount, queueProps.data()); + + std::vector supportsPresent(queueCount); + for (uint32_t i = 0; i < queueCount; i++) { + vkGetPhysicalDeviceSurfaceSupportKHR(vkPhysicalDevice, + i, surface, &supportsPresent[i]); + } + + // Search for a graphics and a present queue in the array of queue + // families, try to find one that supports both + uint32_t graphicsQueueNodeIndex = UINT32_MAX; + uint32_t presentQueueNodeIndex = UINT32_MAX; + for (uint32_t i = 0; i < queueCount; i++) { + if ((queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) { + if (graphicsQueueNodeIndex == UINT32_MAX) { + graphicsQueueNodeIndex = i; + } + + if (supportsPresent[i] == VK_TRUE) { + graphicsQueueNodeIndex = i; + presentQueueNodeIndex = i; + break; + } else { + Warning() << "Queue" << i << "does not support present."; + } + } + } + if (presentQueueNodeIndex == UINT32_MAX) { + // If there's no queue that supports both present and graphics + // try to find a separate present queue + for (uint32_t i = 0; i < queueCount; ++i) { + if (supportsPresent[i] == VK_TRUE) { + presentQueueNodeIndex = i; + break; + } + } + } + + // Exit if either a graphics or a presenting queue hasn't been found + if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX) { + return; // fatal + } + + // todo : Add support for separate graphics and presenting queue + if (graphicsQueueNodeIndex != presentQueueNodeIndex) { + Error() << "I am unsure about this error in Swapchain.cpp#L" << __LINE__; + return; // fatal + } + + // Get list of supported surface formats + UnsignedInt formatCount; + err = vkGetPhysicalDeviceSurfaceFormatsKHR(vkPhysicalDevice, surface, &formatCount, nullptr); + MAGNUM_VK_ASSERT_ERROR(err); + if(formatCount < 1) { + Error() << "The device does not support any surface formats."; // TODO: Can this even happen? + return; + } + + std::vector surfaceFormats(formatCount); + err = vkGetPhysicalDeviceSurfaceFormatsKHR(vkPhysicalDevice, + _surface, &formatCount, + surfaceFormats.data()); + MAGNUM_VK_ASSERT_ERROR(err); + + VkColorSpaceKHR colorSpace = surfaceFormats[0].colorSpace; + VkFormat colorFormat = VK_FORMAT_B8G8R8A8_UNORM; + if ((formatCount == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED)) { + /* no preferred format */ + colorFormat = VK_FORMAT_B8G8R8A8_UNORM; + } else { + // Always select the first available color format + // If you need a specific format (e.g. SRGB) you'd need to + // iterate over the list of available surface format and + // check for it's presence + colorFormat = surfaceFormats[0].format; + } + + // Get physical device surface properties and formats + VkSurfaceCapabilitiesKHR surfCaps; + err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vkPhysicalDevice, + surface, &surfCaps); + MAGNUM_VK_ASSERT_ERROR(err); + + // Get available present modes + UnsignedInt presentModeCount; + err = vkGetPhysicalDeviceSurfacePresentModesKHR(vkPhysicalDevice, + surface, &presentModeCount, nullptr); + MAGNUM_VK_ASSERT_ERROR(err); + if (presentModeCount < 1) { + Error() << "The device does not support any surface present mode."; // TODO: Can this even happen? + } + + std::vector presentModes(presentModeCount); + err = vkGetPhysicalDeviceSurfacePresentModesKHR(vkPhysicalDevice, + surface, &presentModeCount, + presentModes.data()); + MAGNUM_VK_ASSERT_ERROR(err); + + VkExtent2D swapchainExtent = surfCaps.currentExtent; + if (surfCaps.currentExtent.width == UnsignedInt(-1)) { + Error() << "The surface has undefined extents."; + return; + } + + VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; + for (auto presentMode : presentModes) { + if (presentMode == VK_PRESENT_MODE_MAILBOX_KHR) { + swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR; + break; + } + if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentMode == VK_PRESENT_MODE_IMMEDIATE_KHR)) { + swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + } + } + + UnsignedInt desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1; + if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount)) { + desiredNumberOfSwapchainImages = surfCaps.maxImageCount; + } + + VkSurfaceTransformFlagsKHR preTransform; + if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { + preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + } else { + preTransform = surfCaps.currentTransform; + } + + VkSwapchainKHR oldSwapchain = _swapchain; + + VkSwapchainCreateInfoKHR swapchainCI = {}; + swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchainCI.pNext = nullptr; + swapchainCI.flags = 0; + + swapchainCI.surface = _surface; + swapchainCI.imageFormat = colorFormat; + swapchainCI.imageColorSpace = colorSpace; + swapchainCI.imageExtent = swapchainExtent; + swapchainCI.minImageCount = desiredNumberOfSwapchainImages; + swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchainCI.preTransform = VkSurfaceTransformFlagBitsKHR(preTransform); + swapchainCI.imageArrayLayers = 1; + swapchainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchainCI.queueFamilyIndexCount = 0; + swapchainCI.pQueueFamilyIndices = nullptr; + swapchainCI.presentMode = swapchainPresentMode; + swapchainCI.oldSwapchain = VK_NULL_HANDLE; + swapchainCI.clipped = VK_TRUE; + swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + + err = vkCreateSwapchainKHR(vkDevice, &swapchainCI, nullptr, &_swapchain); + MAGNUM_VK_ASSERT_ERROR(err); + + // If an existing sawp chain is re-created, destroy the old swap chain + // This also cleans up all the presentable images + if (oldSwapchain != VK_NULL_HANDLE) { + vkDestroySwapchainKHR(vkDevice, oldSwapchain, nullptr); + } + + UnsignedInt imageCount = 0; + err = vkGetSwapchainImagesKHR(vkDevice, _swapchain, &imageCount, nullptr); + MAGNUM_VK_ASSERT_ERROR(err); + + std::vector images; + images.resize(imageCount); + + err = vkGetSwapchainImagesKHR(vkDevice, _swapchain, &imageCount, images.data()); + MAGNUM_VK_ASSERT_ERROR(err); + + _buffers.resize(imageCount); + for (uint32_t i = 0; i < imageCount; i++) { + _buffers[i].image.reset(new Vk::Image(_device, images[i])); + + // Create an image barrier object + VkImageMemoryBarrier imageMemoryBarrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + nullptr, + 0, /* src access mask */ + 0, /* dst access mask */ + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + VK_QUEUE_FAMILY_IGNORED, + VK_QUEUE_FAMILY_IGNORED, + *_buffers[i].image, + VkImageSubresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} + }; + + vkCmdPipelineBarrier( + cb, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &imageMemoryBarrier); + + _buffers[i].view.reset( + new Vk::ImageView(_device, *_buffers[i].image, colorFormat, + VK_IMAGE_VIEW_TYPE_2D, ImageAspect::Color, + VkComponentMapping{ + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A + } + ) + ); + } +} + +Swapchain::~Swapchain() { + vkDestroySwapchainKHR(_device, _swapchain, nullptr); + vkDestroySurfaceKHR(Vk::Context::current().vkInstance(), _surface, nullptr); +} + +Swapchain& Swapchain::queuePresent(VkQueue queue, UnsignedInt currentBuffer) { + VkPresentInfoKHR presentInfo = {}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.pNext = nullptr; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &_swapchain; + presentInfo.pImageIndices = ¤tBuffer; + VkResult err = vkQueuePresentKHR(queue, &presentInfo); + MAGNUM_VK_ASSERT_ERROR(err); + + return *this; +} + +Swapchain& Swapchain::queuePresent(Queue& queue, UnsignedInt currentBuffer, Semaphore& waitSemaphore) { + VkSemaphore sem = waitSemaphore.vkSemaphore(); + VkPresentInfoKHR presentInfo = {}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.pNext = nullptr; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &_swapchain; + presentInfo.pImageIndices = ¤tBuffer; + presentInfo.pWaitSemaphores = &sem; + presentInfo.waitSemaphoreCount = 1; + VkResult err = vkQueuePresentKHR(queue.vkQueue(), &presentInfo); + MAGNUM_VK_ASSERT_ERROR(err); + + return *this; +} + +}} diff --git a/src/Magnum/Vk/Swapchain.h b/src/Magnum/Vk/Swapchain.h new file mode 100644 index 000000000..eb74d4416 --- /dev/null +++ b/src/Magnum/Vk/Swapchain.h @@ -0,0 +1,155 @@ +#ifndef Magnum_Vk_Swapchain_h +#define Magnum_Vk_Swapchain_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::Swapchain + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/CommandBuffer.h" +#include "Magnum/Vk/Context.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/ImageView.h" +#include "Magnum/Vk/Semaphore.h" +#include "Magnum/Vk/visibility.h" + +namespace Magnum { namespace Vk { + +typedef struct { + std::unique_ptr image; + std::unique_ptr view; +} SwapchainBuffer; + +class MAGNUM_VK_EXPORT Swapchain { + public: + + Swapchain(Device& device, CommandBuffer& cb, VkSurfaceKHR surface); + + /** @brief Copying is not allowed */ + Swapchain(const Swapchain&) = delete; + + /** @brief Move constructor */ + Swapchain(Swapchain&& other); + + /** + * @brief Destructor + * + * @see @fn_vk{DestroySwapchain} + */ + ~Swapchain(); + + /** @brief Copying is not allowed */ + Swapchain& operator=(const Swapchain&) = delete; + + /** @brief Move assignment is not allowed */ + Swapchain& operator=(Swapchain&&) = delete; + + VkSwapchainKHR vkSwapchain() { + return _swapchain; + } + + Swapchain& acquireNextImage(Semaphore& presentCompleteSemaphore) { + VkResult err = vkAcquireNextImageKHR(_device.vkDevice(), + _swapchain, UINT64_MAX, + presentCompleteSemaphore.vkSemaphore(), + VkFence(nullptr), &_currentIndex); + MAGNUM_VK_ASSERT_ERROR(err); + + return *this; + } + + Swapchain& queuePresent(VkQueue queue, UnsignedInt currentBuffer); + + /** + * Present the current image to the given + * TODO + * @brief queuePresent + * @param queue + * @param currentBuffer + * @param waitSemaphore + * @return Reference to self (for method chaining) + */ + Swapchain& queuePresent(Queue& queue, UnsignedInt currentBuffer, Semaphore& waitSemaphore); + + /** + * @brief Number of images in the swapchain + */ + UnsignedInt imageCount() const { + return _buffers.size(); + } + + /** + * @brief Index of current buffer in swapchain + */ + UnsignedInt currentIndex() const { + return _currentIndex; + } + + /** + * @brief VkImageView at current index + */ + Image& image() { + return *_buffers[_currentIndex].image; + } + + /** + * @brief VkImageView at the given index + */ + Image& image(UnsignedInt index) { + return *_buffers[index].image; + } + + /** + * @brief VkImageView at the given index + */ + Vk::ImageView& imageView(UnsignedInt index) { + return *_buffers[index].view; + } + + private: + PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; + + PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; + PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; + PFN_vkQueuePresentKHR vkQueuePresentKHR; + + Device& _device; + VkSurfaceKHR _surface; + VkSwapchainKHR _swapchain; + std::vector _buffers; + UnsignedInt _currentIndex; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Test/CommandTest.cpp b/src/Magnum/Vk/Test/CommandTest.cpp new file mode 100644 index 000000000..fd706d6c6 --- /dev/null +++ b/src/Magnum/Vk/Test/CommandTest.cpp @@ -0,0 +1,59 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + + +#include +#include + +#include "Magnum/Vk/Command.h" +#include "Magnum/Vk/Context.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/PhysicalDevice.h" +#include "AbstractVulkanTester.h" + + +namespace Magnum { namespace Vk { namespace Test { + +struct CommandVkTest: AbstractVulkanTester { + explicit CommandVkTest(); + + void doTheLambdasWork(); +}; + +CommandVkTest::CommandVkTest() { + addTests({&CommandVkTest::doTheLambdasWork}); +} + +void CommandVkTest::doTheLambdasWork() { + Vk::Context context{}; + + //CommandBuffer buffer; + //buffer << Cmd::setScissor(0, {Range2Di{{0, 0}, {0, 0}}); +} + +}}} + +MAGNUM_VK_TEST_MAIN(Magnum::Vk::Test::CommandVkTest) diff --git a/src/Magnum/Vk/Test/ContextVkTest.cpp b/src/Magnum/Vk/Test/ContextVkTest.cpp new file mode 100644 index 000000000..8e25e7daf --- /dev/null +++ b/src/Magnum/Vk/Test/ContextVkTest.cpp @@ -0,0 +1,76 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + Copyright © 2016 Jonathan Hale + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + + +#include +#include + +#include "Magnum/Vk/Context.h" +#include "AbstractVulkanTester.h" + + +namespace Magnum { namespace Vk { namespace Test { + +struct ContextVkTest: AbstractVulkanTester { + explicit ContextVkTest(); + + void constructCopyMove(); + + void createInstance(); + void createWithValidation(); +}; + +ContextVkTest::ContextVkTest() { + addTests({&ContextVkTest::constructCopyMove, + &ContextVkTest::createInstance, + &ContextVkTest::createWithValidation}); +} + +void ContextVkTest::constructCopyMove() { + /* Only move-construction allowed */ + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY((std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void ContextVkTest::createInstance() { + Vk::Context context; + + CORRADE_VERIFY(&Vk::Context::current() != nullptr); + CORRADE_VERIFY(Vk::Context::hasCurrent()); + CORRADE_COMPARE(context.version(), Vk::Version::Vulkan_1_0); +} + +void ContextVkTest::createWithValidation() { + Vk::Context context{Vk::Context::Flag::EnableValidation}; + CORRADE_VERIFY(Vk::Context::hasCurrent()); + CORRADE_COMPARE(context.version(), Vk::Version::Vulkan_1_0); +} + +}}} + +MAGNUM_VK_TEST_MAIN(Magnum::Vk::Test::ContextVkTest)