From: adam.b Date: Wed, 31 Jan 2018 16:37:25 +0000 (+0000) Subject: [Vulkan] Basic Vulkan backend X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bd9d85d296a65bca6bdd3b2670557f1079bdee1f;p=platform%2Fcore%2Fuifw%2Fdali-core.git [Vulkan] Basic Vulkan backend Supported: - Pipeline ( limited ) - Shaders ( ShaderModule ) ( very limited ) - Buffers ( vertex and uniform buffers ) ( limited ) - Descriptors ( sets, layouts. descriptors, pools ) ( limited, no samplers ) - CommandBuffers ( limited set of commands ) - Simple synchronisation ( vsync and swapchain ) - Indexed draw Change-Id: Iafd2f6bb675ebb0994a8ed1c913128cef1fda0b0 --- diff --git a/dali/graphics/file.list b/dali/graphics/file.list index b73e81b..edb00b2 100644 --- a/dali/graphics/file.list +++ b/dali/graphics/file.list @@ -1,15 +1,20 @@ # Add graphics source files here graphics_src_files = \ - $(graphics_src_dir)/graphics-controller.cpp \ - $(graphics_src_dir)/vulkan/vulkan-graphics.cpp \ - $(graphics_src_dir)/vulkan/vulkan-fence.cpp \ - $(graphics_src_dir)/vulkan/vulkan-queue.cpp \ - $(graphics_src_dir)/vulkan/vulkan-surface.cpp \ - $(graphics_src_dir)/vulkan/vulkan-command-buffer.cpp \ - $(graphics_src_dir)/vulkan/vulkan-command-pool.cpp \ - $(graphics_src_dir)/vulkan/vulkan-image.cpp \ - $(graphics_src_dir)/vulkan/vulkan-buffer.cpp \ - $(graphics_src_dir)/vulkan/vulkan-device-memory-manager.cpp + $(graphics_src_dir)/vulkan/vulkan-command-pool.cpp \ + $(graphics_src_dir)/vulkan/vulkan-surface.cpp \ + $(graphics_src_dir)/vulkan/vulkan-fence.cpp \ + $(graphics_src_dir)/vulkan/vulkan-descriptor-set.cpp \ + $(graphics_src_dir)/vulkan/vulkan-framebuffer.cpp \ + $(graphics_src_dir)/vulkan/vulkan-queue.cpp \ + $(graphics_src_dir)/vulkan/generated/spv-shaders-gen.cpp \ + $(graphics_src_dir)/vulkan/gpu-memory/vulkan-gpu-memory-handle.cpp \ + $(graphics_src_dir)/vulkan/gpu-memory/vulkan-gpu-memory-manager.cpp \ + $(graphics_src_dir)/vulkan/vulkan-image.cpp \ + $(graphics_src_dir)/vulkan/vulkan-command-buffer.cpp \ + $(graphics_src_dir)/vulkan/vulkan-pipeline.cpp \ + $(graphics_src_dir)/vulkan/vulkan-buffer.cpp \ + $(graphics_src_dir)/vulkan/vulkan-graphics.cpp \ + $(graphics_src_dir)/vulkan/vulkan-shader.cpp diff --git a/dali/graphics/vulkan/generated/spv-shaders-gen.cpp b/dali/graphics/vulkan/generated/spv-shaders-gen.cpp new file mode 100644 index 0000000..2ec5c3c --- /dev/null +++ b/dali/graphics/vulkan/generated/spv-shaders-gen.cpp @@ -0,0 +1,169 @@ +#include "spv-shaders-gen.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wlarger-than=" +std::vector VSH_CODE = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xae, 0x01, 0x00, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x67, 0x6c, 0x5f, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x00, 0x06, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74, + 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43, + 0x6c, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00, + 0x05, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x77, 0x6f, 0x72, 0x6c, + 0x64, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x4d, 0x61, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x76, 0x69, 0x65, 0x77, 0x4d, 0x61, 0x74, 0x00, + 0x06, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x70, 0x72, 0x6f, 0x6a, 0x4d, 0x61, 0x74, 0x00, 0x06, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, + 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x74, 0x72, 0x69, 0x43, + 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, + 0x20, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x1a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x92, 0x00, 0x05, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x1a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x92, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x91, 0x00, 0x05, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, + 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +std::vector FSH_CODE = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xae, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x43, + 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x74, 0x72, 0x69, 0x43, 0x6f, 0x6c, 0x6f, 0x72, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +#pragma GCC diagnostic pop diff --git a/dali/graphics/vulkan/generated/spv-shaders-gen.h b/dali/graphics/vulkan/generated/spv-shaders-gen.h new file mode 100644 index 0000000..716b7ff --- /dev/null +++ b/dali/graphics/vulkan/generated/spv-shaders-gen.h @@ -0,0 +1,46 @@ +// Autogenerated +#ifndef SPV_GENERATED_HEADER +#define SPV_GENERATED_HEADER +#include +#include + + +extern std::vector VSH_CODE; +/* +#version 430 + +layout( location = 0 ) in vec3 aPosition; + +layout( set = 0, binding = 0, std140 ) uniform world +{ + mat4 modelMat; + mat4 viewMat; + mat4 projMat; + vec4 color; +}; + +layout( location = 0 ) out vec4 triColor; + +void main() +{ + gl_Position = projMat * viewMat * modelMat * vec4( aPosition, 1.0 ); + triColor = color; +}*/ + + +extern std::vector FSH_CODE; +/* +#version 430 + +layout( location = 0 ) in vec4 triColor; +layout( location = 0 ) out vec4 outColor; + +void main() +{ + outColor = triColor; +}*/ + + +#endif // SPV_GENERATED_HEADER + + diff --git a/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-allocator.h b/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-allocator.h new file mode 100644 index 0000000..66d75d2 --- /dev/null +++ b/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-allocator.h @@ -0,0 +1,139 @@ +#ifndef DALI_GRAPHICS_VULKAN_GPU_MEMORY_ALLOCATOR +#define DALI_GRAPHICS_VULKAN_GPU_MEMORY_ALLOCATOR + +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ +class Buffer; +class Image; +class GpuMemoryBlock; +/** + * Interface to Gpu memory allocation, must be overriden. + */ +using GpuMemoryAllocationData = void*; + +class GpuMemoryAllocator +{ +public: + + GpuMemoryAllocator() = default; + + /** + * + */ + virtual ~GpuMemoryAllocator() = default; + + /** + * + * @param requirements + * @param memoryProperties + * @return + */ + virtual GpuMemoryBlockHandle Allocate( const vk::MemoryRequirements& requirements, vk::MemoryPropertyFlags memoryProperties ) = 0; + + /** + * + * @param buffer + * @param memoryProperties + * @return + */ + virtual GpuMemoryBlockHandle Allocate( const Handle& buffer, vk::MemoryPropertyFlags memoryProperties ) = 0; + + /** + * + * @param buffer + * @param memoryProperties + * @return + */ + virtual GpuMemoryBlockHandle Allocate( Image& buffer, vk::MemoryPropertyFlags memoryProperties ) = 0; + + // refcounting managed via allocator which ownes all the blocks, allocator may + // implement this feature any way ( or simply ignore it ) + /** + * + * @param allocationId + */ + virtual void Retain( GpuMemoryBlock& allocationId ) {} + + /** + * + * @param allocationId + */ + virtual void Release( GpuMemoryBlock& allocationId ) {} + + /** + * + * @param allocationId + */ + virtual uint32_t GetRefCount( GpuMemoryBlock& allocationId ) + { + return 0u; + } + + // Garbage collection + /** + * + * @param userdata + */ + virtual void GC( void* userdata ) = 0; + + // Retrieve Vulkan object for this allocation + /** + * + * @return + */ + virtual vk::DeviceMemory GetVkDeviceMemory( GpuMemoryBlock& allocationId ) const = 0; + + /** + * Memory mapping + * @param allocationId + * @param offset + * @param size + * @return + */ + virtual void* Map( GpuMemoryBlock& allocationId, uint32_t offset, uint32_t size ) = 0; + + /** + * Memory mapping + * @param allocationId + * @param offset + * @param size + * @return + */ + virtual void Unmap( GpuMemoryBlock& allocationId ) = 0; + + /** + * + * @param allocationId + */ + virtual void Flush( GpuMemoryBlock& allocationId ) = 0; +}; + +} // Namespace Vulkan + +} // namespace Graphics + +} // Namespace Dali + +#endif // DALI_GRAPHICS_VULKAN_GPU_MEMORY_ALLOCATOR diff --git a/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.cpp b/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.cpp new file mode 100644 index 0000000..0d78be4 --- /dev/null +++ b/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ + +void GpuMemoryBlock::OnRelease( uint32_t refcount ) +{ + mAllocator.Release( *this ); +} + +void GpuMemoryBlock::OnRetain( uint32_t refcount ) +{ + mAllocator.Retain( *this ); +} + +bool GpuMemoryBlock::OnDestroy() +{ + // don't use default delete + return true; +} + +GpuMemoryBlock::operator vk::DeviceMemory() +{ + return mAllocator.GetVkDeviceMemory( *this ); +} + +void* GpuMemoryBlock::Map() +{ + return mAllocator.Map( *this, 0, 0 ); +} + +void* GpuMemoryBlock::Map( uint32_t offset, uint32_t size ) +{ + return mAllocator.Map( *this, offset, size ); +} + +void GpuMemoryBlock::Unmap() +{ + mAllocator.Unmap( *this ); +} + +void GpuMemoryBlock::Flush() +{ + NotImplemented(); +} + +} + +} + +} \ No newline at end of file diff --git a/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.h b/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.h new file mode 100644 index 0000000..1a30f87 --- /dev/null +++ b/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.h @@ -0,0 +1,122 @@ +#ifndef DALI_VULKAN_161117_GPU_MEMORY_HANDLE_H +#define DALI_VULKAN_161117_GPU_MEMORY_HANDLE_H + +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ +class GpuMemoryAllocator; +const uint32_t INVALID_ALLOCATION { UINT32_MAX }; + +struct Any {}; +class GpuMemoryBlock : public VkManaged +{ +public: + + template + GpuMemoryBlock( GpuMemoryAllocator& allocator, std::unique_ptr data ) : + mAllocator(allocator), mAllocationData(reinterpret_cast(data.release())){} + + /** + * + * @return + */ + void* Map(); + + /** + * + * @param offset + * @param size + * @return + */ + void* Map( uint32_t offset, uint32_t size ); + + /** + * + */ + void Unmap(); + + /** + * + */ + void Flush(); + + /** + * + * @return + */ + operator vk::DeviceMemory(); + + /** + * + * @tparam T + * @return + */ + template + T* GetData() const + { + return reinterpret_cast(mAllocationData.get()); + } + + /** + * + * @return + */ + GpuMemoryAllocator& GetAllocator() const + { + return mAllocator; + } + +public: + + /** + * + * @param refcount + */ + void OnRelease( uint32_t refcount ) override; + + /** + * + * @param refcount + */ + void OnRetain( uint32_t refcount ) override; + + /** + * + */ + bool OnDestroy() override; + +private: + + GpuMemoryAllocator& mAllocator; + std::unique_ptr mAllocationData; // may be any POD object pointer, depends on allocator +}; + +using GpuMemoryBlockHandle = Handle; + +} +} +} + +#endif //DALI_VULKAN_161117_GPU_MEMORY_HANDLE_H diff --git a/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.cpp b/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.cpp new file mode 100644 index 0000000..7fc9a64 --- /dev/null +++ b/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ + +namespace +{ + +const uint32_t INVALID_MEMORY_INDEX = -1u; + +/** + * Helper function which returns GPU heap index that can be used to allocate + * particular type of resource + */ +uint32_t GetMemoryIndex(const vk::PhysicalDeviceMemoryProperties &memoryProperties, + uint32_t memoryTypeBits, vk::MemoryPropertyFlags properties) +{ + for(uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) + { + if((memoryTypeBits & (1u << i)) && + ((memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)) + { + return i; + } + } + return INVALID_MEMORY_INDEX; +} +} + +/** + * Class: GpuMemoryDefaultAllocator + * + * Non-thread safe default GPU memory allocator + * with simple refcounting and garbage collection on demand + */ +struct GpuMemoryDefaultAllocator : public GpuMemoryAllocator +{ + struct MemoryBlock + { + MemoryBlock() = default; + ~MemoryBlock() = default; + + vk::MemoryRequirements requirements {}; + vk::DeviceSize offset { 0u }; + vk::DeviceSize size { 0u }; + vk::DeviceSize alignment { 0u }; + vk::DeviceMemory memory { nullptr }; + }; + + GpuMemoryDefaultAllocator( GpuMemoryManager& manager ) + : GpuMemoryAllocator(), mGpuManager( manager ), + mGraphics(manager.GetGraphics()) + { + + } + + ~GpuMemoryDefaultAllocator() override = default; + + + GpuMemoryBlockHandle Allocate( const vk::MemoryRequirements& requirements, vk::MemoryPropertyFlags memoryProperties ) override + { + + auto memoryTypeIndex = GetMemoryIndex(mGraphics.GetMemoryProperties(), requirements.memoryTypeBits, + memoryProperties); + + auto memory = VkAssert( + mGraphics.GetDevice() + .allocateMemory(vk::MemoryAllocateInfo{} + .setMemoryTypeIndex(memoryTypeIndex) + .setAllocationSize(requirements.size), mGraphics.GetAllocator())); + + // add allocated memory to the heap of memories as a base handle + auto handle = GpuMemoryBlockHandle( new GpuMemoryBlock( *this, MakeUnique() ) ); + + auto &block = *handle->GetData(); + block.requirements = requirements; + block.offset = 0u; + block.size = requirements.size; + block.alignment = requirements.alignment; + block.memory = memory; + + mUniqueBlocks.emplace_back( MakeUnique(handle) ); + return handle; + } + + /** + * + * @param buffer + * @param memoryProperties + * @return + */ + virtual GpuMemoryBlockHandle Allocate( const Handle& buffer, vk::MemoryPropertyFlags memoryProperties ) override + { + return Allocate( mGraphics.GetDevice().getBufferMemoryRequirements( buffer->GetVkBuffer() ), + memoryProperties ); + } + + /** + * + * @param buffer + * @param memoryProperties + * @return + */ + GpuMemoryBlockHandle Allocate( Image& image, vk::MemoryPropertyFlags memoryProperties ) override + { + return Allocate( mGraphics.GetDevice().getImageMemoryRequirements( image.GetImage() ), + memoryProperties ); + } + + /** + * + * Reference counting + */ + void Retain( GpuMemoryBlock& allocationId ) override + { + } + + void Release( GpuMemoryBlock& block ) override + { + if( block.GetRefCount() == 1 ) + { + GC(nullptr); + } + } + + /** + * + * Garbage collection + */ + void GC( void* userdata ) override + { + for( auto&& block : mUniqueBlocks ) + { + if( block->GetRefCount() == 1 ) + { + // collect and make invalid ( maybe freelist or sumtink ) + mGraphics.GetDevice().freeMemory( (**block.get()), mGraphics.GetAllocator() ); + block.reset( nullptr ); + } + } + } + + vk::DeviceMemory GetVkDeviceMemory( GpuMemoryBlock& block ) const override + { + return block.GetData()->memory; + } + + void* Map( GpuMemoryBlock& block, uint32_t offset, uint32_t size ) override + { + return VkAssert( mGraphics.GetDevice().mapMemory( block.GetData()->memory, + offset, size == 0u ? VK_WHOLE_SIZE : static_cast(size))); + } + + void Unmap( GpuMemoryBlock& block ) override + { + mGraphics.GetDevice().unmapMemory( block.GetData()->memory ); + } + + void Flush( GpuMemoryBlock& allocationId ) override + { + NotImplemented(); + } + + GpuMemoryManager& mGpuManager; + Graphics& mGraphics; + + std::vector> mUniqueBlocks; +}; + +struct GpuMemoryManager::Impl +{ + Impl( Graphics& graphics, GpuMemoryManager& interface ) : + mGraphics( graphics ), + mMemoryManager( interface ) + { + + } + + ~Impl() + { + } + + bool Initialise() + { + CreateDefaultAllocator(); + return true; + } + + GpuMemoryAllocator& GetDefaultAllocator() const + { + return *mDefaultAllocator; + } + + void CreateDefaultAllocator() + { + mDefaultAllocator = MakeUnique( mMemoryManager ); + } + + Graphics& mGraphics; + GpuMemoryManager& mMemoryManager; // interface to this implementation + std::unique_ptr mDefaultAllocator; // default allocator, brute force allocation +}; + +/** + * Class: GpuMemoryManager + */ + +std::unique_ptr GpuMemoryManager::New(Graphics& graphics) +{ + auto retval = std::unique_ptr(new GpuMemoryManager(graphics)); + if( retval->mImpl->Initialise() ) + { + return retval; + } + return nullptr; +} + +GpuMemoryManager::GpuMemoryManager() = default; + +GpuMemoryManager::~GpuMemoryManager() = default; + +GpuMemoryManager::GpuMemoryManager(Graphics& graphics) +{ + mImpl = std::unique_ptr>( new Impl(graphics, *this) ); +} + +GpuMemoryAllocator& GpuMemoryManager::GetDefaultAllocator() const +{ + return mImpl->GetDefaultAllocator(); +} + + +GpuMemoryAllocatorUID GpuMemoryManager::RegisterAllocator( std::unique_ptr allocator ) +{ + NotImplemented(); + return 0; +} + +bool GpuMemoryManager::UnregisterAllocator( GpuMemoryAllocatorUID allocatorHandle ) +{ + NotImplemented(); + return false; +} + +Graphics& GpuMemoryManager::GetGraphics() const +{ + return mImpl->mGraphics; +} + +} + +} + +} diff --git a/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.h b/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.h new file mode 100644 index 0000000..34ad5a3 --- /dev/null +++ b/dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.h @@ -0,0 +1,91 @@ +#ifndef DALI_VULKAN_161117_GPU_MEMORY_MANAGER_H +#define DALI_VULKAN_161117_GPU_MEMORY_MANAGER_H + +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ +using GpuMemoryAllocatorUID = uint32_t; +class Graphics; +class GpuMemoryAllocator; + +class GpuMemoryManager +{ +public: + + static std::unique_ptr New( Graphics& graphics ); + + /** + * + */ + ~GpuMemoryManager(); + + /** + * + * @return + */ + GpuMemoryAllocator& GetDefaultAllocator() const; + + /** + * + * @param allocator + * @return + */ + GpuMemoryAllocatorUID RegisterAllocator( std::unique_ptr allocator ); + + /** + * + * @param allocatorHandle + * @return + */ + bool UnregisterAllocator( GpuMemoryAllocatorUID allocatorHandle ); + + /** + * + * @return + */ + Graphics& GetGraphics() const; + +private: + + GpuMemoryManager(); + + /** + * + */ + GpuMemoryManager( Graphics& graphics ); + +private: + + class Impl; + std::unique_ptr mImpl; +}; + +} + +} + +} + +#endif //DALI_VULKAN_161117_GPU_MEMORY_MANAGER_H diff --git a/dali/graphics/vulkan/shaders/basic-shader.frag b/dali/graphics/vulkan/shaders/basic-shader.frag new file mode 100644 index 0000000..63e6c1c --- /dev/null +++ b/dali/graphics/vulkan/shaders/basic-shader.frag @@ -0,0 +1,9 @@ +#version 430 + +layout( location = 0 ) in vec4 triColor; +layout( location = 0 ) out vec4 outColor; + +void main() +{ + outColor = triColor; +} \ No newline at end of file diff --git a/dali/graphics/vulkan/shaders/basic-shader.vert b/dali/graphics/vulkan/shaders/basic-shader.vert new file mode 100644 index 0000000..6f1988f --- /dev/null +++ b/dali/graphics/vulkan/shaders/basic-shader.vert @@ -0,0 +1,19 @@ +#version 430 + +layout( location = 0 ) in vec3 aPosition; + +layout( set = 0, binding = 0, std140 ) uniform world +{ + mat4 modelMat; + mat4 viewMat; + mat4 projMat; + vec4 color; +}; + +layout( location = 0 ) out vec4 triColor; + +void main() +{ + gl_Position = projMat * viewMat * modelMat * vec4( aPosition, 1.0 ); + triColor = color; +} \ No newline at end of file diff --git a/dali/graphics/vulkan/vulkan-buffer.cpp b/dali/graphics/vulkan/vulkan-buffer.cpp index 17b4b74..81226da 100644 --- a/dali/graphics/vulkan/vulkan-buffer.cpp +++ b/dali/graphics/vulkan/vulkan-buffer.cpp @@ -1,5 +1,179 @@ -// -// Created by adam.b on 06/06/17. -// +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ -#include "vulkan-buffer.h" +#include +#include +#include +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ + +struct Buffer::Impl final +{ + /** + * + * @param graphics + * @param createInfo + */ + Impl(Graphics& graphics, Buffer& owner, const vk::BufferCreateInfo& createInfo) + : mGraphics(graphics), + mInterface( owner ), + mDeviceMemory(nullptr), + mInfo(createInfo) + { + } + + /** + * + */ + ~Impl() + { + mGraphics.GetDevice().destroyBuffer( mBuffer, mGraphics.GetAllocator() ); + } + + /** + * Initialises Buffer with memory, as host visible ( for write ) + * @return + */ + bool Initialise() + { + mBuffer = VkAssert(mGraphics.GetDevice().createBuffer( mInfo, mGraphics.GetAllocator())); + return true; + } + + /** + * + * @return + */ + vk::BufferUsageFlags GetUsage() const + { + return mInfo.usage; + } + + /** + * + * @return + */ + size_t GetSize() const + { + return static_cast(mInfo.size); + } + + /** + * + * @return + */ + vk::Buffer GetVkBuffer() const + { + return mBuffer; + } + + void BindMemory( GpuMemoryBlockHandle handle ) + { + assert( mBuffer && "Buffer not initialised!"); + VkAssert(mGraphics.GetDevice().bindBufferMemory( mBuffer, (*handle), 0 )); + mDeviceMemory = handle; + } + + Vulkan::Graphics& mGraphics; + Vulkan::Buffer& mInterface; + GpuMemoryBlockHandle mDeviceMemory; + vk::BufferCreateInfo mInfo; + vk::Buffer mBuffer; +}; + +/** + * + * @param graphics + * @param size + * @return + */ +BufferHandle Buffer::New(Graphics& graphics, size_t size, Type type) +{ + auto usageFlags = vk::BufferUsageFlags{}; + + switch( type ) + { + case Type::VERTEX: { usageFlags |= vk::BufferUsageFlagBits::eVertexBuffer; break; }; + case Type::INDEX: { usageFlags |= vk::BufferUsageFlagBits::eIndexBuffer; break; }; + case Type::UNIFORM: { usageFlags |= vk::BufferUsageFlagBits::eUniformBuffer; break; }; + case Type::SHADER_STORAGE: { usageFlags |= vk::BufferUsageFlagBits::eStorageBuffer; break; }; + } + + auto info = vk::BufferCreateInfo{}; + info.setSharingMode( vk::SharingMode::eExclusive ); + info.setSize( size ); + info.setUsage( usageFlags | vk::BufferUsageFlagBits::eTransferDst ); + auto buffer = Handle( new Buffer(graphics, info) ); + + if(buffer && buffer->mImpl->Initialise()) + { + graphics.AddBuffer( buffer ); + } + return buffer; +} + +Buffer::Buffer(Graphics& graphics, const vk::BufferCreateInfo& createInfo) +: VkManaged() +{ + mImpl = MakeUnique(graphics, *this, createInfo); +} + +Buffer::~Buffer() = default; + +vk::BufferUsageFlags Buffer::GetUsage() const +{ + return mImpl->GetUsage(); +} + +const GpuMemoryBlockHandle& Buffer::GetMemoryHandle() const +{ + return mImpl->mDeviceMemory; +} + +uint32_t Buffer::GetSize() const +{ + return U32(mImpl->GetSize()); +} + +vk::Buffer Buffer::GetVkBuffer() const +{ + return mImpl->GetVkBuffer(); +} + +void Buffer::BindMemory( const GpuMemoryBlockHandle& handle ) +{ + mImpl->BindMemory( handle ); +} + +bool Buffer::OnDestroy() +{ + mImpl->mGraphics.RemoveBuffer( *this ); + return true; +} + + +} + +} + +} \ No newline at end of file diff --git a/dali/graphics/vulkan/vulkan-buffer.h b/dali/graphics/vulkan/vulkan-buffer.h index 5cdedc6..0b67908 100644 --- a/dali/graphics/vulkan/vulkan-buffer.h +++ b/dali/graphics/vulkan/vulkan-buffer.h @@ -1,9 +1,22 @@ -// -// Created by adam.b on 06/06/17. -// +#ifndef DALI_GRAPHICS_VULKAN_BUFFER_H +#define DALI_GRAPHICS_VULKAN_BUFFER_H -#ifndef VULKAN_PROJECT_BUFFER_H -#define VULKAN_PROJECT_BUFFER_H +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ #include @@ -13,12 +26,101 @@ namespace Graphics { namespace Vulkan { +class DeviceMemory; +class Graphics; +class GpuMemoryBlock; +using GpuMemoryBlockHandle = Handle; -class Buffer +using VertexBuffer = Buffer; +using UniformBuffer = Buffer; +using IndexBuffer = Buffer; +using BufferHandle = Handle; + +class Buffer : public VkManaged { +public: + + /** + * Type of the buffer + */ + enum class Type + { + VERTEX, + INDEX, + UNIFORM, + SHADER_STORAGE + }; + + /** + * Destructor + */ + ~Buffer() override; + + /** + * Creates logical buffer without allocating any memory + * @param graphics + * @param size + * @param type + * @return + */ + static BufferHandle New( Graphics& graphics, size_t size, Type type ); + + /** + * Returns buffer usage flags + * @return + */ + vk::BufferUsageFlags GetUsage() const; + + /** + * Returns buffer size in bytes + * @return + */ + uint32_t GetSize() const; + + /** + * Returns Vulkan VkBuffer object associated with this buffer + * @return + */ + vk::Buffer GetVkBuffer() const; + + /** + * Returns handle to the allocated memory + * @return + */ + const GpuMemoryBlockHandle& GetMemoryHandle() const; + /** + * Binds buffer memory + * @param handle + */ + void BindMemory( const GpuMemoryBlockHandle& handle ); + +public: + + /** + * + * @return + */ + bool OnDestroy() override; + + +private: + + /** + * Creates new VkBuffer with given specification, it doesn't + * bind the memory. + * @param graphics + * @param createInfo + */ + Buffer(Graphics& graphics, const vk::BufferCreateInfo& createInfo); + +private: + + class Impl; + std::unique_ptr mImpl; }; + } } } diff --git a/dali/graphics/vulkan/vulkan-command-buffer.cpp b/dali/graphics/vulkan/vulkan-command-buffer.cpp index 501cd26..f67dba9 100644 --- a/dali/graphics/vulkan/vulkan-command-buffer.cpp +++ b/dali/graphics/vulkan/vulkan-command-buffer.cpp @@ -16,9 +16,15 @@ */ // INTERNAL INCLUDES +#include #include #include #include +#include +#include +#include +#include +#include namespace Dali { @@ -27,60 +33,380 @@ namespace Graphics namespace Vulkan { -CommandBuffer::CommandBuffer(Graphics& graphics, CommandPool& ownerPool) -: CommandBuffer(graphics, ownerPool, - vk::CommandBufferAllocateInfo().setCommandBufferCount(1).setLevel(vk::CommandBufferLevel::ePrimary)) +struct CommandBuffer::Impl { -} + Impl( CommandPool& commandPool, const vk::CommandBufferAllocateInfo& allocateInfo, vk::CommandBuffer commandBuffer ) + : mGraphics( commandPool.GetGraphics() ), + mOwnerCommandPool( commandPool ), + mAllocateInfo( allocateInfo ), + mCommandBuffer( commandBuffer ) + { + + } + + ~Impl() + { + } + + bool Initialise() + { + return true; + } + + template + bool IsResourceAdded( Handle resourceHandle ) + { + for( auto&& res : mResources ) + { + if( res == resourceHandle ) + { + return true; + } + } + return false; + } + + template + bool PushResource( Handle resourceHandle ) + { + if(!IsResourceAdded( resourceHandle )) + { + mResources.push_back(VkTypeCast( resourceHandle )); + return true; + } + return false; + } + + /** + * + */ + void Begin(vk::CommandBufferUsageFlags usageFlags, vk::CommandBufferInheritanceInfo* inheritanceInfo) + { + assert(!mRecording && "CommandBuffer already is in the recording state"); + auto info = vk::CommandBufferBeginInfo{}; + info.setPInheritanceInfo(inheritanceInfo); + info.setFlags(usageFlags); + + // set the inheritance option + auto inheritance = vk::CommandBufferInheritanceInfo{}.setSubpass( 0 ); + + if( mAllocateInfo.level == vk::CommandBufferLevel::eSecondary ) + { + // todo: sets render pass from 'default' surface, should be supplied from primary command buffer + // which has render pass associated within execution context + inheritance.setRenderPass( mGraphics.GetSurface(0).GetRenderPass() ); + info.setPInheritanceInfo( &inheritance ); + } + + VkAssert(mCommandBuffer.begin(info)); + mRecording = true; + } + + void End() + { + assert(mRecording && "CommandBuffer is not in the recording state!"); + VkAssert(mCommandBuffer.end()); + mRecording = false; + } + + void Reset() + { + assert(!mRecording && "Can't reset command buffer during recording!"); + assert(mCommandBuffer && "Invalid command buffer!"); + mCommandBuffer.reset(vk::CommandBufferResetFlagBits::eReleaseResources); + } + + void Free() + { + assert(mCommandBuffer && "Invalid command buffer!"); + mGraphics.GetDevice().freeCommandBuffers(mOwnerCommandPool.GetPool(), mCommandBuffer); + } + + void ImageLayoutTransition(vk::Image image, + vk::ImageLayout oldLayout, + vk::ImageLayout newLayout, + vk::ImageAspectFlags aspectMask) + { + // just push new image barrier until any command is being called or buffer recording ends. + // it will make sure we batch barriers together rather than calling cmdPipelineBarrier + // for each separately + vk::AccessFlags srcAccessMask, dstAccessMask; + vk::PipelineStageFlags srcStageMask, dstStageMask; + + // TODO: add other transitions + switch(oldLayout) + { + case vk::ImageLayout::eUndefined: + { + srcStageMask = vk::PipelineStageFlagBits::eTopOfPipe; + } + break; + case vk::ImageLayout::ePresentSrcKHR: + { + srcStageMask = vk::PipelineStageFlagBits::eBottomOfPipe; + srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead; + } + break; + case vk::ImageLayout::eColorAttachmentOptimal: + { + srcStageMask = vk::PipelineStageFlagBits::eFragmentShader | vk::PipelineStageFlagBits::eColorAttachmentOutput; + srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead; + } + break; + case vk::ImageLayout::eGeneral: + case vk::ImageLayout::eDepthStencilAttachmentOptimal: + case vk::ImageLayout::eDepthStencilReadOnlyOptimal: + case vk::ImageLayout::eShaderReadOnlyOptimal: + case vk::ImageLayout::eTransferSrcOptimal: + case vk::ImageLayout::eTransferDstOptimal: + case vk::ImageLayout::ePreinitialized: + case vk::ImageLayout::eSharedPresentKHR: + { + } + } + + switch(newLayout) + { + case vk::ImageLayout::eColorAttachmentOptimal: + { + dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eFragmentShader; + dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eHostWrite; + break; + } + case vk::ImageLayout::eDepthStencilAttachmentOptimal: + { + dstStageMask = vk::PipelineStageFlagBits::eFragmentShader | vk::PipelineStageFlagBits::eEarlyFragmentTests; + dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite; + break; + } + case vk::ImageLayout::ePresentSrcKHR: + { + dstStageMask = vk::PipelineStageFlagBits::eBottomOfPipe; + dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eMemoryRead; + } + case vk::ImageLayout::eGeneral: + case vk::ImageLayout::eDepthStencilReadOnlyOptimal: + case vk::ImageLayout::eShaderReadOnlyOptimal: + case vk::ImageLayout::eTransferSrcOptimal: + case vk::ImageLayout::eTransferDstOptimal: + case vk::ImageLayout::ePreinitialized: + case vk::ImageLayout::eUndefined: + case vk::ImageLayout::eSharedPresentKHR: + { + break; + } + + } + + RecordImageLayoutTransition(image, srcAccessMask, dstAccessMask, srcStageMask, dstStageMask, + oldLayout, newLayout, aspectMask); + } + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wframe-larger-than=" + void RecordImageLayoutTransition(vk::Image image, vk::AccessFlags srcAccessMask, + vk::AccessFlags dstAccessMask, vk::PipelineStageFlags srcStageMask, + vk::PipelineStageFlags dstStageMask, vk::ImageLayout oldLayout, + vk::ImageLayout newLayout, vk::ImageAspectFlags aspectMask) + { + vk::ImageSubresourceRange subres; + subres.setLayerCount(1).setBaseMipLevel(0).setBaseArrayLayer(0).setLevelCount(1).setAspectMask(aspectMask); + + + auto barrier = vk::ImageMemoryBarrier{}; + barrier + .setImage(image) + .setSubresourceRange(subres) + .setSrcAccessMask(srcAccessMask) + .setDstAccessMask(dstAccessMask) + .setOldLayout(oldLayout) + .setNewLayout(newLayout); + ; + // todo: implement barriers batching + mCommandBuffer.pipelineBarrier(srcStageMask, dstStageMask, vk::DependencyFlags{}, nullptr, nullptr, barrier); + } +#pragma GCC diagnostic pop + + /** Push wait semaphores */ + void PushWaitSemaphores(const std::vector< vk::Semaphore >& semaphores, + const std::vector< vk::PipelineStageFlags >& stages) + { + mWaitSemaphores = semaphores; + mWaitStages = stages; + } + + /** Push signal semaphores */ + void PushSignalSemaphores(const std::vector< vk::Semaphore >& semaphores) + { + mSignalSemaphores = semaphores; + } + + // TODO: handles should be synchronized + void BindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount, std::vector> buffers, + const vk::DeviceSize *pOffsets) + { + // update list of used resources and create an array of VkBuffers + std::vector vkBuffers; + vkBuffers.reserve( buffers.size() ); + for( auto&& buffer : buffers ) + { + vkBuffers.emplace_back( buffer->GetVkBuffer() ); + PushResource(buffer); + } + + mCommandBuffer.bindVertexBuffers( firstBinding, bindingCount, vkBuffers.data(), pOffsets); + } + + void BindIndexBuffer( BufferRef buffer, uint32_t offset, vk::IndexType indexType) + { + // validate + assert ( (buffer->GetUsage() & vk::BufferUsageFlagBits::eIndexBuffer) && "The buffer used as index buffer has wrong usage flags!" ); + + PushResource( buffer ); + mCommandBuffer.bindIndexBuffer( buffer->GetVkBuffer(), offset, indexType ); + } + + void BindGraphicsPipeline( Handle pipeline ) + { + PushResource( pipeline ); + mCurrentPipeline = pipeline; + mCommandBuffer.bindPipeline( vk::PipelineBindPoint::eGraphics, pipeline->GetVkPipeline() ); + } + + void BindDescriptorSets( std::vector> descriptorSets, + Handle pipeline, uint32_t firstSet, uint32_t descriptorSetCount ) + { + // update resources + PushResource( pipeline ); + std::vector vkSets; + vkSets.reserve( descriptorSets.size() ); + for( auto&& set : descriptorSets ) + { + vkSets.emplace_back( set->GetVkDescriptorSet() ); + PushResource( set ); + } + + // TODO: support dynamic offsets + mCommandBuffer.bindDescriptorSets( vk::PipelineBindPoint::eGraphics, pipeline->GetVkPipelineLayout(), + firstSet, descriptorSetCount, vkSets.data(), 0, nullptr ); + } + + void Draw( uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance ) + { + mCommandBuffer.draw( vertexCount, instanceCount, firstVertex, firstInstance ); + } + + void DrawIndexed( uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, uint32_t vertexOffset, uint32_t firstInstance ) + { + mCommandBuffer.drawIndexed( indexCount, instanceCount, firstIndex, vertexOffset, firstInstance ); + } + + const std::vector< Handle> GetResources() const + { + return mResources; + } + + // RENDER PASS + void BeginRenderPass( FBID framebufferId, uint32_t bufferIndex ) + { + auto& surface = mGraphics.GetSurface( framebufferId ); + auto renderPass = surface.GetRenderPass(); + auto frameBuffer = surface.GetFramebuffer( bufferIndex ); + auto clearValues = surface.GetClearValues(); + + auto info = vk::RenderPassBeginInfo{}; + info.setFramebuffer( frameBuffer ); + info.setRenderPass( renderPass ); + info.setClearValueCount( U32(clearValues.size()) ); + info.setPClearValues( clearValues.data() ); + info.setRenderArea( vk::Rect2D( { 0,0 }, surface.GetSize() ) ); + + mCurrentRenderPass = renderPass; + mCommandBuffer.beginRenderPass( info, vk::SubpassContents::eInline ); + } + + void BeginRenderPass( vk::RenderPassBeginInfo renderPassBeginInfo, vk::SubpassContents subpassContents ) + { + mCurrentRenderPass = renderPassBeginInfo.renderPass; + mCommandBuffer.beginRenderPass( renderPassBeginInfo, subpassContents ); + } + + void EndRenderPass() + { + mCurrentRenderPass = nullptr; + mCommandBuffer.endRenderPass(); + } + + void ExecuteCommands( std::vector> commandBuffers ) + { + auto vkBuffers = std::vector{}; + vkBuffers.reserve( commandBuffers.size() ); + for( auto&& buf : commandBuffers ) + { + vkBuffers.emplace_back( buf->GetVkCommandBuffer() ); + PushResource( buf ); + } + + mCommandBuffer.executeCommands( vkBuffers ); + } + + Graphics& mGraphics; + CommandPool& mOwnerCommandPool; + vk::CommandBufferAllocateInfo mAllocateInfo {}; -CommandBuffer::CommandBuffer(Graphics& graphics, CommandPool& ownerPool, - const vk::CommandBufferAllocateInfo& allocateInfo) -: mGraphics(graphics), mCommandPool(ownerPool), mRecording(false) + vk::CommandBuffer mCommandBuffer {}; + + // semaphores per command buffer + std::vector< vk::Semaphore > mSignalSemaphores {}; + std::vector< vk::Semaphore > mWaitSemaphores {}; + std::vector< vk::PipelineStageFlags > mWaitStages {}; + + std::vector< Handle> mResources; // used resources + + PipelineRef mCurrentPipeline; + + vk::RenderPass mCurrentRenderPass; + + bool mRecording { false }; +}; + +/** + * + * Class: CommandBuffer + * + */ + +CommandBuffer::CommandBuffer( CommandPool& commandPool, const vk::CommandBufferAllocateInfo& allocateInfo, vk::CommandBuffer vkCommandBuffer ) { - assert(allocateInfo.commandBufferCount == 1 && "Number of buffers to allocate must be equal 1!"); - mCommandBuffer = VkAssert(mGraphics.GetDevice().allocateCommandBuffers(allocateInfo))[0]; + mImpl = MakeUnique( commandPool, allocateInfo, vkCommandBuffer ); } CommandBuffer::~CommandBuffer() { - if(mCommandBuffer) - { - mGraphics.GetDevice().freeCommandBuffers(mCommandPool.GetPool(), mCommandBuffer); - } } /** Begin recording */ void CommandBuffer::Begin(vk::CommandBufferUsageFlags usageFlags, vk::CommandBufferInheritanceInfo* inheritanceInfo) { - assert(!mRecording && "CommandBuffer already is in the recording state"); - auto info = vk::CommandBufferBeginInfo{}; - info.setPInheritanceInfo(inheritanceInfo); - info.setFlags(usageFlags); - VkAssert(mCommandBuffer.begin(info)); - mRecording = true; + mImpl->Begin( usageFlags, inheritanceInfo ); } /** Finish recording */ void CommandBuffer::End() { - assert(mRecording && "CommandBuffer is not in the recording state!"); - VkAssert(mCommandBuffer.end()); - mRecording = false; + mImpl->End(); } /** Reset command buffer */ void CommandBuffer::Reset() { - assert(!mRecording && "Can't reset command buffer during recording!"); - assert(mCommandBuffer && "Invalid command buffer!"); - mCommandBuffer.reset(vk::CommandBufferResetFlagBits::eReleaseResources); + mImpl->Reset(); } /** Free command buffer */ void CommandBuffer::Free() { - assert(mCommandBuffer && "Invalid command buffer!"); - mGraphics.GetDevice().freeCommandBuffers(mCommandPool.GetPool(), mCommandBuffer); + mImpl->Free(); } /** Records image layout transition barrier for one image */ @@ -89,119 +415,115 @@ void CommandBuffer::ImageLayoutTransition(vk::Image image, vk::ImageLayout newLayout, vk::ImageAspectFlags aspectMask) { - // must be in recording state - - // just push new image barrier until any command is being called or buffer recording ends. - // it will make sure we batch barriers together rather than calling cmdPipelineBarrier - // for each separately - vk::AccessFlags srcAccessMask, dstAccessMask; - vk::PipelineStageFlags srcStageMask, dstStageMask; - - // TODO: add other transitions - switch(oldLayout) - { - case vk::ImageLayout::eUndefined: - { - srcStageMask = vk::PipelineStageFlagBits::eTopOfPipe; - } - break; - case vk::ImageLayout::ePresentSrcKHR: - { - srcStageMask = vk::PipelineStageFlagBits::eBottomOfPipe; - srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead; - } - break; - case vk::ImageLayout::eColorAttachmentOptimal: - { - srcStageMask = vk::PipelineStageFlagBits::eFragmentShader | vk::PipelineStageFlagBits::eColorAttachmentOutput; - srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead; - } - break; - case vk::ImageLayout::eGeneral: - case vk::ImageLayout::eDepthStencilAttachmentOptimal: - case vk::ImageLayout::eDepthStencilReadOnlyOptimal: - case vk::ImageLayout::eShaderReadOnlyOptimal: - case vk::ImageLayout::eTransferSrcOptimal: - case vk::ImageLayout::eTransferDstOptimal: - case vk::ImageLayout::ePreinitialized: - case vk::ImageLayout::eSharedPresentKHR: - { - } - } - - switch(newLayout) - { - case vk::ImageLayout::eColorAttachmentOptimal: - { - dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eFragmentShader; - dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eHostWrite; - break; - } - case vk::ImageLayout::eDepthStencilAttachmentOptimal: - { - dstStageMask = vk::PipelineStageFlagBits::eFragmentShader | vk::PipelineStageFlagBits::eEarlyFragmentTests; - dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite; - break; - } - case vk::ImageLayout::ePresentSrcKHR: - { - dstStageMask = vk::PipelineStageFlagBits::eBottomOfPipe; - dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eMemoryRead; - } - case vk::ImageLayout::eGeneral: - case vk::ImageLayout::eDepthStencilReadOnlyOptimal: - case vk::ImageLayout::eShaderReadOnlyOptimal: - case vk::ImageLayout::eTransferSrcOptimal: - case vk::ImageLayout::eTransferDstOptimal: - case vk::ImageLayout::ePreinitialized: - case vk::ImageLayout::eUndefined: - case vk::ImageLayout::eSharedPresentKHR: - default: - { - } - } - - RecordImageLayoutTransition(image, srcAccessMask, dstAccessMask, srcStageMask, dstStageMask, - oldLayout, newLayout, aspectMask); + mImpl->ImageLayoutTransition( image, oldLayout, newLayout, aspectMask ); } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wframe-larger-than=" void CommandBuffer::RecordImageLayoutTransition(vk::Image image, vk::AccessFlags srcAccessMask, vk::AccessFlags dstAccessMask, vk::PipelineStageFlags srcStageMask, vk::PipelineStageFlags dstStageMask, vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageAspectFlags aspectMask) { - vk::ImageSubresourceRange subres; - subres.setLayerCount(1).setBaseMipLevel(0).setBaseArrayLayer(0).setLevelCount(1).setAspectMask(aspectMask); - - - auto barrier = vk::ImageMemoryBarrier{}; - barrier - .setImage(image) - .setSubresourceRange(subres) - .setSrcAccessMask(srcAccessMask) - .setDstAccessMask(dstAccessMask) - .setOldLayout(oldLayout) - .setNewLayout(newLayout); - ; - // todo: implement barriers batching - mCommandBuffer.pipelineBarrier(srcStageMask, dstStageMask, vk::DependencyFlags{}, nullptr, nullptr, barrier); + mImpl->RecordImageLayoutTransition( image, srcAccessMask, dstAccessMask,srcStageMask, dstStageMask, oldLayout, newLayout, aspectMask ); } -#pragma GCC diagnostic pop /** Push wait semaphores */ void CommandBuffer::PushWaitSemaphores(const std::vector< vk::Semaphore >& semaphores, const std::vector< vk::PipelineStageFlags >& stages) { - mWaitSemaphores = semaphores; - mWaitStages = stages; + mImpl->PushWaitSemaphores( semaphores, stages ); } /** Push signal semaphores */ void CommandBuffer::PushSignalSemaphores(const std::vector< vk::Semaphore >& semaphores) { - mSignalSemaphores = semaphores; + mImpl->PushSignalSemaphores( semaphores ); +} + +const std::vector< vk::Semaphore >& CommandBuffer::GetSignalSemaphores() const +{ + return mImpl->mSignalSemaphores; +} + +const std::vector< vk::Semaphore >& CommandBuffer::GetSWaitSemaphores() const +{ + return mImpl->mWaitSemaphores; +} + +const std::vector< vk::PipelineStageFlags >& CommandBuffer::GetWaitSemaphoreStages() const +{ + return mImpl->mWaitStages; +} + +vk::CommandBuffer CommandBuffer::GetVkCommandBuffer() const +{ + return mImpl->mCommandBuffer; +} + +bool CommandBuffer::IsPrimary() const +{ + return mImpl->mAllocateInfo.level == vk::CommandBufferLevel::ePrimary; +} + +void CommandBuffer::BindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount, std::vector> buffers, + const vk::DeviceSize *pOffsets) +{ + mImpl->BindVertexBuffers( firstBinding, bindingCount, buffers, pOffsets ); +} + +void CommandBuffer::BindIndexBuffer( BufferRef buffer, uint32_t offset, vk::IndexType indexType) +{ + mImpl->BindIndexBuffer( buffer, offset, indexType ); +} + +void CommandBuffer::BindVertexBuffer(uint32_t binding, Dali::Graphics::Vulkan::Handle buffer, vk::DeviceSize offset ) +{ + mImpl->BindVertexBuffers( binding, 1, std::vector>({ buffer }), &offset ); +} + +void CommandBuffer::BindGraphicsPipeline( Handle pipeline ) +{ + mImpl->BindGraphicsPipeline( pipeline ); +} + +void CommandBuffer::BindDescriptorSets( std::vector> descriptorSets, + Handle pipeline, uint32_t firstSet, uint32_t descriptorSetCount ) +{ + mImpl->BindDescriptorSets( descriptorSets, pipeline, firstSet, descriptorSetCount ); +} + +void CommandBuffer::BindDescriptorSets( std::vector> descriptorSets, uint32_t firstSet ) +{ + mImpl->BindDescriptorSets( descriptorSets, mImpl->mCurrentPipeline, 0, static_cast(descriptorSets.size()) ); +} + +void CommandBuffer::Draw( uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance ) +{ + mImpl->Draw( vertexCount, instanceCount, firstVertex, firstInstance ); +} + +void CommandBuffer::DrawIndexed( uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, uint32_t vertexOffset, uint32_t firstInstance ) +{ + mImpl->DrawIndexed( indexCount, instanceCount, firstIndex, vertexOffset, firstInstance ); +} + +void CommandBuffer::BeginRenderPass( FBID framebufferId, uint32_t bufferIndex ) +{ + mImpl->BeginRenderPass( framebufferId, bufferIndex ); +} + +void CommandBuffer::BeginRenderPass( vk::RenderPassBeginInfo renderPassBeginInfo, vk::SubpassContents subpassContents ) +{ + mImpl->BeginRenderPass( renderPassBeginInfo, subpassContents ); +} + +void CommandBuffer::EndRenderPass() +{ + mImpl->EndRenderPass(); +} + +void CommandBuffer::ExecuteCommands( std::vector> commandBuffers ) +{ + mImpl->ExecuteCommands( commandBuffers ); } } // namespace Vulkan diff --git a/dali/graphics/vulkan/vulkan-command-buffer.h b/dali/graphics/vulkan/vulkan-command-buffer.h index 3fb0675..2dab9f7 100644 --- a/dali/graphics/vulkan/vulkan-command-buffer.h +++ b/dali/graphics/vulkan/vulkan-command-buffer.h @@ -27,19 +27,20 @@ namespace Graphics { namespace Vulkan { - +class Image; class Graphics; -class CommandPool; -class CommandBuffer +class Buffer; +class Pipeline; +class DescriptorSet; +class CommandBuffer : public VkManaged { + friend class CommandPool; + public: - CommandBuffer() = delete; - CommandBuffer(Graphics& graphics, CommandPool& ownerPool, vk::CommandBuffer commandBuffer); - CommandBuffer(Graphics& graphics, CommandPool& ownerPool, const vk::CommandBufferAllocateInfo& allocateInfo); - CommandBuffer(Graphics& graphics, CommandPool& ownerPool); + CommandBuffer() = delete; - ~CommandBuffer(); + ~CommandBuffer() override; /** Begin recording */ void Begin(vk::CommandBufferUsageFlags usageFlags = vk::CommandBufferUsageFlags{}, @@ -64,28 +65,146 @@ public: /** Push signal semaphores */ void PushSignalSemaphores(const std::vector< vk::Semaphore >& semaphores); - const std::vector< vk::Semaphore >& GetSignalSemaphores() const - { - return mSignalSemaphores; - } + /** + * + * @return + */ + const std::vector< vk::Semaphore >& GetSignalSemaphores() const; - const std::vector< vk::Semaphore >& GetSWaitSemaphores() const - { - return mWaitSemaphores; - } + /** + * + * @return + */ + const std::vector< vk::Semaphore >& GetSWaitSemaphores() const; - const std::vector< vk::PipelineStageFlags >& GetWaitSemaphoreStages() const - { - return mWaitStages; - } + /** + * + * @return + */ + const std::vector< vk::PipelineStageFlags >& GetWaitSemaphoreStages() const; /** Returns Vulkan object associated with the buffer */ - inline const vk::CommandBuffer& Get() const + vk::CommandBuffer GetVkCommandBuffer() const; + + operator vk::CommandBuffer() const { - return mCommandBuffer; + return GetVkCommandBuffer(); } + /** + * Tests if the command buffer is primary + * @return Returns true if the command buffer is primary + */ + bool IsPrimary() const; + + /** + * Binds an array of vertex buffers + * @param firstBinding + * @param bindingCount + * @param buffers + * @param pOffsets + */ + void BindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount, + std::vector> buffers, + const vk::DeviceSize *pOffsets); + + /** + * Binds an index buffer + * @param buffer + * @param offset + * @param indexType + */ + void BindIndexBuffer( BufferRef buffer, uint32_t offset, vk::IndexType indexType); + + /** + * Binds single vertex buffer + * @param binding + * @param buffer + * @param offset + */ + void BindVertexBuffer(uint32_t binding, Dali::Graphics::Vulkan::Handle buffer, vk::DeviceSize offset ); + + /** + * Binds graphics pipeline + * @param pipeline + */ + void BindGraphicsPipeline( Handle pipeline ); + + /** + * + * @param descriptorSets + * @param pipeline + * @param firstSet + * @param descriptorSetCount + */ + void BindDescriptorSets( std::vector> descriptorSets, + Handle pipeline, uint32_t firstSet, uint32_t descriptorSetCount ); + + /** + * Binds descriptor sets to the most recently bound Pipeline + * @param descriptorSets + * @param firstSet + */ + void BindDescriptorSets( std::vector> descriptorSets, uint32_t firstSet ); + + /** + * Issues draw command + * @param vertexCount + * @param instanceCount + * @param firstVertex + * @param firstInstance + */ + void Draw( uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance ); + + /** + * Issues draw indexed primiteve command + * @param indexCount + * @param instanceCount + * @param firstIndex + * @param vertexOffset + * @param firstInstance + */ + void DrawIndexed( uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, uint32_t vertexOffset, uint32_t firstInstance ); + + /** + * Begins render pass using VkRenderPass and VkFramebuffer associated with FBID + * @todo should be replaced with proper implementation and use the framebuffer + * @param framebufferId + * @param bufferIndex + */ + void BeginRenderPass( FBID framebufferId, uint32_t bufferIndex ); + + /** + * Allows to issue custom VkRenderPassBeginInfo structure + * @param renderPassBeginInfo + * @param subpassContents + */ + void BeginRenderPass( vk::RenderPassBeginInfo renderPassBeginInfo, vk::SubpassContents subpassContents ); + + /** + * Ends current render pass + */ + void EndRenderPass(); + + /** + * Executes secondary command buffers within primary command buffer + * @param commandBuffers + */ + void ExecuteCommands( std::vector> commandBuffers ); + private: + + /** + * + * @param image + * @param srcAccessMask + * @param dstAccessMask + * @param srcStageMask + * @param dstStageMask + * @param oldLayout + * @param newLayout + * @param aspectMask + */ void RecordImageLayoutTransition(vk::Image image, vk::AccessFlags srcAccessMask, vk::AccessFlags dstAccessMask, @@ -96,18 +215,13 @@ private: vk::ImageAspectFlags aspectMask); private: - Graphics& mGraphics; - - CommandPool& mCommandPool; - // semaphores per command buffer - std::vector< vk::Semaphore > mSignalSemaphores; - std::vector< vk::Semaphore > mWaitSemaphores; - std::vector< vk::PipelineStageFlags > mWaitStages; + // Constructor called by the CommandPool only + CommandBuffer( CommandPool& commandPool, const vk::CommandBufferAllocateInfo& allocateInfo, vk::CommandBuffer vkCommandBuffer ); - vk::CommandBuffer mCommandBuffer; + class Impl; + std::unique_ptr mImpl; - bool mRecording; }; } // namespace Vulkan diff --git a/dali/graphics/vulkan/vulkan-command-pool.cpp b/dali/graphics/vulkan/vulkan-command-pool.cpp index dec4825..7b5de98 100644 --- a/dali/graphics/vulkan/vulkan-command-pool.cpp +++ b/dali/graphics/vulkan/vulkan-command-pool.cpp @@ -16,9 +16,9 @@ */ // INTERNAL INCLUDES +#include #include #include -#include namespace Dali { @@ -27,41 +27,111 @@ namespace Graphics namespace Vulkan { -CommandPool::CommandPool(Graphics& graphics, const vk::CommandPoolCreateInfo& createInfo) -: mGraphics(graphics) +/** + * + * Class: CommandPool::Impl + */ + +struct CommandPool::Impl { - mPool = VkAssert(graphics.GetDevice().createCommandPool(createInfo, graphics.GetAllocator())); -} + Impl( Graphics& graphics, CommandPool& interface, const vk::CommandPoolCreateInfo& createInfo ) + : mGraphics( graphics ), + mInterface( interface ), + mCreateInfo( createInfo ), + mCommandPool( nullptr ) + { + } + + ~Impl() + { + if(mCommandPool) + { + mGraphics.GetDevice().destroyCommandPool( mCommandPool, mGraphics.GetAllocator()); + } + } + + bool Initialise() + { + mCommandPool = VkAssert(mGraphics.GetDevice().createCommandPool(mCreateInfo, mGraphics.GetAllocator())); + return true; + } + + Handle NewCommandBuffer( const vk::CommandBufferAllocateInfo& allocateInfo ) + { + vk::CommandBufferAllocateInfo info( allocateInfo ); + info.setCommandPool( mCommandPool ); + info.setCommandBufferCount(1); + auto retval = VkAssert( mGraphics.GetDevice().allocateCommandBuffers( info ) ); + mAllocatedCommandBuffers.emplace_back( new CommandBuffer( mInterface, info, retval[0]) ); + return mAllocatedCommandBuffers.back(); + } + + Graphics& mGraphics; + CommandPool& mInterface; + vk::CommandPoolCreateInfo mCreateInfo; + vk::CommandPool mCommandPool; + + std::vector> mAllocatedCommandBuffers; +}; -CommandPool::~CommandPool() +/** + * + * Class: CommandPool + */ +CommandPoolHandle CommandPool::New( Graphics& graphics, const vk::CommandPoolCreateInfo& createInfo ) { - if(mPool) + auto retval = Handle( new CommandPool(graphics, createInfo) ); + + if(retval && retval->mImpl->Initialise()) { - mGraphics.GetDevice().destroyCommandPool(mPool, mGraphics.GetAllocator()); + graphics.AddCommandPool( retval ); } + + return retval; } -std::unique_ptr< CommandBuffer > CommandPool::AllocateCommandBuffer( - const vk::CommandBufferAllocateInfo& info) +CommandPoolHandle CommandPool::New( Graphics& graphics ) { - auto copyInfo = info; - copyInfo.setCommandPool(mPool); - return MakeUnique(mGraphics, *this, copyInfo); + return New( graphics, vk::CommandPoolCreateInfo{}); } -std::unique_ptr< CommandBuffer > CommandPool::AllocateCommandBuffer(vk::CommandBufferLevel level) +CommandPool::CommandPool() = default; + +CommandPool::CommandPool(Graphics& graphics, const vk::CommandPoolCreateInfo& createInfo) { - auto info = - vk::CommandBufferAllocateInfo{}.setCommandBufferCount(1).setLevel(level).setCommandPool( - mPool); - return MakeUnique(mGraphics, *this, info); + mImpl = MakeUnique( graphics, *this, createInfo ); } +CommandPool::~CommandPool() = default; + vk::CommandPool CommandPool::GetPool() const { - return mPool; + return mImpl->mCommandPool; +} + +Graphics& CommandPool::GetGraphics() const +{ + return mImpl->mGraphics; } +bool CommandPool::OnDestroy() +{ + return false; +} + +Handle CommandPool::NewCommandBuffer( const vk::CommandBufferAllocateInfo& allocateInfo ) +{ + return mImpl->NewCommandBuffer( allocateInfo ); +} + +Handle CommandPool::NewCommandBuffer( bool isPrimary ) +{ + return mImpl->NewCommandBuffer( vk::CommandBufferAllocateInfo{}.setLevel( + isPrimary ? vk::CommandBufferLevel::ePrimary : vk::CommandBufferLevel::eSecondary + ) ); +} + + } // namespace Vulkan } // namespace Graphics } // namespace Dali diff --git a/dali/graphics/vulkan/vulkan-command-pool.h b/dali/graphics/vulkan/vulkan-command-pool.h index 3b227db..e04ec44 100644 --- a/dali/graphics/vulkan/vulkan-command-pool.h +++ b/dali/graphics/vulkan/vulkan-command-pool.h @@ -1,5 +1,5 @@ -#ifndef DALI_GRAPHICS_VULKAN_COMMANDPOOL_H -#define DALI_GRAPHICS_VULKAN_COMMANDPOOL_H +#ifndef DALI_GRAPHICS_VULKAN_COMMANDPOOL +#define DALI_GRAPHICS_VULKAN_COMMANDPOOL /* * Copyright (c) 2017 Samsung Electronics Co., Ltd. @@ -30,26 +30,75 @@ namespace Vulkan class Graphics; class CommandBuffer; -class CommandPool + +using CommandPoolHandle = Handle; + +class CommandPool : public VkManaged { + public: - CommandPool( Graphics& graphics, const vk::CommandPoolCreateInfo& createInfo ); - ~CommandPool(); + /** + * + * @param graphics + * @param createInfo + * @return + */ + static CommandPoolHandle New( Graphics& graphics, const vk::CommandPoolCreateInfo& createInfo ); - std::unique_ptr AllocateCommandBuffer( const vk::CommandBufferAllocateInfo& info ); + /** + * + * @param graphics + * @return + */ + static CommandPoolHandle New( Graphics& graphics ); - std::unique_ptr AllocateCommandBuffer( vk::CommandBufferLevel level ); + ~CommandPool() override; + /** + * + * @return + */ vk::CommandPool GetPool() const; + /** + * + * @return + */ + Graphics& GetGraphics() const; + + /** + * + * @param allocateInfo + * @return + */ + Handle NewCommandBuffer( const vk::CommandBufferAllocateInfo& allocateInfo ); + + /** + * + * @param isPrimary + * @return + */ + Handle NewCommandBuffer( bool isPrimary = true ); + +public: + + bool OnDestroy() override; + private: - Graphics& mGraphics; - vk::CommandPool mPool; + + CommandPool(); + + CommandPool( Graphics& graphics, const vk::CommandPoolCreateInfo& createInfo ); + + class Impl; + std::unique_ptr mImpl; + }; + } // namespace Vulkan } // namespace Graphics } // namespace Dali -#endif // DALI_GRAPHICS_VULKAN_COMMANDPOOL_H +#endif // DALI_GRAPHICS_VULKAN_COMMANDPOOL diff --git a/dali/graphics/vulkan/vulkan-descriptor-set.cpp b/dali/graphics/vulkan/vulkan-descriptor-set.cpp new file mode 100644 index 0000000..65a56f9 --- /dev/null +++ b/dali/graphics/vulkan/vulkan-descriptor-set.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ +struct DescriptorPool::Impl +{ + Impl( DescriptorPool& owner, Graphics& graphics, vk::DescriptorPoolCreateInfo createInfo ) + : mGraphics( graphics ), + mOwner( owner ), + mCreateInfo( createInfo ) + { + + } + + ~Impl() + { + + } + + /** + * Allocates an array of descriptor sets + * @param allocateInfo + * @return + */ + std::vector> AllocateDescriptorSets( vk::DescriptorSetAllocateInfo allocateInfo ) + { + // all other fields must be set correct + allocateInfo.setDescriptorPool( mVkDescriptorPool ); + auto result = VkAssert( mGraphics.GetDevice().allocateDescriptorSets( allocateInfo ) ); + + std::vector> retval; + retval.reserve( result.size() ); + for( auto&& item : result ) + { + Handle handle( new DescriptorSet(mGraphics, mOwner, item, allocateInfo) ); + retval.emplace_back( handle ); + mDescriptorSetCache.emplace_back( handle ); + } + + return retval; + } + + bool Initialise() + { + mVkDescriptorPool = VkAssert( mGraphics.GetDevice().createDescriptorPool( mCreateInfo, mGraphics.GetAllocator() ) ); + return true; + } + + Graphics& mGraphics; + DescriptorPool& mOwner; + vk::DescriptorPoolCreateInfo mCreateInfo; + + vk::DescriptorPool mVkDescriptorPool; + + // cache + std::vector> mDescriptorSetCache; +}; + +Handle DescriptorPool::New( Graphics& graphics, const vk::DescriptorPoolCreateInfo& createInfo ) +{ + auto pool = Handle( new DescriptorPool( graphics, createInfo ) ); + if(pool->mImpl->Initialise()) + { + graphics.AddDescriptorPool(pool); + } + return pool; +} + +DescriptorPool::DescriptorPool( Graphics& graphics, const vk::DescriptorPoolCreateInfo& createInfo ) +{ + mImpl = MakeUnique( *this, graphics, createInfo ); +} + +DescriptorPool::~DescriptorPool() = default; + +vk::DescriptorPool DescriptorPool::GetVkDescriptorPool() const +{ + return mImpl->mVkDescriptorPool; +} + +std::vector DescriptorPool::AllocateDescriptorSets( vk::DescriptorSetAllocateInfo allocateInfo ) +{ + return mImpl->AllocateDescriptorSets( allocateInfo ); +} + +/**************************************************************************************** + * Class DescriptorSet::Impl + */ + +struct DescriptorSet::Impl +{ + Impl( Graphics& graphics, DescriptorPool& pool, vk::DescriptorSet set, vk::DescriptorSetAllocateInfo allocateInfo ) + : mGraphics( graphics ), + mPool( pool ), + mAllocateInfo( allocateInfo ), + mVkDescriptorSet( set ) + { + + } + + ~Impl() + { + if(mVkDescriptorSet) + { + mGraphics.GetDevice().freeDescriptorSets( mPool.GetVkDescriptorPool(), 1, &mVkDescriptorSet ); + } + } + + void WriteUniformBuffer( uint32_t binding, Handle buffer, uint32_t offset, uint32_t size ) + { + // add resource to the list + mResources.emplace_back( buffer.StaticCast() ); + + auto bufferInfo = vk::DescriptorBufferInfo{} + .setOffset( U32(offset) ) + .setRange( U32(size) ) + .setBuffer( buffer->GetVkBuffer() ); + + auto write = vk::WriteDescriptorSet{}.setPBufferInfo( &bufferInfo ) + .setDescriptorType( vk::DescriptorType::eUniformBuffer ) + .setDescriptorCount( 1 ) + .setDstSet( mVkDescriptorSet ) + .setDstBinding( binding ) + .setDstArrayElement( 0 ); + + // write descriptor set + mGraphics.GetDevice().updateDescriptorSets( 1, &write, 0, nullptr ); + } + + void WriteStorageBuffer( Handle buffer, uint32_t offset, uint32_t size ) + { + mResources.emplace_back( buffer.StaticCast() ); + } + + Graphics& mGraphics; + DescriptorPool& mPool; + vk::DescriptorSetAllocateInfo mAllocateInfo; + vk::DescriptorSet mVkDescriptorSet; + + // attached resources + std::vector> mResources; +}; + +/** + * Called by DescriptorPool only! + */ +DescriptorSet::DescriptorSet( Graphics& graphics, DescriptorPool& pool, vk::DescriptorSet descriptorSet, vk::DescriptorSetAllocateInfo allocateInfo ) +{ + mImpl = MakeUnique( graphics, pool, descriptorSet, allocateInfo ); +} + +DescriptorSet::~DescriptorSet() = default; + +void DescriptorSet::WriteUniformBuffer( uint32_t binding, Handle buffer, uint32_t offset, uint32_t size ) +{ + mImpl->WriteUniformBuffer( binding, buffer, offset, size ); +} + +vk::DescriptorSet DescriptorSet::GetVkDescriptorSet() const +{ + return mImpl->mVkDescriptorSet; +} + + + + + + + + + + + + + + + + + + + +struct DescriptorSetLayout::Impl +{ + Impl( Graphics& graphics, const vk::DescriptorSetLayoutCreateInfo& createInfo ) : + mGraphics( graphics ), + mCreateInfo( createInfo ) + { + } + + ~Impl() + { + if(mLayout) + { + mGraphics.GetDevice().destroyDescriptorSetLayout( mLayout, mGraphics.GetAllocator() ); + } + } + + bool Initialise() + { + mLayout = VkAssert( mGraphics.GetDevice().createDescriptorSetLayout( mCreateInfo, mGraphics.GetAllocator() )); + if(mLayout) + { + return true; + } + return false; + } + + Graphics& mGraphics; + vk::DescriptorSetLayout mLayout; + vk::DescriptorSetLayoutCreateInfo mCreateInfo; +}; + +/** + * Class: DescriptorSetLayout + */ + +std::unique_ptr DescriptorSetLayout::New( Graphics& graphics, const vk::DescriptorSetLayoutCreateInfo& createInfo ) +{ + auto retval = std::unique_ptr( new DescriptorSetLayout(graphics, createInfo ) ); + if( retval->mImpl->Initialise() ) + { + return retval; + } + return nullptr; +} + +DescriptorSetLayout::DescriptorSetLayout( Graphics& graphics, const vk::DescriptorSetLayoutCreateInfo& createInfo ) +{ + mImpl = MakeUnique( graphics, createInfo ); +} + +} // Namespace Vulkan + +} // Namespace Graphics + +} // Namespace Dali diff --git a/dali/graphics/vulkan/vulkan-descriptor-set.h b/dali/graphics/vulkan/vulkan-descriptor-set.h new file mode 100644 index 0000000..e2d48e9 --- /dev/null +++ b/dali/graphics/vulkan/vulkan-descriptor-set.h @@ -0,0 +1,128 @@ +#ifndef DALI_GRAPHICS_VULKAN_DESCRIPTOR_SET +#define DALI_GRAPHICS_VULKAN_DESCRIPTOR_SET + +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ +class Graphics; +class Buffer; +class Image; +class DescriptorPool; + +class DescriptorSet : public VkManaged +{ + friend class DescriptorPool; + +public: + + ~DescriptorSet() override; + + /** + * + * @param buffer + * @param offset + * @param size + */ + void WriteUniformBuffer( uint32_t binding, Handle buffer, uint32_t offset, uint32_t size ); + + /** + * + * @param buffer + * @param offset + * @param size + */ + void WriteStorageBuffer( Handle buffer, uint32_t offset, uint32_t size ); + + /** + * + */ + void WriteImage( Handle ); + + /** + * + * @param writeDescriptorSet + */ + void Write( vk::WriteDescriptorSet writeDescriptorSet ); + + /** + * Returns VkDescriptorSet associated with this object + * @return Descriptor set + */ + vk::DescriptorSet GetVkDescriptorSet() const; + +private: + + DescriptorSet( Graphics& graphics, DescriptorPool& pool, vk::DescriptorSet descriptorSet, vk::DescriptorSetAllocateInfo allocateInfo ); + + class Impl; + std::unique_ptr mImpl; +}; + +using DescriptorSetHandle = Handle; + +class DescriptorPool : public VkManaged +{ +public: + + static Handle New( Graphics& graphics, const vk::DescriptorPoolCreateInfo& createInfo ); + + ~DescriptorPool() override; + + vk::DescriptorPool GetVkDescriptorPool() const; + + std::vector AllocateDescriptorSets( vk::DescriptorSetAllocateInfo allocateInfo ); + +private: + + DescriptorPool( Graphics& graphics, const vk::DescriptorPoolCreateInfo& createInfo ); + + class Impl; + std::unique_ptr mImpl; +}; + + +class DescriptorSetLayout +{ +public: + + static std::unique_ptr New( Graphics& graphics, const vk::DescriptorSetLayoutCreateInfo& createInfo ); + +private: + + DescriptorSetLayout( Graphics& graphics, const vk::DescriptorSetLayoutCreateInfo& createInfo ); + +private: + + class Impl; + std::unique_ptr mImpl; +}; + +} // Namespace Vulkan + +} // Namespace Graphics + +} // Namespace Dali + +#endif // DALI_GRAPHICS_VULKAN_DESCRIPTOR_SET diff --git a/dali/graphics/vulkan/vulkan-device-memory-manager.cpp b/dali/graphics/vulkan/vulkan-device-memory-manager.cpp deleted file mode 100644 index 93f7cb9..0000000 --- a/dali/graphics/vulkan/vulkan-device-memory-manager.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include -#include - -namespace Dali -{ -namespace Graphics -{ -namespace Vulkan -{ - -namespace -{ - -const uint32_t INVALID_MEMORY_INDEX = -1u; - -/** - * Helper function which returns GPU heap index that can be used to allocate - * particular type of resource - */ -uint32_t GetMemoryIndex(const vk::PhysicalDeviceMemoryProperties &memoryProperties, - uint32_t memoryTypeBits, vk::MemoryPropertyFlags properties) -{ - for(uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) - { - if((memoryTypeBits & (1u << i)) && - ((memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)) - { - return i; - } - } - return INVALID_MEMORY_INDEX; -} -} - -/* - * DeviceMemory - */ - -DeviceMemory::DeviceMemory(DeviceMemoryManager &manager, Graphics &graphics, - const vk::MemoryRequirements &requirements, - vk::MemoryPropertyFlags properties) -: mManager(manager), - mGraphics(graphics), - mDeviceMemory{nullptr}, - mProperties{properties}, - mRequirements(requirements), - mUserCount{0u} -{ - auto info = vk::MemoryAllocateInfo{}; - info.setAllocationSize(requirements.size) - .setMemoryTypeIndex( - GetMemoryIndex(mGraphics.GetMemoryProperties(), requirements.memoryTypeBits, properties)); - - mDeviceMemory = VkAssert(mGraphics.GetDevice().allocateMemory(info)); -} - -void *DeviceMemory::Map(uint32_t offset, uint32_t size) -{ - return nullptr; -} - -void DeviceMemory::Unmap() -{ -} - -void DeviceMemory::Bind(Image &image, uint32_t offset) -{ - assert(image.GetImage() && "Image is nullptr!"); - VkAssert(mGraphics.GetDevice().bindImageMemory(image.GetImage(), mDeviceMemory, offset)); - ++mUserCount; -} - -void DeviceMemory::Bind(Buffer &image, uint32_t offset) -{ -} - -/* - * DeviceMemoryManager - */ - -DeviceMemoryManager::DeviceMemoryManager(Graphics &graphics) : mGraphics(graphics) -{ -} - -std::unique_ptr< DeviceMemory > DeviceMemoryManager::Allocate(vk::MemoryRequirements requirements, - vk::MemoryPropertyFlags flags) -{ - return MakeUnique< DeviceMemory >(*this, mGraphics, requirements, flags); -} - -} // namespace Vulkan -} // namespace Graphics -} // namespace Dali diff --git a/dali/graphics/vulkan/vulkan-device-memory-manager.h b/dali/graphics/vulkan/vulkan-device-memory-manager.h deleted file mode 100644 index cf183f0..0000000 --- a/dali/graphics/vulkan/vulkan-device-memory-manager.h +++ /dev/null @@ -1,89 +0,0 @@ -// -// Created by adam.b on 06/06/17. -// - -#ifndef VULKAN_PROJECT_DEVICEMEMORYMANAGER_H -#define VULKAN_PROJECT_DEVICEMEMORYMANAGER_H - -#include - -namespace Dali -{ -namespace Graphics -{ -namespace Vulkan -{ - -class Graphics; -class Image; -class Buffer; -class DeviceMemoryManager; - -/** - * DeviceMemory represents continuous memory block with particular properties - * like being mappable etc. The actual memory is being allocated from DeviceMemory, - * however simplest use may assume use of whole DeviceMemory block for a single - * resource/ - */ -class DeviceMemory -{ -public: - DeviceMemory(DeviceMemoryManager& manager, Graphics& graphics, - const vk::MemoryRequirements& requirements, vk::MemoryPropertyFlags properties); - - void* Map(uint32_t offset, uint32_t size); - - void Unmap(); - - void Bind( Image& image, uint32_t offset ); - void Bind( Buffer& image, uint32_t offset ); - -private: - DeviceMemoryManager& mManager; - Graphics& mGraphics; - - vk::DeviceMemory mDeviceMemory; - vk::MemoryPropertyFlags mProperties; - vk::MemoryRequirements mRequirements; - - std::atomic< uint32_t > mUserCount; // this is just a refcount -}; - -/** - * DeviceMemoryManager - */ -class DeviceMemoryManager -{ -public: - DeviceMemoryManager() = delete; - DeviceMemoryManager(Graphics& graphics); - ~DeviceMemoryManager() = default; - DeviceMemoryManager(const DeviceMemoryManager&) = delete; - DeviceMemoryManager(DeviceMemoryManager&&) = default; - - DeviceMemoryManager& operator=(const DeviceMemoryManager&) = delete; - DeviceMemoryManager& operator=(DeviceMemoryManager&&) = default; - - /* Allocates memory for VkImage */ - vk::DeviceMemory& Allocate(vk::Image image, vk::MemoryPropertyFlags memoryFlags); - - /* Allocates memory for VkBuffer */ - vk::DeviceMemory& Allocate(vk::Buffer image, vk::MemoryPropertyFlags memoryFlags); - - std::unique_ptr< DeviceMemory > Allocate(vk::MemoryRequirements requirements, - vk::MemoryPropertyFlags flags); - - Graphics& GetGraphics() const - { - return mGraphics; - } - -private: - Graphics& mGraphics; -}; - -} // namespace Vulkan -} // namespace Graphics -} // namespace Dali - -#endif //VULKAN_PROJECT_DEVICEMEMORYMANAGER_H diff --git a/dali/graphics/vulkan/vulkan-fence.cpp b/dali/graphics/vulkan/vulkan-fence.cpp index 74dfa18..772a521 100644 --- a/dali/graphics/vulkan/vulkan-fence.cpp +++ b/dali/graphics/vulkan/vulkan-fence.cpp @@ -26,50 +26,127 @@ namespace Graphics namespace Vulkan { -Fence::Fence(Graphics& graphics) : mGraphics(graphics), mFence(nullptr) +/** + * Class: Fence::Impl + * + */ +struct Fence::Impl { - mFence = - VkAssert(mGraphics.GetDevice().createFence(vk::FenceCreateInfo{}, mGraphics.GetAllocator())); -} + Impl( Vulkan::Graphics& graphics ) + : mGraphics( graphics ) + { + } -Fence::~Fence() -{ - if(mFence) + ~Impl() { - mGraphics.GetDevice().destroyFence(mFence, mGraphics.GetAllocator()); + if( mFence ) + { + mGraphics.GetDevice().destroyFence( mFence, mGraphics.GetAllocator() ); + } } -} -bool Fence::Wait(uint32_t timeout) -{ - if(timeout) + vk::Result Initialise() { - return mGraphics.GetDevice().waitForFences(mFence, true, timeout) == vk::Result::eSuccess; + mFence = VkAssert( mGraphics.GetDevice().createFence( vk::FenceCreateInfo{}, mGraphics.GetAllocator() ) ); + if( mFence ) + return vk::Result::eSuccess; + return vk::Result::eErrorInitializationFailed; } - else + + /** + * + * @param timeout + * @return + */ + bool Wait( uint32_t timeout = 0u ) { - timeout = 16000000; - while(mGraphics.GetDevice().waitForFences(mFence, true, timeout) != vk::Result::eSuccess) + if(mFence) { - // fixme: busy wait, bit ugly + if(timeout) + { + return mGraphics.GetDevice().waitForFences(mFence, true, timeout) == vk::Result::eSuccess; + } + else + { + timeout = 16000000; + while(mGraphics.GetDevice().waitForFences(mFence, true, timeout) != vk::Result::eSuccess) + { + // fixme: busy wait, bit ugly + } + return true; + } } - return true; + return false; } -} -void Fence::Reset() + /** + * + */ + void Reset() + { + if(mFence) + { + mGraphics.GetDevice().resetFences(mFence); + } + } + + vk::Fence GetVkFence() const + { + return mFence; + } + + Vulkan::Graphics& mGraphics; + vk::Fence mFence; +}; + +/** + * Class: Fence + * + */ +Handle Fence::New( Graphics& graphics ) { - if(mFence) + auto retval = Handle( new Fence(graphics) ); + if( vk::Result::eSuccess == retval->mImpl->Initialise() ) { - mGraphics.GetDevice().resetFences(mFence); + return retval; } + return Handle(); +} + +Fence::Fence(Graphics& graphics) +{ + mImpl = MakeUnique(graphics); +} + +const Fence& Fence::ConstRef() const +{ + return *this; +} + +Fence& Fence::Ref() +{ + return *this; +} + +Fence::~Fence() = default; + +bool Fence::Wait(uint32_t timeout) +{ + return mImpl->Wait( timeout ); +} + +void Fence::Reset() +{ + mImpl->Reset(); } vk::Fence Fence::GetFence() const { - return mFence; + return mImpl->GetVkFence(); } + + } // namespace Vulkan } // namespace Graphics } // namespace Dali diff --git a/dali/graphics/vulkan/vulkan-fence.h b/dali/graphics/vulkan/vulkan-fence.h index ea76b6a..db4e6bb 100644 --- a/dali/graphics/vulkan/vulkan-fence.h +++ b/dali/graphics/vulkan/vulkan-fence.h @@ -1,8 +1,8 @@ -#ifndef DALI_GRAPHICS_VULKAN_FENCE_H -#define DALI_GRAPHICS_VULKAN_FENCE_H +#ifndef DALI_GRAPHICS_VULKAN_FENCE +#define DALI_GRAPHICS_VULKAN_FENCE /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,27 +29,47 @@ namespace Vulkan { class Graphics; -class Fence final +class Fence : public VkManaged { public: - Fence( Graphics& graphics ); + static Handle New( Graphics& graphics ); + Fence( Fence&& ) = default; ~Fence(); +private: + + Fence( Graphics& graphics ); + +public: + + const Fence& ConstRef() const; + + Fence& Ref(); + + /** + * + * @param timeout + * @return + */ bool Wait( uint32_t timeout = 0u ); + + /** + * + */ void Reset(); vk::Fence GetFence() const; private: - Graphics& mGraphics; - vk::Fence mFence; + class Impl; + std::unique_ptr mImpl; }; } // namespace Vulkan } // namespace Graphics } // namespace Dali -#endif // DALI_GRAPHICS_VULKAN_FENCE_H +#endif // DALI_GRAPHICS_VULKAN_FENCE diff --git a/dali/graphics/vulkan/vulkan-framebuffer.cpp b/dali/graphics/vulkan/vulkan-framebuffer.cpp new file mode 100644 index 0000000..ecd334a --- /dev/null +++ b/dali/graphics/vulkan/vulkan-framebuffer.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ + +struct Framebuffer::Impl +{ + Impl( Framebuffer& owner, Graphics& graphics, uint32_t width, uint32_t height ) : + mInterface( owner ), + mGraphics( graphics ) + { + + } + + // Framebuffer creation may be deferred + bool Initialise() + { + if(mInitialised) + { + return true; + } + + if(!Validate()) + { + return false; + } + + /* + auto attRef = vk::AttachmentReference{}; + attRef.setLayout(); + attRef.setAttachment(); + + // creating single subpass per framebuffer + auto subpassDesc = vk::SubpassDescription{}; + subpassDesc.setPipelineBindPoint( vk::PipelineBindPoint::eGraphics ); + subpassDesc.setColorAttachmentCount(0); + subpassDesc.setInputAttachmentCount(0); + subpassDesc.setPDepthStencilAttachment(nullptr); + subpassDesc.setPColorAttachments( nullptr ); + subpassDesc.setPInputAttachments( nullptr ); + subpassDesc.setPPreserveAttachments( nullptr ); + subpassDesc.setPResolveAttachments( nullptr ); + + + auto rpInfo = vk::RenderPassCreateInfo{}; + rpInfo.setAttachmentCount( mAttachments.size() ); + //rpInfo.setPAttachments( ) + rpInfo.setDependencyCount( 0 ); + rpInfo.setPDependencies( nullptr ); + rpInfo.setPSubpasses( &subpassDesc ); + rpInfo.setSubpassCount( 1 ); + + auto fbInfo = vk::FramebufferCreateInfo{}; + fbInfo.setWidth( mWidth ); + fbInfo.setHeight( mHeight ); + //fbInfo.setRenderPass( ) + //fbInfo.setAttachmentCount( 0 ); + //fbInfo.setPAttachments( ImageViews ); + */ + mInitialised = true; + } + + + void SetAttachment( Handle image, Framebuffer::AttachmentType type, uint32_t index ) + { + std::vector>& attachments = + type == AttachmentType::COLOR ? mColorAttachments : mDepthStencilAttachments; + + if( attachments.size() <= index ) + { + attachments.resize( index+1 ); + } + attachments[index] = image; + } + + ImageRef GetAttachmentImage( AttachmentType type, uint32_t index ) const + { + return ImageRef(); + } + + ImageViewRef GetAttachmentImageView( AttachmentType type, uint32_t index ) const + { + return ImageViewRef(); + } + + bool Validate() + { + if( mWidth == 0u || mHeight == 0 ) + { + return false; + } + } + + ~Impl() + { + + } + + vk::RenderPass GetVkRenderPass() const + { + return mVkRenderPass; + } + + vk::Framebuffer GetVkFramebuffer() const + { + return mVkFramebuffer; + } + + Framebuffer& mInterface; + Graphics& mGraphics; + + uint32_t mWidth; + uint32_t mHeight; + std::vector> mColorAttachments; + std::vector> mDepthStencilAttachments; + + std::vector mImageViewAttachments; + vk::Framebuffer mVkFramebuffer; + vk::RenderPass mVkRenderPass; + + bool mInitialised { false }; +}; + + +Handle Framebuffer::New( Graphics& graphics, uint32_t width, uint32_t height ) +{ + return FramebufferRef(); +} + +void Framebuffer::SetAttachment( Handle image, Framebuffer::AttachmentType type, uint32_t index ) +{ + mImpl->SetAttachment( image, type, index ); +} + +uint32_t Framebuffer::GetWidth() const +{ + return mImpl->mWidth; +} + +uint32_t Framebuffer::GetHeight() const +{ + return mImpl->mHeight; +} + +Handle Framebuffer::GetAttachmentImage( AttachmentType type, uint32_t index ) const +{ + return mImpl->GetAttachmentImage( type, index ); +} + +Handle Framebuffer::GetAttachmentImageView( AttachmentType type, uint32_t index ) const +{ + return mImpl->GetAttachmentImageView( type, index ); +} + +} // Namespace Vulkan + +} // Namespace Graphics + +} // Namespace Dali diff --git a/dali/graphics/vulkan/vulkan-framebuffer.h b/dali/graphics/vulkan/vulkan-framebuffer.h new file mode 100644 index 0000000..3cb5918 --- /dev/null +++ b/dali/graphics/vulkan/vulkan-framebuffer.h @@ -0,0 +1,76 @@ +#ifndef DALI_GRAPHICS_VULKAN_FRAMEBUFFER +#define DALI_GRAPHICS_VULKAN_FRAMEBUFFER + +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ + +class Image; + +/** + * Framebuffer encapsulates following objects: + * - Images ( attachments ) + * - Framebuffer + * - ImageViews + */ +class Framebuffer : public VkManaged +{ +public: + + enum class AttachmentType + { + COLOR, + DEPTH_STENCIL, + INPUT, + RESOLVE, + PRESERVE + }; + + static Handle New( Graphics& graphics, uint32_t width, uint32_t height ); + + uint32_t GetWidth() const; + + uint32_t GetHeight() const; + + Handle GetAttachmentImage( AttachmentType type, uint32_t index ) const; + + Handle GetAttachmentImageView( AttachmentType type, uint32_t index ) const; + + void SetAttachment( Handle image, Framebuffer::AttachmentType type, uint32_t index ); + +private: + + class Impl; + std::unique_ptr mImpl; + +}; + + +} // Namespace Vulkan + +} // Namespace Graphics + +} // Namespace Dali + +#endif // DALI_GRAPHICS_VULKAN_FRAMEBUFFER diff --git a/dali/graphics/vulkan/vulkan-graphics.cpp b/dali/graphics/vulkan/vulkan-graphics.cpp index 1ad1ff2..ae4b42e 100644 --- a/dali/graphics/vulkan/vulkan-graphics.cpp +++ b/dali/graphics/vulkan/vulkan-graphics.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,16 +21,29 @@ #include #include #include -#include +#include + +#include +#include +#include +#include +#include +#include #ifndef VK_KHR_XLIB_SURFACE_EXTENSION_NAME #define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface" #endif +#ifndef VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME +#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface" +#endif + #ifndef VK_KHR_XCB_SURFACE_EXTENSION_NAME #define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface" #endif +#include + namespace Dali { namespace Graphics @@ -39,36 +52,145 @@ using VkSurfaceFactory = Dali::Integration::Graphics::Vulkan::VkSurfaceFactory; namespace Vulkan { +const auto VALIDATION_LAYERS = std::vector< const char* >{ + + //"VK_LAYER_LUNARG_screenshot", // screenshot + "VK_LAYER_RENDERDOC_Capture", + "VK_LAYER_LUNARG_parameter_validation", // parameter + //"VK_LAYER_LUNARG_vktrace", // vktrace ( requires vktrace connection ) + "VK_LAYER_LUNARG_monitor", // monitor + "VK_LAYER_LUNARG_swapchain", // swapchain + "VK_LAYER_GOOGLE_threading", // threading + "VK_LAYER_LUNARG_api_dump", // api + "VK_LAYER_LUNARG_object_tracker", // objects + "VK_LAYER_LUNARG_core_validation", // core + "VK_LAYER_GOOGLE_unique_objects", // unique objects + "VK_LAYER_LUNARG_standard_validation", // standard +}; + Graphics::Graphics() = default; Graphics::~Graphics() = default; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wframe-larger-than=" + +Platform Graphics::GetDefaultPlatform() const +{ +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + mPlatform = Platform::WAYLAND; +#elif VK_USE_PLATFORM_XCB_KHR + mPlatform = Platform::XCB; +#elif VK_USE_PLATFORM_XLIB_KHR + mPlatform = Platform::XLIB; +#else + return mPlatform; +#endif +} + +std::vector Graphics::PrepareDefaultInstanceExtensions() +{ + auto extensions = vk::enumerateInstanceExtensionProperties(); + + std::string extensionName; + + bool xlibAvailable { false }; + bool xcbAvailable { false }; + bool waylandAvailable { false }; + + for( auto&& ext : extensions.value ) + { + extensionName = ext.extensionName; + if( extensionName == VK_KHR_XCB_SURFACE_EXTENSION_NAME ) + { + xcbAvailable = true; + } + else if( extensionName == VK_KHR_XLIB_SURFACE_EXTENSION_NAME ) + { + xlibAvailable = true; + } + else if( extensionName == VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME ) + { + waylandAvailable = true; + } + } + + std::vector retval; + + // depending on the platform validate extensions + auto platform = GetDefaultPlatform(); + + if( platform != Platform::UNDEFINED ) + { + if (platform == Platform::XCB && xcbAvailable) + { + retval.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); + } + else if (platform == Platform::XLIB && xlibAvailable) + { + retval.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); + } + else if (platform == Platform::WAYLAND && waylandAvailable) + { + retval.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); + } + } + else // try to determine the platform based on available extensions + { + if (xcbAvailable) + { + mPlatform = Platform::XCB; + retval.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); + } + else if (xlibAvailable) + { + mPlatform = Platform::XLIB; + retval.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); + } + else if (waylandAvailable) + { + mPlatform = Platform::WAYLAND; + retval.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); + } + else + { + // can't determine the platform! + mPlatform = Platform::UNDEFINED; + } + } + + // other essential extensions + retval.push_back( VK_KHR_SURFACE_EXTENSION_NAME ); + retval.push_back( VK_EXT_DEBUG_REPORT_EXTENSION_NAME ); + + return retval; +} void Graphics::Create() { - CreateInstance(); + + auto extensions = PrepareDefaultInstanceExtensions(); + + auto layers = vk::enumerateInstanceLayerProperties(); + std::vector validationLayers; + for( auto&& reqLayer : VALIDATION_LAYERS ) + { + for( auto&& prop : layers.value ) + { + //std::cout << prop.layerName << std::endl; + if( std::string(prop.layerName) == reqLayer ) + { + validationLayers.push_back(reqLayer); + } + } + } + + CreateInstance(extensions, validationLayers); PreparePhysicalDevice(); } -void Graphics::CreateInstance() +void Graphics::CreateInstance( const std::vector& extensions, const std::vector& validationLayers ) { auto info = vk::InstanceCreateInfo{}; - auto extensions = - std::vector< const char* >{VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_EXTENSION_NAME, - VK_KHR_XLIB_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME }; - - const auto validationLayers = std::vector< const char* >{ - //"VK_LAYER_LUNARG_screenshot", // screenshot - "VK_LAYER_LUNARG_parameter_validation", // parameter - //"VK_LAYER_LUNARG_vktrace", // vktrace ( requires vktrace connection ) - "VK_LAYER_LUNARG_monitor", // monitor - "VK_LAYER_LUNARG_swapchain", // swapchain - "VK_LAYER_GOOGLE_threading", // threading - "VK_LAYER_LUNARG_api_dump", // api - "VK_LAYER_LUNARG_object_tracker", // objects - "VK_LAYER_LUNARG_core_validation", // core - "VK_LAYER_GOOGLE_unique_objects", // unique objects - "VK_LAYER_LUNARG_standard_validation", // standard - }; info.setEnabledExtensionCount(U32(extensions.size())) .setPpEnabledExtensionNames(extensions.data()) @@ -87,8 +209,7 @@ void Graphics::DestroyInstance() } } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wframe-larger-than=" + void Graphics::PreparePhysicalDevice() { auto devices = VkAssert(mInstance.enumeratePhysicalDevices()); @@ -120,7 +241,7 @@ void Graphics::PreparePhysicalDevice() GetQueueFamilyProperties(); - mDeviceMemoryManager = MakeUnique( *this ); + mDeviceMemoryManager = GpuMemoryManager::New( *this ); } #pragma GCC diagnostic pop @@ -357,17 +478,114 @@ Queue& Graphics::GetPresentQueue() const return *mPresentQueue.get(); } -std::unique_ptr< CommandPool > Graphics::CreateCommandPool(const vk::CommandPoolCreateInfo& info) +Handle< CommandPool > Graphics::CreateCommandPool(const vk::CommandPoolCreateInfo& info) { - auto cmdpool = std::unique_ptr< CommandPool >(new CommandPool(*this, info)); + auto cmdpool = CommandPool::New( *this, vk::CommandPoolCreateInfo{}. + setQueueFamilyIndex( 0u ). + setFlags( vk::CommandPoolCreateFlagBits::eResetCommandBuffer ) ); return cmdpool; } Surface& Graphics::GetSurface( FBID surfaceId ) { + // TODO: FBID == 0 means default framebuffer, but there should be no + // such thing as default framebuffer. + if( surfaceId == 0 ) + { + return *mSurfaceFBIDMap.begin()->second.get(); + } return *mSurfaceFBIDMap[surfaceId].get(); } +// TODO: all this stuff should go into some vulkan cache + +void Graphics::AddBuffer( Handle buffer ) +{ + mBuffersCache.push_back( buffer ); +} + +void Graphics::AddImage( Handle image ) +{ + mImageCache.push_back( image ); +} + +void Graphics::AddPipeline( Handle pipeline ) +{ + mPipelineCache.push_back( pipeline ); +} + +void Graphics::AddShader( Handle shader ) +{ + mShaderCache.push_back( shader ); +} + +void Graphics::AddCommandPool( Handle pool ) +{ + mCommandPoolCache.push_back( pool ); +} + +void Graphics::AddDescriptorPool( Handle pool ) +{ + mDescriptorPoolCache.push_back( pool ); +} + +void Graphics::AddFramebuffer( Handle framebuffer ) +{ + mFramebufferCache.push_back( framebuffer ); +} + +void Graphics::RemoveBuffer( Buffer& buffer ) +{ + auto index = 0u; + for( auto&& iter : mBuffersCache ) + { + if( &*iter == &buffer ) + { + iter.Reset(); + mBuffersCache.erase( mBuffersCache.begin()+index ); + return; + } + } +} + +void Graphics::RemoveShader( Shader& shader ) +{ + auto index = 0u; + for( auto&& iter : mShaderCache ) + { + if( &*iter == &shader ) + { + iter.Reset(); + mShaderCache.erase( mShaderCache.begin()+index ); + return; + } + ++index; + } +} + +void Graphics::RemoveCommandPool( CommandPool& commandPool ) +{ + NotImplemented(); +} + +void Graphics::RemoveDescriptorPool( std::unique_ptr pool ) +{ + NotImplemented(); +} + +Handle Graphics::FindShader( vk::ShaderModule shaderModule ) +{ + for( auto&& iter : mShaderCache ) + { + if( iter->GetVkShaderModule() == shaderModule ) + { + return Handle(&*iter); + } + } + return Handle(); +} + + } // namespace Vulkan } // namespace Graphics } // namespace Dali diff --git a/dali/graphics/vulkan/vulkan-graphics.h b/dali/graphics/vulkan/vulkan-graphics.h index 5e4c9e9..aa5298e 100644 --- a/dali/graphics/vulkan/vulkan-graphics.h +++ b/dali/graphics/vulkan/vulkan-graphics.h @@ -1,5 +1,5 @@ -#ifndef DALI_GRAPHICS_VULKAN_GRAPHICS_H -#define DALI_GRAPHICS_VULKAN_GRAPHICS_H +#ifndef DALI_GRAPHICS_VULKAN_GRAPHICS +#define DALI_GRAPHICS_VULKAN_GRAPHICS /* * Copyright (c) 2017 Samsung Electronics Co., Ltd. @@ -35,9 +35,23 @@ using SurfaceFactory = Dali::Integration::Graphics::SurfaceFactory; namespace Vulkan { +enum class Platform +{ + UNDEFINED, + XLIB, + XCB, + WAYLAND, +}; + +class Buffer; +class Image; +class Pipeline; +class Shader; +class Framebuffer; class Surface; class CommandPool; -class DeviceMemoryManager; +class DescriptorPool; +class GpuMemoryManager; class Graphics { @@ -58,7 +72,7 @@ public: void CreateDevice(); /** Creates new command pool */ - std::unique_ptr< CommandPool > CreateCommandPool(const vk::CommandPoolCreateInfo& info); + CommandPoolRef CreateCommandPool(const vk::CommandPoolCreateInfo& info); vk::Device GetDevice() const; @@ -68,7 +82,7 @@ public: const vk::AllocationCallbacks& GetAllocator() const; - DeviceMemoryManager& GetDeviceMemoryManager() const + GpuMemoryManager& GetDeviceMemoryManager() const { return *mDeviceMemoryManager; } @@ -83,18 +97,21 @@ public: Queue& GetComputeQueue(uint32_t index = 0u) const; Queue& GetPresentQueue() const; + Platform GetDefaultPlatform() const; + private: - void CreateInstance(); + void CreateInstance( const std::vector& extensions, const std::vector& validationLayers ); void DestroyInstance(); void PreparePhysicalDevice(); void GetPhysicalDeviceProperties(); void GetQueueFamilyProperties(); std::vector< vk::DeviceQueueCreateInfo > GetQueueCreateInfos(); + std::vector PrepareDefaultInstanceExtensions(); private: - std::unique_ptr mDeviceMemoryManager; + std::unique_ptr mDeviceMemoryManager; vk::Instance mInstance; std::unique_ptr mAllocator{nullptr}; @@ -121,10 +138,39 @@ private: std::vector< std::unique_ptr > mTransferQueues; std::vector< std::unique_ptr > mComputeQueues; std::unique_ptr< Queue > mPresentQueue; + + Platform mPlatform { Platform::UNDEFINED }; + +public: + // TODO: all this stuff should go into some vulkan cache + + void AddBuffer( Handle buffer ); + void AddImage( Handle image ); + void AddPipeline( Handle pipeline ); + void AddShader( Handle shader ); + void AddCommandPool( Handle pool ); + void AddDescriptorPool( Handle pool ); + void AddFramebuffer( Handle framebuffer ); + + ShaderRef FindShader( vk::ShaderModule shaderModule ); + + void RemoveBuffer( Buffer& buffer ); + void RemoveShader( Shader& shader ); + void RemoveCommandPool( CommandPool& commandPool ); + void RemoveDescriptorPool( std::unique_ptr pool ); + +private: + std::vector mBuffersCache; + std::vector mImageCache; + std::vector mPipelineCache; + std::vector mShaderCache; + std::vector mCommandPoolCache; + std::vector mDescriptorPoolCache; + std::vector mFramebufferCache; }; } // namespace Vulkan } // namespace Graphics } // namespace Dali -#endif // DALI_GRAPHICS_VULKAN_GRAPHICS_H +#endif // DALI_GRAPHICS_VULKAN_GRAPHICS diff --git a/dali/graphics/vulkan/vulkan-image.cpp b/dali/graphics/vulkan/vulkan-image.cpp index 50e05e0..5ec2477 100644 --- a/dali/graphics/vulkan/vulkan-image.cpp +++ b/dali/graphics/vulkan/vulkan-image.cpp @@ -40,17 +40,17 @@ vk::ImageView Image::CreateUnmanagedView(const vk::ImageViewCreateInfo& info) return nullptr; } -UniqueImageView Image::CreateView(const vk::ImageViewCreateInfo& info) +ImageViewRef Image::CreateView(const vk::ImageViewCreateInfo& info) { - return MakeUnique< ImageView >(mGraphics, *this, info); + return MakeRef< ImageView >(mGraphics, *this, info); } -ImageView::ImageView(Graphics& graphics, Image& image) : mGraphics(graphics), mImageRef(image) +ImageView::ImageView(Graphics& graphics, Image& image) : mGraphics(graphics), mImageRef(&image) { } ImageView::ImageView(Graphics& graphics, Image& image, const VkImageViewCreateInfo& createInfo) -: mGraphics(graphics), mImageRef(image) +: mGraphics(graphics), mImageRef(&image) { mImageView = VkAssert(mGraphics.GetDevice().createImageView(createInfo, mGraphics.GetAllocator())); diff --git a/dali/graphics/vulkan/vulkan-image.h b/dali/graphics/vulkan/vulkan-image.h index ff29ffa..aefb4e9 100644 --- a/dali/graphics/vulkan/vulkan-image.h +++ b/dali/graphics/vulkan/vulkan-image.h @@ -1,5 +1,5 @@ -#ifndef DALI_GRAPHICS_VULKAN_IMAGE_H -#define DALI_GRAPHICS_VULKAN_IMAGE_H +#ifndef DALI_GRAPHICS_VULKAN_IMAGE +#define DALI_GRAPHICS_VULKAN_IMAGE /* * Copyright (c) 2017 Samsung Electronics Co., Ltd. @@ -34,7 +34,7 @@ enum class ResourceOwnershipType EXTERNAL }; -class Image : public Resource +class Image : public VkManaged { public: /** @@ -75,7 +75,7 @@ public: * @param info * @return */ - UniqueImageView CreateView(const vk::ImageViewCreateInfo& info); + ImageViewRef CreateView(const vk::ImageViewCreateInfo& info); /** * Returns underlying Vulkan object @@ -100,7 +100,7 @@ private: * ImageView * todo: move it to its own file */ -class ImageView : public Resource +class ImageView : public VkManaged { public: ImageView(Graphics& graphics, Image& image); @@ -115,12 +115,13 @@ public: Image& GetImage() const { - return mImageRef.GetResource(); + return *mImageRef; } private: + Graphics& mGraphics; - ResourceRef mImageRef; + Handle mImageRef; vk::ImageView mImageView; }; @@ -131,4 +132,4 @@ private: } // namespace Dali -#endif // DALI_GRAPHICS_VULKAN_IMAGE_H +#endif // DALI_GRAPHICS_VULKAN_IMAGE diff --git a/dali/graphics/vulkan/vulkan-pipeline.cpp b/dali/graphics/vulkan/vulkan-pipeline.cpp new file mode 100644 index 0000000..e9c0219 --- /dev/null +++ b/dali/graphics/vulkan/vulkan-pipeline.cpp @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ + +/** + * Class Pipeline::Impl + * Internal implementation of the pipeline + */ +struct Pipeline::Impl +{ + Impl( Vulkan::Graphics& graphics, const vk::GraphicsPipelineCreateInfo& info ) : + mInfo( info ), + mGraphics( graphics ) + { + }; + + Impl() = default; + ~Impl() + { + if(mPipelineLayout) + { + mGraphics.GetDevice().destroyPipelineLayout( mPipelineLayout, mGraphics.GetAllocator() ); + } + if(mPipeline) + { + mGraphics.GetDevice().destroyPipeline( mPipeline, mGraphics.GetAllocator() ); + } + } + + /** + * + * @return + */ + vk::Pipeline GetVkPipeline() const + { + return mPipeline; + } + + vk::Result Initialise() + { + if( !ValidateShaderModules() ) + { + return vk::Result::eErrorInitializationFailed; + } + + CreatePipelineLayout(); + + // use default render pass for default framebuffer + // TODO: swapchain/surface should use vulkan-framebuffer object + // in place of swapchain structures! + if( !mInfo.renderPass ) + { + SetRenderPass( mGraphics.GetSurface( 0 ).GetRenderPass() ); + } + + SetRasterizationState(); + + SetDepthStencilState(); + + SetMultisampleState(); + + SetColorBlendState(); + + mInfo.setFlags( vk::PipelineCreateFlagBits::eAllowDerivatives ); + // create pipeline + mPipeline = VkAssert( mGraphics.GetDevice().createGraphicsPipeline( nullptr, mInfo, mGraphics.GetAllocator() ) ); + if(mPipeline) + { + return vk::Result::eSuccess; + } + return vk::Result::eErrorInitializationFailed; + } + + void SetRenderPass( vk::RenderPass renderpass ) + { + mInfo.setRenderPass( renderpass ); + } + + void SetDepthStencilState() + { + mDepthStencilState = vk::PipelineDepthStencilStateCreateInfo{}; + mDepthStencilState.setDepthBoundsTestEnable( false ); + mDepthStencilState.setStencilTestEnable( false ); + mInfo.setPDepthStencilState( & mDepthStencilState ); + } + + void SetMultisampleState() + { + mMultisampleState = vk::PipelineMultisampleStateCreateInfo{}; + mMultisampleState.setSampleShadingEnable( false ); + mMultisampleState.setRasterizationSamples( vk::SampleCountFlagBits::e1); + mMultisampleState.setAlphaToCoverageEnable( false ); + mMultisampleState.setMinSampleShading( 1.0f ); + mMultisampleState.setPSampleMask( nullptr ); + mInfo.setPMultisampleState( &mMultisampleState ); + } + + void SetVertexInputState( + std::vector attrDesc, + std::vector bindingDesc) + { + mBindingDesc.clear(); + mAttrDesc.clear(); + mVertexInputState = vk::PipelineVertexInputStateCreateInfo{}; + mVertexInputState.setPVertexAttributeDescriptions( (mAttrDesc = attrDesc).data() ); + mVertexInputState.setPVertexBindingDescriptions( (mBindingDesc = bindingDesc).data() ); + mVertexInputState.setVertexAttributeDescriptionCount( U32(mAttrDesc.size()) ); + mVertexInputState.setVertexBindingDescriptionCount( U32(mBindingDesc.size()) ); + mInfo.setPVertexInputState( &mVertexInputState ); + } + + /** + * Sets the viewport on uncompiled pipeline + * @return + */ + void SetViewport( float x, float y, float width, float height ) + { + assert( !mPipeline && "Pipeline cannot be changed anymore!"); + + // AB: add scissor, read data from graphics for fullscreen viewport + // simplified mode for the demo purposes + mViewports.emplace_back( x, y, width, height ); + mViewports[0].setMinDepth( 0.0f ); + mViewports[0].setMaxDepth( 1.0f ); + mScissors = vk::Rect2D( { static_cast(x), static_cast(y) }, + { U32(width), U32(height) }); + mViewportState = vk::PipelineViewportStateCreateInfo{}. + setViewportCount( U32(mViewports.size()) ). + setPViewports( mViewports.data() ). + setPScissors( &mScissors ). + setScissorCount( 1 ); + + // replace viewport state + mInfo.setPViewportState( &mViewportState ); + } + + /** + * + * @param topology + * @param restartEnable + */ + void SetInputAssemblyState( vk::PrimitiveTopology topology, bool restartEnable ) + { + mInputAssemblyState = vk::PipelineInputAssemblyStateCreateInfo{}; + mInputAssemblyState.setPrimitiveRestartEnable( restartEnable ); + mInputAssemblyState.setTopology( topology ); + mInfo.setPInputAssemblyState( &mInputAssemblyState ); + } + + void SetRasterizationState() + { + mRasterizationState = vk::PipelineRasterizationStateCreateInfo{}; + mRasterizationState.setCullMode( vk::CullModeFlagBits::eNone ); + mRasterizationState.setDepthBiasClamp( 0.0f ); + mRasterizationState.setDepthBiasEnable( false ); + mRasterizationState.setDepthClampEnable( false ); + mRasterizationState.setFrontFace( vk::FrontFace::eClockwise ); + mRasterizationState.setPolygonMode( vk::PolygonMode::eFill ); + mRasterizationState.setRasterizerDiscardEnable( false ); + mRasterizationState.setLineWidth( 1.0f ); + mInfo.setPRasterizationState( & mRasterizationState ); + } + + void SetColorBlendState() + { + mAttachementNoBlendState = vk::PipelineColorBlendAttachmentState{}; + //mAttachementNoBlendState.setBlendEnable( true ); + mAttachementNoBlendState.setColorWriteMask( vk::ColorComponentFlagBits::eR | + vk::ColorComponentFlagBits::eG | + vk::ColorComponentFlagBits::eB | + vk::ColorComponentFlagBits::eA ); + + mColorBlendState.setBlendConstants( { 1.0f, 1.0f, 1.0f, 1.0f }); + mColorBlendState = vk::PipelineColorBlendStateCreateInfo{}; + mColorBlendState.setAttachmentCount( 1 ); + mColorBlendState.setPAttachments( &mAttachementNoBlendState ); + mInfo.setPColorBlendState(&mColorBlendState); + } + + /** + * Sets the shader. Must be set before compiling the pipeline, compiled pipeline + * becomes immutable. + * @param shader + * @param stage + * @return + */ + bool SetShader( ShaderRef shader, Shader::Type stage ) + { + assert( !mPipeline && "Pipeline cannot be changed anymore!"); + + // check if shader isn't orphaned for some reason + if( !mGraphics.FindShader( *shader ) ) + { + return false; + } + + auto info = vk::PipelineShaderStageCreateInfo{}. + setModule( *shader ). + setStage( static_cast( stage ) ). + setPName( "main" ); + + mShaderStageCreateInfo.push_back( info ); + mShaderResources.push_back( shader ); + + mInfo.setPStages( mShaderStageCreateInfo.data() ); + mInfo.setStageCount( static_cast(mShaderStageCreateInfo.size()) ); + + return false; + } + + /** + * + */ + void CreatePipelineLayout() + { + // pull desciptor set layouts from shaders + auto layoutInfo = vk::PipelineLayoutCreateInfo{}; + + //info.setPSetLayouts( vk::DescriptorSetLayout ) + + std::vector allLayouts{}; + for( auto&& shader : mShaderResources ) + { + auto& layouts = shader->GetDescriptorSetLayouts(); + if( layouts.size() ) + { + allLayouts.resize(layouts.size()); + for (auto i = 0u; i < layouts.size(); ++i) + { + if (layouts[i]) + { + allLayouts[i] = layouts[i]; + } + } + } + } + + layoutInfo.setPSetLayouts( allLayouts.data() ); + layoutInfo.setSetLayoutCount( static_cast(allLayouts.size()) ); + + mPipelineLayout = VkAssert( mGraphics.GetDevice().createPipelineLayout( layoutInfo, mGraphics.GetAllocator() ) ); + + mInfo.setLayout( mPipelineLayout ); + } + + + bool Compile() + { + return Initialise() == vk::Result::eSuccess; + } + + bool ValidateShaderModules() + { + for( auto i = 0u; i < mInfo.stageCount; ++i ) + { + const auto& stage = mInfo.pStages[i]; + auto shaderHandle = mGraphics.FindShader( stage.module ); + if( shaderHandle ) + { + mShaderResources.push_back( shaderHandle ); + } + else + { + return false; // invalid shader! Can't track it + } + } + return true; + } + + + vk::GraphicsPipelineCreateInfo mInfo { }; + vk::Pipeline mPipeline { nullptr }; + uint32_t mModified { 0u }; + Graphics& mGraphics; + + // resources + std::vector> mShaderResources; + + vk::PipelineViewportStateCreateInfo mViewportState {}; + std::vector mViewports {}; + vk::Rect2D mScissors {}; + + std::vector mShaderStageCreateInfo; + vk::PipelineLayout mPipelineLayout{}; + + // vertex input state + vk::PipelineVertexInputStateCreateInfo mVertexInputState {}; + std::vector mAttrDesc; + std::vector mBindingDesc; + + // vertex input assembly state + vk::PipelineInputAssemblyStateCreateInfo mInputAssemblyState {}; + + // rasterization state + vk::PipelineRasterizationStateCreateInfo mRasterizationState {}; + + // Dpeth/stencil state + vk::PipelineDepthStencilStateCreateInfo mDepthStencilState {}; + + // Multisample state + vk::PipelineMultisampleStateCreateInfo mMultisampleState {}; + + // Color blend + vk::PipelineColorBlendStateCreateInfo mColorBlendState {}; + vk::PipelineColorBlendAttachmentState mAttachementNoBlendState {}; +}; + +/********************************************************************* + * Class Pipeline + * + */ + +PipelineRef Pipeline::New( Graphics& graphics, const vk::GraphicsPipelineCreateInfo& info ) +{ + auto pipeline = Handle( new Pipeline(graphics, info) ); + graphics.AddPipeline(pipeline); + return pipeline; +} + +Pipeline::~Pipeline() = default; + +Pipeline::Pipeline( Graphics& graphics, const vk::GraphicsPipelineCreateInfo& info ) +{ + mImpl = MakeUnique( graphics, info ); +} + +vk::Pipeline Pipeline::GetVkPipeline() const +{ + return mImpl->GetVkPipeline(); +} + +bool Pipeline::OnDestroy() +{ + return false; +} + +void Pipeline::SetViewport( float x, float y, float width, float height ) +{ + mImpl->SetViewport( x, y, width, height ); +} + +bool Pipeline::SetShader( ShaderRef shader, Shader::Type stage ) +{ + return mImpl->SetShader( shader, stage ); +} + +void Pipeline::SetVertexInputState(std::vector attrDesc, + std::vector bindingDesc) +{ + mImpl->SetVertexInputState( attrDesc, bindingDesc ); +} + +void Pipeline::SetInputAssemblyState( vk::PrimitiveTopology topology, bool restartEnable ) +{ + mImpl->SetInputAssemblyState( topology, restartEnable ); +} + +bool Pipeline::Compile() +{ + return mImpl->Compile(); +} + +vk::PipelineLayout Pipeline::GetVkPipelineLayout() const +{ + return mImpl->mPipelineLayout; +} + +} // namespace Vulkan + +} // namespace Graphics + +} // namespace Dali \ No newline at end of file diff --git a/dali/graphics/vulkan/vulkan-pipeline.h b/dali/graphics/vulkan/vulkan-pipeline.h new file mode 100644 index 0000000..0dbef6f --- /dev/null +++ b/dali/graphics/vulkan/vulkan-pipeline.h @@ -0,0 +1,119 @@ +#ifndef DALI_GRAPHICS_VULKAN_PIPELINE +#define DALI_GRAPHICS_VULKAN_PIPELINE + +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ +class Graphics; +class Pipeline : public VkManaged +{ +public: + + /** + * Creates immutable Pipeline object ( verified resources for tracking ) + * @param graphics + * @param info + * @return + */ + static Handle New( Graphics& graphics, const vk::GraphicsPipelineCreateInfo& info ); + + /** + * Destructor + */ + ~Pipeline() override; + + /** + * Sets the viewport + * @param x + * @param y + * @param width + * @param height + */ + void SetViewport( float x, float y, float width, float height ); + + /** + * Attaches A shader module to the particular stage of pipeline + * @param shader + * @param stage + * @return + */ + bool SetShader( ShaderRef shader, Shader::Type stage ); + + /** + * + * @param attrDesc + * @param bindingDesc + */ + void SetVertexInputState(std::vector attrDesc, + std::vector bindingDesc); + + /** + * + * @param topology + * @param restartEnable + */ + void SetInputAssemblyState( vk::PrimitiveTopology topology, bool restartEnable ); + /** + * + * @return + */ + bool Compile(); + +private: + + Pipeline( Graphics& graphics, const vk::GraphicsPipelineCreateInfo& info ); + +public: + + /** + * Returns Vulkan VkPipeline object associated with Pipeline + * @return + */ + vk::Pipeline GetVkPipeline() const; + + /** + * Returns Vulkan VkPipelineLayout object associated with Pipeline + * @return + */ + vk::PipelineLayout GetVkPipelineLayout() const; + + bool OnDestroy() override; + +private: + class Impl; + std::unique_ptr mImpl; +}; + +using PipelineRef = Handle; + +} // Namespace Vulkan + +} // Namespace Graphics + +} // Namespace Dali + +#endif // DALI_GRAPHICS_VULKAN_PIPELINE diff --git a/dali/graphics/vulkan/vulkan-queue.cpp b/dali/graphics/vulkan/vulkan-queue.cpp index 81c7a3c..fa7417b 100644 --- a/dali/graphics/vulkan/vulkan-queue.cpp +++ b/dali/graphics/vulkan/vulkan-queue.cpp @@ -56,20 +56,20 @@ inline PrepareSemaphoresData PrepareSemaphores(const std::vector< CommandBufferR PrepareSemaphoresData retval{}; for(auto& cmdbufref : commandBuffers) { - auto& cmdbuf = cmdbufref.get(); + auto& cmdbuf = cmdbufref; if(!retval.signalSemaphores.empty()) { retval.signalSemaphores.insert(retval.signalSemaphores.end(), - cmdbuf.GetSignalSemaphores().begin(), - cmdbuf.GetSignalSemaphores().end()); + cmdbuf->GetSignalSemaphores().begin(), + cmdbuf->GetSignalSemaphores().end()); } if(!retval.waitSemaphores.empty()) { - retval.waitSemaphores.insert(retval.waitSemaphores.end(), cmdbuf.GetSWaitSemaphores().begin(), - cmdbuf.GetSWaitSemaphores().end()); + retval.waitSemaphores.insert(retval.waitSemaphores.end(), cmdbuf->GetSWaitSemaphores().begin(), + cmdbuf->GetSWaitSemaphores().end()); retval.waitDstStageMasks.insert(retval.waitDstStageMasks.end(), - cmdbuf.GetWaitSemaphoreStages().begin(), - cmdbuf.GetWaitSemaphoreStages().end()); + cmdbuf->GetWaitSemaphoreStages().begin(), + cmdbuf->GetWaitSemaphoreStages().end()); } } return std::move(retval); @@ -77,13 +77,13 @@ inline PrepareSemaphoresData PrepareSemaphores(const std::vector< CommandBufferR } // submission -Submission::Submission(Fence& fence) : mFences(fence) +Submission::Submission(Handle fence) : mFences(fence) { } bool Submission::WaitForFence(uint32_t timeout) { - return mFences.get().Wait(timeout); + return mFences->Wait(timeout); } // queue @@ -97,7 +97,7 @@ Queue::~Queue() // queues are non-destructible { } -std::unique_ptr< Submission > Queue::Submit(CommandBuffer& commandBuffer, Fence& fence) +std::unique_ptr< Submission > Queue::Submit( CommandBufferRef commandBuffer, Handle fence) { auto buffers = std::vector< CommandBufferRef >({commandBuffer}); return Submit(buffers, fence); @@ -105,7 +105,7 @@ std::unique_ptr< Submission > Queue::Submit(CommandBuffer& commandBuffer, Fence& #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wframe-larger-than=" -std::unique_ptr< Submission > Queue::Submit(const std::vector< CommandBufferRef >& commandBuffers, Fence& fence) +std::unique_ptr< Submission > Queue::Submit(const std::vector< CommandBufferRef >& commandBuffers, Handle fence) { // Prepare command buffers for submission auto buffers = PrepareBuffers(commandBuffers); @@ -123,7 +123,7 @@ std::unique_ptr< Submission > Queue::Submit(const std::vector< CommandBufferRef info.setPWaitSemaphores(semaphores.waitSemaphores.data()); info.setPWaitDstStageMask(semaphores.waitDstStageMasks.data()); - VkAssert(mQueue.submit(1, &info, fence.GetFence())); + VkAssert(mQueue.submit(1, &info, fence->GetFence())); return MakeUnique< Submission >(fence); } @@ -134,7 +134,7 @@ std::vector< vk::CommandBuffer > Queue::PrepareBuffers(const std::vector< Comman std::vector< vk::CommandBuffer > retval(commandBuffers.size()); for(uint32_t i = 0; i < commandBuffers.size(); ++i) { - retval[i] = commandBuffers[i].get().Get(); + retval[i] = commandBuffers[i]->GetVkCommandBuffer(); } return retval; } diff --git a/dali/graphics/vulkan/vulkan-queue.h b/dali/graphics/vulkan/vulkan-queue.h index 351a9fb..22c019d 100644 --- a/dali/graphics/vulkan/vulkan-queue.h +++ b/dali/graphics/vulkan/vulkan-queue.h @@ -1,8 +1,8 @@ -#ifndef DALI_GRAPHICS_VULKAN_QUEUE_H -#define DALI_GRAPHICS_VULKAN_QUEUE_H +#ifndef DALI_GRAPHICS_VULKAN_QUEUE +#define DALI_GRAPHICS_VULKAN_QUEUE /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,13 +32,13 @@ class Fence; class Submission { public: - Submission(Fence& fence); + Submission(Handle fence); bool WaitForFence(uint32_t timeout = 0u); private: // todo: possibly resources locks stored here? - FenceRef mFences; + Handle mFences; }; class Queue @@ -51,10 +51,10 @@ public: /** Submits command buffers */ std::unique_ptr< Submission > Submit(const std::vector< CommandBufferRef >& commandBuffers, - Fence& fence); + Handle fence); /** Helper function to submit single command buffer */ - std::unique_ptr< Submission > Submit(CommandBuffer& commandBuffer, Fence& fence); + std::unique_ptr< Submission > Submit(CommandBufferRef commandBuffer, Handle fence); void WaitIdle() const; @@ -89,7 +89,9 @@ private: }; } // namespace Vulkan + } // namespace Graphics + } // namespace Dali -#endif // DALI_GRAPHICS_VULKAN_QUEUE_H +#endif // DALI_GRAPHICS_VULKAN_QUEUE diff --git a/dali/graphics/vulkan/vulkan-shader.cpp b/dali/graphics/vulkan/vulkan-shader.cpp new file mode 100644 index 0000000..fa96b2f --- /dev/null +++ b/dali/graphics/vulkan/vulkan-shader.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ + +/* + * Class: Shader::Impl + */ +struct Shader::Impl +{ + Impl( Shader& owner, Graphics& graphics, const vk::ShaderModuleCreateInfo& info ) : + mOwner( owner ), + mGraphics( graphics ), + mCreateInfo( info ) + { + } + + ~Impl() + { + if(mDSLayouts.size()) + { + for(auto&& ds : mDSLayouts ) + { + mGraphics.GetDevice().destroyDescriptorSetLayout( ds, mGraphics.GetAllocator() ); + } + } + if(mShaderModule) + { + mGraphics.GetDevice().destroyShaderModule( mShaderModule, mGraphics.GetAllocator() ); + } + } + + vk::Result Initialise() + { + if( (mShaderModule = VkAssert( mGraphics.GetDevice().createShaderModule( mCreateInfo, mGraphics.GetAllocator() ) ))) + { + return vk::Result::eSuccess; + } + return vk::Result::eErrorInitializationFailed; + } + + vk::ShaderModule GetVkShaderModule() const + { + return mShaderModule; + } + + + // creates new descriptor set layout + // TODO: should be read from the shader and any manual setting should not + // take place after we have proper reflection! + void SetDescriptorSetLayout( uint32_t set, vk::DescriptorSetLayoutCreateInfo info ) + { + auto layout = VkAssert( mGraphics.GetDevice().createDescriptorSetLayout( info, mGraphics.GetAllocator() ) ); + if( mDSLayouts.size() >= set ) + { + mDSLayouts.resize( set+1 ); + } + else if ( mDSLayouts[set] ) // already existing set ( this is error but for now handle it ) + { + mGraphics.GetDevice().destroyDescriptorSetLayout( mDSLayouts[set], mGraphics.GetAllocator() ); + } + mDSLayouts[set] = layout; + } + + const std::vector& GetDescriptorSetLayouts() const + { + return mDSLayouts; + } + + + Shader& mOwner; + Graphics& mGraphics; + vk::ShaderModuleCreateInfo mCreateInfo; + vk::ShaderModule mShaderModule; + std::vector mDSLayouts; // descriptorset layouts +}; + +/* + * Class: Shader + */ +Handle Shader::New(Graphics &graphics, const vk::ShaderModuleCreateInfo &info) +{ + auto shader = Handle(new Shader(graphics, info)); // can't use make unique because of permissions + if(shader) + { + if( shader->mImpl->Initialise() == vk::Result::eSuccess ) + { + graphics.AddShader( shader ); + } + } + return shader; +} + +Handle Shader::New( Graphics& graphics, const void* bytes, std::size_t size ) +{ + return New( graphics, vk::ShaderModuleCreateInfo{} + .setCodeSize( size ) + .setPCode(reinterpret_cast(bytes))); +} + +Shader::Shader( Graphics& graphics, const vk::ShaderModuleCreateInfo& info ) +{ + mImpl = MakeUnique( *this, graphics, info ); +} + +Shader::~Shader() = default; + +vk::ShaderModule Shader::GetVkShaderModule() const +{ + return mImpl->GetVkShaderModule(); +} + +bool Shader::OnDestroy() +{ + mImpl->mGraphics.RemoveShader( *this ); + return true; +} + +void Shader::SetDescriptorSetLayout( uint32_t set, vk::DescriptorSetLayoutCreateInfo info ) +{ + mImpl->SetDescriptorSetLayout( set, info ); +} + +const std::vector& Shader::GetDescriptorSetLayouts() const +{ + return mImpl->GetDescriptorSetLayouts(); +} +} +} +} \ No newline at end of file diff --git a/dali/graphics/vulkan/vulkan-shader.h b/dali/graphics/vulkan/vulkan-shader.h new file mode 100644 index 0000000..1c0a997 --- /dev/null +++ b/dali/graphics/vulkan/vulkan-shader.h @@ -0,0 +1,98 @@ +#ifndef DALI_GRAPHICS_VULKAN_SHADER +#define DALI_GRAPHICS_VULKAN_SHADER + +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Graphics +{ +namespace Vulkan +{ +class Graphics; +class Shader : public VkManaged // can be overriden as ShaderGLSL for example +{ +public: + + enum class Type + { + VERTEX = static_cast( vk::ShaderStageFlagBits::eVertex ), + FRAGMENT = static_cast( vk::ShaderStageFlagBits::eFragment ), + COMPUTE = static_cast( vk::ShaderStageFlagBits::eCompute ), + GEOMETRY = static_cast( vk::ShaderStageFlagBits::eGeometry ), + }; + + /** + * + * @param graphics + * @param info + * @return + */ + static Handle New( Graphics& graphics, const vk::ShaderModuleCreateInfo& info ); + + /** + * Creates new shader module from SPIRV code + * @param graphics + * @param bytes + * @param size + * @return + */ + static Handle New( Graphics& graphics, const void* bytes, std::size_t size ); + + /** + * + */ + ~Shader(); + + vk::ShaderModule GetVkShaderModule() const; + + const std::vector& GetDescriptorSetLayouts() const; + + bool OnDestroy() override; + + operator vk::ShaderModule() const + { + return GetVkShaderModule(); + } + +public: + + void SetDescriptorSetLayout( uint32_t set, vk::DescriptorSetLayoutCreateInfo info ); + +private: + + Shader( Graphics& graphics, const vk::ShaderModuleCreateInfo& info ); + +private: + + class Impl; + std::unique_ptr mImpl; +}; + +using ShaderRef = Handle; + +} // Namespace Vulkan + +} // Namespace Graphics + +} // Namespace Dali + +#endif // DALI_GRAPHICS_VULKAN_SHADER diff --git a/dali/graphics/vulkan/vulkan-standalone-test.cpp b/dali/graphics/vulkan/vulkan-standalone-test.cpp index f42b323..ff62bb0 100644 --- a/dali/graphics/vulkan/vulkan-standalone-test.cpp +++ b/dali/graphics/vulkan/vulkan-standalone-test.cpp @@ -12,6 +12,13 @@ #define VK_USE_PLATFORM_XCB_KHR #endif +#include +#include +#include +#include + +using namespace glm; + #include #include @@ -19,10 +26,44 @@ #include #include +// internals +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "generated/spv-shaders-gen.h" + #define USE_XLIB 0 +#include using Dali::Integration::Graphics::Graphics; using Dali::Integration::Graphics::Vulkan::VkSurfaceFactory; +using Dali::Graphics::Vulkan::Buffer; +using Dali::Graphics::Vulkan::DeviceMemory; +using Dali::Graphics::Vulkan::Shader; +using Dali::Graphics::Vulkan::DescriptorSetLayout; +using Dali::Graphics::Vulkan::GpuMemoryManager; +using Dali::Graphics::Vulkan::GpuMemoryAllocator; +using Dali::Graphics::Vulkan::Shader; +using Dali::Graphics::Vulkan::ShaderRef; +using Dali::Graphics::Vulkan::Pipeline; +using Dali::Graphics::Vulkan::PipelineRef; +using Dali::Graphics::Vulkan::CommandPool; +using Dali::Graphics::Vulkan::CommandBuffer; +using Dali::Graphics::Vulkan::DescriptorPool; + +extern std::vector VSH; +extern std::vector FSH; template< typename T, typename... Args > std::unique_ptr< T > MakeUnique(Args&&... args) @@ -176,6 +217,156 @@ std::unique_ptr< Test::xcb_window_t > create_xcb_window(int width, int height) namespace VulkanTest { + +Dali::Graphics::Vulkan::GpuMemoryBlockHandle test_gpu_memory_manager( Dali::Graphics::Vulkan::Graphics& graphics, + GpuMemoryManager& gpuManager, + const Dali::Graphics::Vulkan::Handle& buffer ) +{ + auto device = graphics.GetDevice(); + auto& allocator = graphics.GetAllocator(); + + auto& gpuAllocator = gpuManager.GetDefaultAllocator(); + return gpuAllocator.Allocate( buffer, vk::MemoryPropertyFlagBits::eHostVisible ); +} + +struct UniformData +{ + mat4 modelMat; + mat4 viewMat; + mat4 projMat; + vec4 color; +} __attribute__((aligned(16))); + + +mat4 MVP; + + + + +template +void update_buffer( Dali::Graphics::Vulkan::BufferHandle buffer, T& value ) +{ + auto ptr = reinterpret_cast(buffer->GetMemoryHandle()->Map()); + *ptr = value; + buffer->GetMemoryHandle()->Unmap(); +} + +void update_translation( Dali::Graphics::Vulkan::BufferHandle buffer ) +{ + static float x = 0.0f; + x += 0.5f; + + UniformData ub; + ub.modelMat = mat4{1.0f}; + ub.modelMat = glm::translate( ub.modelMat, vec3( x, x, 0.0f )); + ub.modelMat = glm::rotate( ub.modelMat, glm::radians( x ), glm::vec3( 0.0f, 0.0f, 1.0f) ); + ub.viewMat = lookAt( vec3( 0.0f, 0.0f, 10.0f ), + vec3( 0.0f, 0.0f, 0.0f ), + vec3( 0.0f, 1.0f, 0.0f ) ); + + glm::mat4 clip( 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + 0.0f, 0.0f, 0.5f, 1.0f ); + + ub.projMat = clip * ortho( 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 100.0f ); + ub.color = vec4( x / 640.0f, x / 480.0f, 1.0f, 1.0f ); + update_buffer( buffer, ub ); +} + +Dali::Graphics::Vulkan::BufferHandle create_uniform_buffer( Dali::Graphics::Vulkan::Graphics& gr ) +{ + // create uniform buffer + auto uniformBuffer = Buffer::New( gr, sizeof(UniformData), Buffer::Type::UNIFORM ); + + // allocate memory + auto memory = gr.GetDeviceMemoryManager().GetDefaultAllocator().Allocate( uniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible ); + + // bind memory + uniformBuffer->BindMemory( memory ); + + auto ub = reinterpret_cast(memory->Map()); + + ub->modelMat = mat4{1.0f}; + //ub->modelMat = glm::translate( ub->modelMat, vec3( 0.0f, 0.0f, 0.0f )); + + ub->viewMat = lookAt( vec3( 0.0f, 0.0f, 10.0f ), + vec3( 0.0f, 0.0f, 0.0f ), + vec3( 0.0f, 1.0f, 0.0f ) ); + + glm::mat4 clip( 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + 0.0f, 0.0f, 0.5f, 1.0f ); + + ub->projMat = clip * ortho( 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 100.0f ); + ub->color = vec4( 0.0f, 1.0f, 1.0f, 1.0f ); + + + MVP = ub->projMat * ub->viewMat * ub->modelMat; + + memory->Unmap(); + + return uniformBuffer; +} + +Dali::Graphics::Vulkan::Handle +create_descriptor_pool( Dali::Graphics::Vulkan::Graphics& gr ) +{ + vk::DescriptorPoolSize size; + size.setDescriptorCount( 1024 ).setType( vk::DescriptorType::eUniformBuffer ); + + // TODO: how to organize this??? + auto pool = DescriptorPool::New( gr, + vk::DescriptorPoolCreateInfo{}. + setMaxSets( 1024 ). + setPoolSizeCount(1).setPPoolSizes(&size)); + return pool; +} + +void test_handle() +{ + /* + using namespace Dali::Graphics::Vulkan; + GpuMemoryBlockHandle handle( new GpuMemoryBlock() ); + + decltype(handle) handle2 = handle; + handle.GetRefCount();*/ +} + +PipelineRef +create_pipeline( Dali::Graphics::Vulkan::Graphics& graphics, + Dali::Graphics::Vulkan::ShaderRef vertexShader, + Dali::Graphics::Vulkan::ShaderRef fragmentShader + ) +{ + using namespace Dali::Graphics::Vulkan; + auto pipelineInfo = vk::GraphicsPipelineCreateInfo{}; + auto pipeline = Pipeline::New( graphics, pipelineInfo ); + + pipeline->SetShader( vertexShader, Shader::Type::VERTEX ); + pipeline->SetShader( fragmentShader, Shader::Type::FRAGMENT ); + pipeline->SetViewport( 0, 0, 640, 480 ); + pipeline->SetVertexInputState( + std::vector{vk::VertexInputAttributeDescription{}. + setBinding( 0 ). + setOffset( 0 ). + setLocation( 0 ). + setFormat( vk::Format::eR32G32B32Sfloat )}, + std::vector{vk::VertexInputBindingDescription{}. + setBinding( 0 ). + setStride( sizeof(float)*3 ). + setInputRate( vk::VertexInputRate::eVertex)} + ); + pipeline->SetInputAssemblyState( vk::PrimitiveTopology::eTriangleList, false ); + + if( !pipeline->Compile() ) + { + pipeline.Reset(); + } + return pipeline; +} + int RunTestMain() { @@ -189,14 +380,113 @@ int RunTestMain() std::unique_ptr{new VkSurfaceXcb{window->connection, window->window}}; #endif + auto graphics = MakeUnique(); auto fbid = graphics->Create( std::move(surfaceFactory) ); - while(1) + // access internal implementation + auto& gr = graphics->GetImplementation(); + + // GPU memory manager + auto& memmgr = gr.GetDeviceMemoryManager(); + + const vec3 VERTICES[] = + { + {0.0f, 0.0f, 0.0f}, + {320.0f, 0.0f, 0.0f}, + {0.0f, 160.0f, 0.0f}, + }; + + + + + // shaders + auto vertexShader = Shader::New( gr, VSH_CODE.data(), VSH_CODE.size() ); + vertexShader->SetDescriptorSetLayout( 0, vk::DescriptorSetLayoutCreateInfo{}. + setBindingCount( 1 ). + setPBindings( std::vector{ + vk::DescriptorSetLayoutBinding{}. + setBinding( 0 ). + setStageFlags( vk::ShaderStageFlagBits::eVertex ). + setDescriptorType( vk::DescriptorType::eUniformBuffer ). + setDescriptorCount( 1 ) + }.data() + )); + + auto fragmentShader = Shader::New( gr, FSH_CODE.data(), FSH_CODE.size() ); + + // buffer + auto vertexBuffer = Buffer::New( gr, sizeof(float)*3*3, Buffer::Type::VERTEX ); + + auto descriptorPool = create_descriptor_pool( gr ); + auto descriptorSet = descriptorPool->AllocateDescriptorSets( vk::DescriptorSetAllocateInfo{} + .setPSetLayouts( vertexShader->GetDescriptorSetLayouts().data() ) + .setDescriptorSetCount( static_cast(vertexShader->GetDescriptorSetLayouts().size()))); + + + + auto& gpuManager = gr.GetDeviceMemoryManager(); + + auto bufferMemory = test_gpu_memory_manager( gr, gpuManager, vertexBuffer ); + vertexBuffer->BindMemory( bufferMemory ); + + auto ptr = static_cast(bufferMemory->Map()); + std::copy( reinterpret_cast(VERTICES), reinterpret_cast(VERTICES)+(sizeof(float)*9), ptr); + bufferMemory->Unmap(); + + auto pipeline = create_pipeline( gr, vertexShader, fragmentShader ); + + auto commandPool = CommandPool::New( gr ); + + auto uniformBuffer = create_uniform_buffer( gr ); + + descriptorSet[0]->WriteUniformBuffer( 0, uniformBuffer, 0, uniformBuffer->GetSize() ); + + // get new buffer + auto cmdDraw = commandPool->NewCommandBuffer( false ); + + // begin recording + cmdDraw->Begin( vk::CommandBufferUsageFlagBits::eRenderPassContinue); + + // vertex buffer + cmdDraw->BindVertexBuffer( 0, vertexBuffer, 0 ); + + // pipeline + cmdDraw->BindGraphicsPipeline( pipeline ); + + // descriptor sets + cmdDraw->BindDescriptorSets( descriptorSet, 0 ); + + // do draw + cmdDraw->Draw( 3, 1, 0, 0 ); + + // finish + cmdDraw->End(); + + + + bool running = true; + + while( running ) { graphics->PreRender( fbid ); + // queue submit draw + + auto cmdbuf = gr.GetSurface( fbid ).GetCurrentCommandBuffer(); + + // get command buffer for current frame and execute the draw call + cmdbuf->ExecuteCommands( { cmdDraw } ); + + graphics->PostRender( fbid ); + + update_translation( uniformBuffer ); } return 0; } } + +int main() +{ + VulkanTest::RunTestMain(); +} diff --git a/dali/graphics/vulkan/vulkan-surface.cpp b/dali/graphics/vulkan/vulkan-surface.cpp index 6d047a9..c38377a 100644 --- a/dali/graphics/vulkan/vulkan-surface.cpp +++ b/dali/graphics/vulkan/vulkan-surface.cpp @@ -73,7 +73,7 @@ void Surface::AcquireNextImage() if(!mFrameFence) { - mFrameFence = MakeUnique< Fence >(mGraphics); + mFrameFence = Fence::New(mGraphics); } // acquire image, for simplicity using fence for acquiring as it is unknown what next command buffer will @@ -92,7 +92,7 @@ void Surface::AcquireNextImage() if(swapImage.layout != vk::ImageLayout::eColorAttachmentOptimal) { auto& queue = mGraphics.GetGraphicsQueue(); - queue.Submit(*swapImage.layoutToColorCmdBuf.get(), *mFrameFence.get())->WaitForFence(); + queue.Submit(swapImage.layoutToColorCmdBuf, mFrameFence)->WaitForFence(); } mFrameFence->Reset(); @@ -112,16 +112,16 @@ void Surface::BeginRenderPass() * todo: automatically start main render pass -> this may have to be done manually in future * if more flexibility is needed */ - auto vkCmdBuf = swapImage.mainCmdBuf->Get(); + auto vkCmdBuf = swapImage.mainCmdBuf->GetVkCommandBuffer(); { std::array< vk::ClearValue, 2 > clearValues; - static float r = 0.0f; - r += 0.01f; + static float r = 1.0f; + //r += 0.01f; if(r > 1.0f) r -= 1.0f; - clearValues[0].color.setFloat32({r, 0.0f, 0.0f, 1.0f}); + clearValues[0].color.setFloat32({0.0f, 1.0f, 0.0f, 1.0f}); clearValues[1].depthStencil.setDepth(1.0f).setStencil(0.0f); auto rpInfo = vk::RenderPassBeginInfo{}; @@ -131,16 +131,51 @@ void Surface::BeginRenderPass() .setClearValueCount(mHasDepthStencil ? 2 : 1) .setPClearValues(clearValues.data()); - auto subpassContents = vk::SubpassContents{vk::SubpassContents::eInline}; + auto subpassContents = vk::SubpassContents{vk::SubpassContents::eSecondaryCommandBuffers}; vkCmdBuf.beginRenderPass(rpInfo, subpassContents); } } +std::vector Surface::GetClearValues() const +{ + static float r = 0.0f; + r += 0.01f; + if(r > 1.0f) + r -= 1.0f; + + std::array< vk::ClearValue, 2 > clearValues; + clearValues[0].color.setFloat32({r, 0.0f, 0.0f, 1.0f}); + clearValues[1].depthStencil.setDepth(1.0f).setStencil(0.0f); + + auto retval = std::vector{}; + retval.emplace_back( clearValues[0] ); + if( mHasDepthStencil ) + { + retval.emplace_back( clearValues[1] ); + } + return retval; +} + +vk::Extent2D Surface::GetSize() const +{ + return mCapabilities->currentExtent; +} + +Handle Surface::GetCommandBuffer( uint32_t index ) +{ + return mSwapImages[index].mainCmdBuf; +} + +Handle Surface::GetCurrentCommandBuffer() +{ + return mSwapImages[mCurrentBufferIndex].mainCmdBuf; +} + void Surface::EndRenderPass() { // todo: use semaphores and do not create fences all over again auto& swapImage = mSwapImages[mCurrentBufferIndex]; - auto vkCmdBuf = swapImage.mainCmdBuf->Get(); + auto vkCmdBuf = swapImage.mainCmdBuf->GetVkCommandBuffer(); // complete render pass vkCmdBuf.endRenderPass(); @@ -150,7 +185,7 @@ void Surface::EndRenderPass() // submit auto& queue = mGraphics.GetGraphicsQueue(); - queue.Submit(*swapImage.mainCmdBuf.get(), *mFrameFence.get())->WaitForFence(); + queue.Submit(swapImage.mainCmdBuf, mFrameFence)->WaitForFence(); } void Surface::Present() @@ -260,7 +295,7 @@ void Surface::InitialiseSwapchain() void Surface::AddSwapchainImage(vk::Image image, std::vector< SwapchainImage >& swapchainImages) { auto swapImage = std::move(SwapchainImage{}); - swapImage.image = MakeUnique( mGraphics, image ); + swapImage.image = MakeRef( mGraphics, image ); // create ImageView CreateImageView(swapImage); @@ -379,9 +414,7 @@ void Surface::CreateCommandBuffers() { if(!mCommandPool) { - auto info = vk::CommandPoolCreateInfo{}.setFlags(vk::CommandPoolCreateFlagBits::eResetCommandBuffer); - info.setQueueFamilyIndex(0); // todo: get correct queue family index ( 0 works by default ;) ) - mCommandPool = MakeUnique< CommandPool >(mGraphics, info); + mCommandPool = CommandPool::New( mGraphics, vk::CommandPoolCreateInfo{}.setFlags(vk::CommandPoolCreateFlagBits::eResetCommandBuffer) ); } // allocate command buffers @@ -391,8 +424,8 @@ void Surface::CreateCommandBuffers() for(auto& swapImage : mSwapImages) { - swapImage.layoutToColorCmdBuf = mCommandPool->AllocateCommandBuffer(cmdInfo); - swapImage.mainCmdBuf = mCommandPool->AllocateCommandBuffer(cmdInfo); + swapImage.layoutToColorCmdBuf = mCommandPool->NewCommandBuffer(cmdInfo); + swapImage.mainCmdBuf = mCommandPool->NewCommandBuffer(cmdInfo); // Record layout transition for each image, after transition command buffers will be re-recorded // and will take in account only present -> color layout transition @@ -404,13 +437,13 @@ void Surface::CreateCommandBuffers() swapImage.layoutToColorCmdBuf->End(); swapImage.layout = vk::ImageLayout::eColorAttachmentOptimal; - cmdBuffers.push_back(std::ref(*swapImage.layoutToColorCmdBuf.get())); + cmdBuffers.push_back(swapImage.layoutToColorCmdBuf); } // submit to the queue { auto& queue = mGraphics.GetGraphicsQueue(); - auto fence = Fence(mGraphics); + auto fence = Fence::New(mGraphics); auto submission = queue.Submit(cmdBuffers, fence); submission->WaitForFence(); } diff --git a/dali/graphics/vulkan/vulkan-surface.h b/dali/graphics/vulkan/vulkan-surface.h index c45d2d5..9ffdc92 100644 --- a/dali/graphics/vulkan/vulkan-surface.h +++ b/dali/graphics/vulkan/vulkan-surface.h @@ -1,8 +1,8 @@ -#ifndef DALI_GRAPHICS_VULKAN_SURFACE_H -#define DALI_GRAPHICS_VULKAN_SURFACE_H +#ifndef DALI_GRAPHICS_VULKAN_SURFACE +#define DALI_GRAPHICS_VULKAN_SURFACE /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,16 +53,16 @@ struct SwapchainImage SwapchainImage& operator=(const SwapchainImage&) = delete; SwapchainImage& operator=(SwapchainImage&&) = default; - UniqueImage image; - UniqueImageView imageView; + ImageRef image; + ImageViewRef imageView; vk::Framebuffer framebuffer; vk::ImageLayout layout; vk::Semaphore acqSem; vk::Semaphore presentSem; // layout transitions, prerecorded command buffers - UniqueCommandBuffer layoutToColorCmdBuf; - UniqueCommandBuffer mainCmdBuf; + Handle layoutToColorCmdBuf; + Handle mainCmdBuf; }; class Surface @@ -115,9 +115,38 @@ public: */ vk::SurfaceKHR GetSurfaceKHR() const; -private: + /** + * returns set of clear values for this surface + * @return + */ + std::vector GetClearValues() const; + + /** + * Returns size of surface + * @return + */ + vk::Extent2D GetSize() const; + + /** + * Returns primary command buffer associated with specific buffer + * @param index + * @return + */ + Handle GetCommandBuffer( uint32_t index ); + + /** + * Returns primary command buffer associated with current buffer + * @return + */ + Handle GetCurrentCommandBuffer(); + +/** + * + */ void CreateSwapchain(); +private: + void CreateVulkanSwapchain(); void CreateImageView(SwapchainImage& swapImage); @@ -151,7 +180,7 @@ private: vk::ImageView mDepthStencilImageView; vk::DeviceMemory mDepthStencilMemory; - UniqueCommandPool mCommandPool; + Handle mCommandPool; vk::Format mFormat; vk::ColorSpaceKHR mColorSpace; @@ -160,7 +189,7 @@ private: std::vector< SwapchainImage > mSwapImages; std::unique_ptr< vk::SurfaceCapabilitiesKHR > mCapabilities; - UniqueFence mFrameFence; + Handle mFrameFence; vk::RenderPass mDefaultRenderPass; uint32_t mBufferCount; @@ -172,4 +201,4 @@ private: } // namespace Graphics } // namespace Dali -#endif // DALI_GRAPHICS_VULKAN_SURFACE_H +#endif // DALI_GRAPHICS_VULKAN_SURFACE diff --git a/dali/graphics/vulkan/vulkan-types.h b/dali/graphics/vulkan/vulkan-types.h index 255c549..9ccc269 100644 --- a/dali/graphics/vulkan/vulkan-types.h +++ b/dali/graphics/vulkan/vulkan-types.h @@ -1,8 +1,8 @@ -#ifndef DALI_GRAPHICS_VULKAN_TYPES_H -#define DALI_GRAPHICS_VULKAN_TYPES_H +#ifndef DALI_GRAPHICS_VULKAN_TYPES +#define DALI_GRAPHICS_VULKAN_TYPES /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ namespace Graphics template< typename T, typename... Args > std::unique_ptr< T > MakeUnique(Args&&... args) { - return std::unique_ptr< T >(new T(std::forward< Args >(args)...)); + return std::unique_ptr< T >(new T(std::forward< Args >(args)...)); } namespace Vulkan @@ -43,39 +43,22 @@ namespace Vulkan * Forward class declarations */ class Graphics; -class CommandBuffer; -class CommandPool; class Surface; class Queue; -class Fence; -class DeviceMemory; -class Image; -class ImageView; -class Buffer; /** * Unique pointers to Vulkan types */ using UniqueSurface = std::unique_ptr< Surface >; -using UniqueCommandBuffer = std::unique_ptr< CommandBuffer >; -using UniqueCommandPool = std::unique_ptr< CommandPool >; using UniqueQueue = std::unique_ptr< Queue >; -using UniqueFence = std::unique_ptr< Fence >; -using UniqueDeviceMemory = std::unique_ptr< DeviceMemory >; -using UniqueBuffer = std::unique_ptr< Buffer >; -using UniqueImage = std::unique_ptr< Image >; -using UniqueImageView = std::unique_ptr< ImageView >; /** * Reference wrappers */ -using CommandBufferRef = std::reference_wrapper< CommandBuffer >; using QueueRef = std::reference_wrapper< Queue >; -using FenceRef = std::reference_wrapper< Fence >; using SurfaceRef = std::reference_wrapper< Surface >; - template< typename T > T VkAssert(const vk::ResultValue< T >& result, vk::Result expected = vk::Result::eSuccess) { @@ -127,55 +110,204 @@ private: std::atomic mUserCount; }; -template< typename T> -class ResourceRef +/** + * Vulkan object handle + * @tparam T + */ +template +class Handle { public: - ResourceRef( T& object ) - : mObject( &object ) + Handle(); + explicit Handle(T* object ); + Handle( const Handle& handle); + Handle& operator=( const Handle& handle ); + Handle& operator=( Handle&& handle ); + Handle( Handle&& handle ) noexcept; + ~Handle(); + + operator bool() const; + + T* operator->() const { - mObject->IncreaseUserCount(); + return mObject; } - ResourceRef( ResourceRef& object ) + uint32_t GetRefCount() const { - if(mObject) - { - mObject->DecreaseUserCount(); - } + return mObject->GetRefCount(); + } - mObject = object.mObject; - mObject->IncreaseUserCount(); + T& operator*() const + { + return *mObject; } - ResourceRef operator=(ResourceRef& object ) + template + Handle StaticCast() { - if(mObject) + return Handle(static_cast(mObject)); + } + + template + bool operator==( const Handle& object ) const + { + return mObject == &*object; + } + + template + Handle DynamicCast(); + + void Reset() + { + if( mObject ) { - mObject->DecreaseUserCount(); + mObject->Release(); + mObject = nullptr; } + } - mObject = object.mObject; - mObject->IncreaseUserCount(); +private: + + T* mObject { nullptr }; +}; + +template +static Handle VkTypeCast( const Handle& inval ) +{ + return Handle(static_cast(&*inval)); +} + +template +Handle::Handle(T* object) + : mObject( object ) +{ + if(mObject) + { + mObject->Retain(); } +} + +template +Handle::Handle() + : mObject( nullptr ) +{ +} - ~ResourceRef() +template +Handle::Handle(const Handle& handle) +{ + mObject = handle.mObject; + if(mObject) { - if(mObject) + mObject->Retain(); + } +} + +template +Handle::Handle( Handle&& handle ) noexcept +{ + mObject = handle.mObject; + handle.mObject = nullptr; +} + +template +Handle::operator bool() const +{ + return mObject != nullptr; +} + +template +Handle& Handle::operator=( Handle&& handle ) +{ + mObject = handle.mObject; + handle.mObject = nullptr; + return *this; +} + +template +Handle& Handle::operator=( const Handle& handle ) +{ + mObject = handle.mObject; + if(mObject) + { + mObject->Retain(); + } + return *this; +} + +template +Handle::~Handle() +{ + if(mObject) + { + mObject->Release(); + } +} + +template +template +Handle Handle::DynamicCast() +{ + auto val = dynamic_cast(mObject); + if(val) + { + return Handle(val); + } + return Handle(); +} + +template< typename T, typename... Args > +Handle< T > MakeRef(Args&&... args) +{ + return Handle< T >(new T(std::forward< Args >(args)...)); +} + +class VkManaged +{ +public: + + VkManaged() = default; + virtual ~VkManaged() = default; + + void Release() + { + OnRelease(--mRefCount); + if(mRefCount == 0) { - mObject->DecreaseUserCount(); + // orphaned + if(!Destroy()) + { + delete this; + } } } - T& GetResource() const + void Retain() { - return *mObject; + OnRetain(++mRefCount); + } + + uint32_t GetRefCount() + { + return mRefCount; } + bool Destroy() + { + return OnDestroy(); + } + + virtual void OnRetain( uint32_t refcount ) {}; + + virtual void OnRelease( uint32_t refcount ) {}; + + virtual bool OnDestroy() { return false; }; + private: - T* mObject; + std::atomic_uint mRefCount { 0u }; }; using FBID = uint32_t; @@ -187,6 +319,20 @@ assert( "Function no implemented" );\ } /* + * Forward declarations of reference types + */ +using ShaderRef = Handle; +using PipelineRef = Handle; +using FenceRef = Handle; +using BufferRef = Handle; +using FramebufferRef = Handle; +using ImageRef = Handle; +using ImageViewRef = Handle; +using DescriptorPoolRef = Handle; +using CommandPoolRef = Handle; +using CommandBufferRef = Handle; + +/* #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wframe-larger-than=" #pragma GCC diagnostic pop @@ -195,4 +341,4 @@ assert( "Function no implemented" );\ } // namespace Graphics } // namespace Dali -#endif // DALI_GRAPHICS_VULKAN_TYPES_H +#endif // DALI_GRAPHICS_VULKAN_TYPES diff --git a/dali/integration-api/graphics/graphics.cpp b/dali/integration-api/graphics/graphics.cpp index 1f06c8d..9db5d47 100644 --- a/dali/integration-api/graphics/graphics.cpp +++ b/dali/integration-api/graphics/graphics.cpp @@ -59,6 +59,9 @@ Dali::Graphics::FBID Graphics::Create( // create device mGraphicsImpl->CreateDevice(); + // create swapchain + mGraphicsImpl->GetSurface( retval ).CreateSwapchain(); + return retval; } diff --git a/dali/integration-api/graphics/graphics.h b/dali/integration-api/graphics/graphics.h index 1603aba..03e29e4 100644 --- a/dali/integration-api/graphics/graphics.h +++ b/dali/integration-api/graphics/graphics.h @@ -77,11 +77,20 @@ public: */ void PostRender( Dali::Graphics::FBID framebufferId = 0u ); + // this function is used only by the standalone test + template + T& GetImplementation() const + { + return static_cast(*mGraphicsImpl.get()); + } + private: std::unique_ptr mGraphicsImpl; }; + + /** * fixme: dummy function to make sure the static library won't be discarded entirely during linking */