$(graphics_src_dir)/vulkan/vulkan-buffer.cpp \
$(graphics_src_dir)/vulkan/vulkan-graphics.cpp \
$(graphics_src_dir)/vulkan/vulkan-shader.cpp \
+ $(graphics_src_dir)/vulkan/vulkan-swapchain.cpp \
$(graphics_src_dir)/vulkan/vulkan-graphics-controller.cpp \
$(graphics_src_dir)/vulkan/spirv/vulkan-spirv.cpp \
$(graphics_src_dir)/graphics-controller.cpp
};
std::vector<uint8_t> FSH_CODE = {
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00,
- 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 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,
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, 0x05, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x75, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 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,
+ 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x47, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
- 0x02, 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, 0x19, 0x00, 0x09, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x3b, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
- 0x2c, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x13, 0x00, 0x00, 0x00, 0x13, 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, 0x3d, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 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
layout( location = 0 ) in vec4 triColor;
layout( location = 0 ) out vec4 outColor;
-layout( binding = 2 ) uniform sampler2D uTexture;
-
void main()
{
- outColor = triColor + texture( uTexture, vec2(0.5, 0.5));
+ outColor = triColor;
}*/
* @param memoryProperties
* @return
*/
- virtual GpuMemoryBlockRef Allocate( Image& buffer, vk::MemoryPropertyFlags memoryProperties ) = 0;
+ virtual GpuMemoryBlockRef Allocate( const ImageRef& 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 memoryProperties
* @return
*/
- GpuMemoryBlockRef Allocate( Image& image, vk::MemoryPropertyFlags memoryProperties ) override
+ GpuMemoryBlockRef Allocate( const ImageRef& image, vk::MemoryPropertyFlags memoryProperties ) override
{
- return Allocate( mGraphics.GetDevice().getImageMemoryRequirements( image.GetVkImage() ),
+ return Allocate( mGraphics.GetDevice().getImageMemoryRequirements( image->GetVkImage() ),
memoryProperties );
}
--- /dev/null
+#include <string>
+#include <vector>
+#include <vulkan/vulkan.hpp>
+
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-allocator.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.h>
+#include <dali/graphics/vulkan/vulkan-buffer.h>
+#include <dali/graphics/vulkan/vulkan-command-buffer.h>
+#include <dali/graphics/vulkan/vulkan-command-pool.h>
+#include <dali/graphics/vulkan/vulkan-graphics.h>
+#include <dali/graphics/vulkan/vulkan-image.h>
+#include <dali/graphics/vulkan/vulkan-fence.h>
+#include <dali/graphics/vulkan/vulkan-queue.h>
+
+
+namespace VulkanTest
+{
+using namespace Dali::Graphics::Vulkan;
+
+struct Pixel
+{
+ Pixel() = default;
+
+ explicit Pixel( uint32_t _color )
+ : color(_color)
+ {}
+
+ explicit Pixel( uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a)
+ {
+ r = _r;
+ g = _g;
+ b = _b;
+ a = _a;
+ }
+
+ union
+ {
+ uint32_t color;
+ struct
+ {
+ uint8_t r, g, b, a;
+ };
+ };
+};
+
+struct Pixmap
+{
+ explicit Pixmap( std::vector<Pixel> _data, uint32_t _width, uint32_t _height ) :
+ data(_data), width(_width), height(_height), bytesPerPixel(4), pixelFormat( vk::Format::eR32G32B32A32Uint )
+ {
+ }
+ std::vector<Pixel> data;
+ uint32_t width;
+ uint32_t height;
+ uint32_t bytesPerPixel;
+ vk::Format pixelFormat;
+};
+
+struct Texture
+{
+ Texture( Graphics& graphics, Pixmap pixmap ) : mGraphics( graphics ), mPixmap( pixmap )
+ {
+ }
+
+ bool Initialise()
+ {
+ // create image
+ mImage = Image::New( mGraphics,
+ vk::ImageCreateInfo{}
+ .setFormat( mPixmap.pixelFormat )
+ .setInitialLayout( vk::ImageLayout::ePreinitialized )
+ .setSamples( vk::SampleCountFlagBits::e1 )
+ .setSharingMode( vk::SharingMode::eExclusive )
+ .setUsage( vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst )
+ .setExtent( {mPixmap.width, mPixmap.height, 1} )
+ .setArrayLayers( 1 )
+ .setImageType( vk::ImageType::e2D )
+ .setTiling( vk::ImageTiling::eOptimal )
+ .setMipLevels( 1 ) );
+
+ // allocate memory and bind to the image
+ auto& allocator = mGraphics.GetDeviceMemoryManager().GetDefaultAllocator();
+ mImage->BindMemory( allocator.Allocate( mImage, vk::MemoryPropertyFlagBits::eDeviceLocal ) );
+
+ // create transient buffer to copy data
+ auto buffer = Buffer::New( mGraphics,
+ vk::BufferCreateInfo{}
+ .setUsage( vk::BufferUsageFlagBits::eTransferSrc )
+ .setSharingMode( vk::SharingMode::eExclusive )
+ .setSize( mPixmap.data.size()*sizeof(mPixmap.data[0]) ) );
+
+ buffer->BindMemory( allocator.Allocate( buffer, vk::MemoryPropertyFlagBits::eHostVisible ) );
+
+ // copy pixels to the buffer
+ auto ptr = buffer->GetMemoryHandle()->MapTyped<Pixel>();
+ std::copy( mPixmap.data.begin(), mPixmap.data.end(), ptr );
+ buffer->GetMemoryHandle()->Unmap();
+
+ // record copy and layout change
+ auto copy = vk::BufferImageCopy{}.setImageExtent( { mPixmap.width, mPixmap.height, 1 } )
+ .setBufferImageHeight( mPixmap.height )
+ .setBufferOffset( 0 )
+ .setBufferRowLength( mPixmap.width * mPixmap.bytesPerPixel )
+ .setImageExtent( { mPixmap.width, mPixmap.height, 1 } )
+ .setImageOffset( { 0, 0, 0 } )
+ .setImageSubresource(
+ vk::ImageSubresourceLayers{}
+ .setMipLevel( 0 )
+ .setAspectMask( vk::ImageAspectFlagBits::eColor )
+ .setLayerCount( 1 )
+ .setBaseArrayLayer( 0 )
+ );
+ mCommandPool = CommandPool::New( mGraphics );
+ mCommandBuffer = mCommandPool->NewCommandBuffer( true );
+ mCommandBuffer->Begin( vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
+
+ // change layout
+ auto barrier = std::vector<vk::ImageMemoryBarrier>{
+ mCommandBuffer->ImageLayoutTransitionBarrier( mImage, vk::ImageLayout::eTransferDstOptimal, vk::ImageAspectFlagBits::eColor )
+ };
+
+ // change layout to prepare image to transfer data
+ mCommandBuffer->PipelineBarrier( vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer,
+ {}, {}, {}, { barrier } );
+
+ // copy image
+ mCommandBuffer->CopyBufferToImage( buffer, mImage, vk::ImageLayout::ePreinitialized, { copy } );
+
+ // change layout to shader read-only optimal
+ mCommandBuffer->PipelineBarrier( vk::PipelineStageFlagBits::eVertexShader, vk::PipelineStageFlagBits::eVertexShader,
+ {}, {}, {}, {
+ mCommandBuffer->ImageLayoutTransitionBarrier( mImage, vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageAspectFlagBits::eColor )
+ } );
+
+ mCommandBuffer->End();
+
+ // submit and wait till image is uploaded so temporary buffer can be destroyed safely
+ auto fence = Fence::New( mGraphics );
+ mGraphics.GetGraphicsQueue(0u).Submit( mCommandBuffer, fence );
+ fence->Wait();
+
+ }
+
+ Graphics& mGraphics;
+ ImageRef mImage;
+ ImageViewRef mImageView;
+
+ CommandPoolRef mCommandPool;
+ CommandBufferRef mCommandBuffer; // primary buffer, executed independent
+
+ // layouts
+ vk::ImageLayout mOldLayout;
+ vk::ImageLayout mNewLayout;
+
+ // Command pool
+
+
+ Pixmap mPixmap;
+};
+
+/**
+ * Generates a random pixmap
+ * @param width
+ * @param height
+ * @return
+ */
+Pixmap GenerateTexture32BPPRGBA( uint32_t width, uint32_t height )
+{
+ std::vector<Pixel> data;
+ data.resize( width * height );
+
+ const Pixel WHITE { 0xffffffff };
+ const Pixel BLACK { 0x000000ff };
+ const Pixel RED { 0xff0000ff };
+ const Pixel GREEN { 0x00ff00ff };
+ const Pixel BLUE { 0x0000ffff };
+
+ const Pixel COLORS[] = { WHITE, BLACK, RED, GREEN, BLUE };
+ const auto COLORS_COUNT = 5u;
+
+ for( auto y = 0u; y < height; ++y )
+ {
+ for( auto x = 0u; x < width; ++x )
+ {
+ data[ x + width * y ] = COLORS[ ((x*x)+(y*y)) % COLORS_COUNT];
+ }
+ }
+
+ return Pixmap{ data, width, height };
+}
+
+Pixmap LoadResourceImage( void* data, uint32_t width, uint32_t height, uint32_t bytesPerPixel )
+{
+ // todo: create Pixmap object
+}
+
+Texture CreateTexture( Graphics& graphics, Pixmap pixmap )
+{
+ return Texture( graphics, pixmap );
+}
+
+int TextureTestMain( Dali::Graphics::Vulkan::Graphics& graphics )
+{
+ auto pixmap = GenerateTexture32BPPRGBA( 1024, 1024 );
+ auto texture = Texture( graphics, pixmap );
+ texture.Initialise();
+ return 0;
+}
+
+} // namespace VulkanTest
\ No newline at end of file
vk::Buffer mBuffer;
};
-/**
- *
- * @param graphics
- * @param size
- * @return
- */
BufferRef Buffer::New(Graphics& graphics, size_t size, Type type)
{
auto usageFlags = vk::BufferUsageFlags{};
info.setSharingMode( vk::SharingMode::eExclusive );
info.setSize( size );
info.setUsage( usageFlags | vk::BufferUsageFlagBits::eTransferDst );
- auto buffer = Handle<Buffer>( new Buffer(graphics, info) );
+ auto buffer = BufferRef( new Buffer(graphics, info) );
if(buffer && buffer->mImpl->Initialise())
{
return buffer;
}
+BufferRef Buffer::New( Graphics& graphics, vk::BufferCreateInfo info )
+{
+ auto buffer = BufferRef( new Buffer(graphics, info) );
+ if( buffer && buffer->mImpl->Initialise() )
+ {
+ graphics.AddBuffer( buffer );
+ return buffer;
+ }
+ return BufferRef();
+}
+
Buffer::Buffer(Graphics& graphics, const vk::BufferCreateInfo& createInfo)
: VkManaged()
{
static BufferRef New( Graphics& graphics, size_t size, Type type );
/**
+ *
+ * @param graphics
+ * @param info
+ * @return
+ */
+ static BufferRef New( Graphics& graphics, vk::BufferCreateInfo info );
+
+ /**
* Returns buffer usage flags
* @return
*/
*/
// INTERNAL INCLUDES
+#include <dali/graphics/vulkan/vulkan-types.h>
#include <dali/graphics/vulkan/vulkan-buffer.h>
#include <dali/graphics/vulkan/vulkan-command-buffer.h>
#include <dali/graphics/vulkan/vulkan-command-pool.h>
#include <dali/graphics/vulkan/vulkan-descriptor-set.h>
#include <dali/graphics/vulkan/vulkan-graphics.h>
#include <dali/graphics/vulkan/vulkan-image.h>
+#include <dali/graphics/vulkan/vulkan-fence.h>
#include <dali/graphics/vulkan/vulkan-pipeline.h>
#include <dali/graphics/vulkan/vulkan-surface.h>
-#include <dali/graphics/vulkan/vulkan-types.h>
+#include <dali/graphics/vulkan/vulkan-framebuffer.h>
namespace Dali
{
~Impl()
{
+ mResources.clear();
+ mGraphics.GetDevice().freeCommandBuffers( mOwnerCommandPool.GetPool(),
+ 1, &mCommandBuffer );
}
bool Initialise()
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() );
+ // Render pass is obtained from the default framebuffer
+ // it's a legacy but little nicer
+ auto swapchain = mGraphics.GetSwapchainForFBID( 0u );
+ inheritance.setRenderPass( swapchain->GetCurrentFramebuffer()->GetVkRenderPass() );
info.setPInheritanceInfo( &inheritance );
}
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::eColorAttachmentOutput;
- srcAccessMask = vk::AccessFlagBits::eMemoryRead | 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::eMemoryWrite;
- 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 */
// 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 swapchain = mGraphics.GetSwapchainForFBID( 0u );
+ auto surface = mGraphics.GetSurface( 0u );
+ auto frameBuffer = swapchain->GetCurrentFramebuffer();
+ auto renderPass = frameBuffer->GetVkRenderPass();
+ auto clearValues = frameBuffer->GetDefaultClearValues();
auto info = vk::RenderPassBeginInfo{};
- info.setFramebuffer( frameBuffer );
+ info.setFramebuffer( frameBuffer->GetVkFramebuffer() );
info.setRenderPass( renderPass );
info.setClearValueCount( U32( clearValues.size() ) );
info.setPClearValues( clearValues.data() );
- info.setRenderArea( vk::Rect2D( {0, 0}, surface.GetSize() ) );
+ info.setRenderArea( vk::Rect2D( {0, 0}, surface->GetSize() ) );
mCurrentRenderPass = renderPass;
mCommandBuffer.beginRenderPass( info, vk::SubpassContents::eInline );
mCommandBuffer.executeCommands( vkBuffers );
}
+ void PipelineBarrier( vk::PipelineStageFlags srcStageMask,
+ vk::PipelineStageFlags dstStageMask,
+ vk::DependencyFlags dependencyFlags,
+ std::vector<vk::MemoryBarrier> memoryBarriers,
+ std::vector<vk::BufferMemoryBarrier> bufferBarriers,
+ std::vector<vk::ImageMemoryBarrier> imageBarriers )
+ {
+ /*
+ * Track resources
+ */
+ if( !imageBarriers.empty() )
+ {
+ for( auto&& imageBarrier : imageBarriers )
+ {
+ ImageRef imageResource{};
+ if( imageResource = mGraphics.FindImage( imageBarrier.image ) )
+ {
+ PushResource( imageResource );
+ }
+ }
+ }
+ //@ todo other resource tracking
+
+ mCommandBuffer.pipelineBarrier( srcStageMask, dstStageMask, dependencyFlags, memoryBarriers, bufferBarriers, imageBarriers );
+ }
+
+ void CopyBufferToImage( BufferRef srcBuffer, ImageRef dstImage, vk::ImageLayout dstLayout, std::vector<vk::BufferImageCopy> regions )
+ {
+ PushResource( srcBuffer );
+ PushResource( dstImage );
+
+ mCommandBuffer.copyBufferToImage( srcBuffer->GetVkBuffer(), dstImage->GetVkImage(), dstLayout, regions );
+ }
+
+ vk::ImageMemoryBarrier ImageLayoutTransitionBarrier( ImageRef image,
+ const vk::AccessFlags& srcAccessMask,
+ const vk::AccessFlags& dstAccessMask,
+ vk::ImageLayout oldLayout,
+ vk::ImageLayout newLayout,
+ const vk::ImageAspectFlags& aspectMask
+ ) const
+ {
+ return vk::ImageMemoryBarrier{}
+ .setNewLayout( newLayout )
+ .setImage( image->GetVkImage() )
+ .setOldLayout( oldLayout )
+ .setSrcAccessMask( srcAccessMask )
+ .setDstAccessMask( dstAccessMask )
+ .setSubresourceRange( vk::ImageSubresourceRange{ aspectMask, 0, image->GetLevelCount(), 0, image->GetLayerCount() } );
+ }
+
+
Graphics& mGraphics;
CommandPool& mOwnerCommandPool;
vk::CommandBufferAllocateInfo mAllocateInfo{};
vk::RenderPass mCurrentRenderPass;
+ FenceRef mFinishedFence;
+
bool mRecording{false};
};
mImpl->Free();
}
-/** Records image layout transition barrier for one image */
-void CommandBuffer::ImageLayoutTransition( vk::Image image,
- vk::ImageLayout oldLayout,
- vk::ImageLayout newLayout,
- vk::ImageAspectFlags aspectMask )
+void CommandBuffer::OnRelease( uint32_t refcount )
{
- mImpl->ImageLayoutTransition( image, oldLayout, newLayout, aspectMask );
+ VkManaged::OnRelease( refcount );
}
-/*
-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 )
-{
- mImpl->RecordImageLayoutTransition(
- image, srcAccessMask, dstAccessMask, srcStageMask, dstStageMask, oldLayout, newLayout, aspectMask );
-}
-*/
/** Push wait semaphores */
void CommandBuffer::PushWaitSemaphores( const std::vector<vk::Semaphore>& semaphores,
const std::vector<vk::PipelineStageFlags>& stages )
mImpl->ExecuteCommands( commandBuffers );
}
+void CommandBuffer::PipelineBarrier( vk::PipelineStageFlags srcStageMask,
+ vk::PipelineStageFlags dstStageMask,
+ vk::DependencyFlags dependencyFlags,
+ std::vector<vk::MemoryBarrier> memoryBarriers,
+ std::vector<vk::BufferMemoryBarrier> bufferBarriers,
+ std::vector<vk::ImageMemoryBarrier> imageBarriers )
+{
+ mImpl->PipelineBarrier( srcStageMask, dstStageMask, dependencyFlags, memoryBarriers, bufferBarriers, imageBarriers );
+}
+
+void CommandBuffer::CopyBufferToImage( BufferRef srcBuffer, ImageRef dstImage,
+ vk::ImageLayout dstLayout, std::vector<vk::BufferImageCopy> regions )
+{
+ mImpl->CopyBufferToImage( srcBuffer, dstImage, dstLayout, regions );
+}
+
+vk::ImageMemoryBarrier CommandBuffer::ImageLayoutTransitionBarrier( ImageRef image,
+ vk::AccessFlags srcAccessMask,
+ vk::AccessFlags dstAccessMask,
+ vk::ImageLayout oldLayout,
+ vk::ImageLayout newLayout,
+ vk::ImageAspectFlags aspectMask
+) const
+{
+ return mImpl->ImageLayoutTransitionBarrier( image,
+ srcAccessMask, dstAccessMask,
+ oldLayout, newLayout,
+ aspectMask );
+}
+
+vk::ImageMemoryBarrier CommandBuffer::ImageLayoutTransitionBarrier( ImageRef image,
+ vk::ImageLayout newLayout,
+ vk::ImageAspectFlags aspectMask
+) const
+{
+
+ vk::AccessFlags srcAccessMask, dstAccessMask;
+ vk::PipelineStageFlags srcStageMask, dstStageMask;
+
+ auto oldLayout = image->GetVkImageLayout();
+
+ switch( oldLayout )
+ {
+ case vk::ImageLayout::ePreinitialized:
+ case vk::ImageLayout::eUndefined:
+ {
+ srcAccessMask = {};
+ srcStageMask = vk::PipelineStageFlagBits::eTopOfPipe;
+ break;
+ }
+ case vk::ImageLayout::ePresentSrcKHR:
+ {
+ srcAccessMask = vk::AccessFlagBits::eColorAttachmentRead;
+ srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
+ break;
+ }
+ case vk::ImageLayout::eTransferSrcOptimal:
+ {
+ srcAccessMask = vk::AccessFlagBits::eMemoryRead;
+ srcStageMask = vk::PipelineStageFlagBits::eTransfer;
+ break;
+ }
+ case vk::ImageLayout::eTransferDstOptimal:
+ {
+ srcAccessMask = vk::AccessFlagBits::eMemoryWrite;
+ srcStageMask = vk::PipelineStageFlagBits::eTransfer;
+ break;
+ }
+ case vk::ImageLayout::eGeneral:
+ case vk::ImageLayout::eColorAttachmentOptimal:
+ case vk::ImageLayout::eDepthStencilAttachmentOptimal:
+ case vk::ImageLayout::eDepthStencilReadOnlyOptimal:
+ case vk::ImageLayout::eShaderReadOnlyOptimal:
+ case vk::ImageLayout::eSharedPresentKHR:
+ {
+ break;
+ }
+ }
+
+ switch( newLayout )
+ {
+ case vk::ImageLayout::ePresentSrcKHR:
+ {
+ dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
+ dstStageMask = vk::PipelineStageFlagBits::eBottomOfPipe;
+ break;
+ }
+ case vk::ImageLayout::eTransferSrcOptimal:
+ {
+ dstAccessMask = vk::AccessFlagBits::eMemoryRead;
+ dstStageMask = vk::PipelineStageFlagBits::eTransfer;
+ break;
+ }
+ case vk::ImageLayout::eTransferDstOptimal:
+ {
+ dstAccessMask = vk::AccessFlagBits::eMemoryWrite;
+ dstStageMask = vk::PipelineStageFlagBits::eTransfer;
+ break;
+ }
+ case vk::ImageLayout::eShaderReadOnlyOptimal:
+ {
+ dstAccessMask = vk::AccessFlagBits::eMemoryRead;
+ dstStageMask = vk::PipelineStageFlagBits::eVertexShader;
+ break;
+ }
+ case vk::ImageLayout::eUndefined:
+ case vk::ImageLayout::eGeneral:
+ case vk::ImageLayout::eColorAttachmentOptimal:
+ case vk::ImageLayout::eDepthStencilAttachmentOptimal:
+ case vk::ImageLayout::eDepthStencilReadOnlyOptimal:
+ case vk::ImageLayout::ePreinitialized:
+ case vk::ImageLayout::eSharedPresentKHR:
+ {
+ break;
+ }
+ }
+
+ return mImpl->ImageLayoutTransitionBarrier( image,
+ srcAccessMask, dstAccessMask,
+ oldLayout, newLayout,
+ aspectMask );
+}
+
} // namespace Vulkan
} // namespace Graphics
} // namespace Dali
/** Free command buffer */
void Free();
- /** Records image layout transition barrier for one image */
- void ImageLayoutTransition(vk::Image image, vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageAspectFlags aspectMask);
-
/** Push wait semaphores */
void PushWaitSemaphores(const std::vector< vk::Semaphore >& semaphores,
const std::vector< vk::PipelineStageFlags >& stages);
void EndRenderPass();
/**
+ * Records pipeline barrier
+ * @param srcStageMask
+ * @param dstStageMask
+ * @param dependencyFlags
+ * @param memoryBarriers
+ * @param bufferBarriers
+ * @param imageBarriers
+ */
+ void PipelineBarrier( vk::PipelineStageFlags srcStageMask,
+ vk::PipelineStageFlags dstStageMask,
+ vk::DependencyFlags dependencyFlags,
+ std::vector<vk::MemoryBarrier> memoryBarriers,
+ std::vector<vk::BufferMemoryBarrier> bufferBarriers,
+ std::vector<vk::ImageMemoryBarrier> imageBarriers );
+
+ /**
* Executes secondary command buffers within primary command buffer
* @param commandBuffers
*/
void ExecuteCommands( std::vector<Dali::Graphics::Vulkan::Handle<CommandBuffer>> commandBuffers );
-private:
+ /**
+ * Copies buffer into the specified image
+ * @param srcBuffer
+ * @param dstImage
+ * @param dtsLayout
+ * @param regions
+ */
+ void CopyBufferToImage( BufferRef srcBuffer, ImageRef dstImage, vk::ImageLayout dstLayout,
+ std::vector<vk::BufferImageCopy> regions );
+
+ void OnRelease( uint32_t refcount ) override;
/**
- *
+ * Creates layout transition barrier
+ * @return
+ */
+ vk::ImageMemoryBarrier ImageLayoutTransitionBarrier( ImageRef image,
+ vk::AccessFlags srcAccessMask,
+ vk::AccessFlags dstAccessMask,
+ vk::ImageLayout oldLayout,
+ vk::ImageLayout newLayout,
+ vk::ImageAspectFlags aspectMask
+ ) const;
+
+ /**
+ * Simplified version of memory barrier generation based on data stored inside the Image
* @param image
- * @param srcAccessMask
- * @param dstAccessMask
- * @param srcStageMask
- * @param dstStageMask
- * @param oldLayout
* @param newLayout
* @param aspectMask
+ * @return
*/
- 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::ImageMemoryBarrier ImageLayoutTransitionBarrier( ImageRef image,
+ vk::ImageLayout newLayout,
+ vk::ImageAspectFlags aspectMask
+ ) const;
private:
mAllocatedCommandBuffers.clear();
}
- Handle<CommandBuffer> NewCommandBuffer( const vk::CommandBufferAllocateInfo& allocateInfo )
+ CommandBufferRef NewCommandBuffer( const vk::CommandBufferAllocateInfo& allocateInfo )
{
vk::CommandBufferAllocateInfo info( allocateInfo );
info.setCommandPool( mCommandPool );
return mAllocatedCommandBuffers.back();
}
+ bool ReleaseCommandBuffer( const CommandBufferRef& buffer, bool forceRelease )
+ {
+ if( buffer.GetRefCount() == 2 )
+ {
+ for(auto&& cmdBuf : mAllocatedCommandBuffers )
+ {
+ if(cmdBuf == buffer )
+ {
+ // fixme: should remove from list but in future the cache of command buffer will work
+ // different
+ cmdBuf.Reset();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
Graphics& mGraphics;
CommandPool& mInterface;
vk::CommandPoolCreateInfo mCreateInfo;
vk::CommandPool mCommandPool;
- std::vector<Handle<CommandBuffer>> mAllocatedCommandBuffers;
+ std::vector<CommandBufferRef> mAllocatedCommandBuffers;
};
/**
mImpl->Reset( releaseResources );
}
+bool CommandPool::ReleaseCommandBuffer( CommandBufferRef buffer, bool forceRelease )
+{
+ return mImpl->ReleaseCommandBuffer( buffer, forceRelease );
+}
+
} // namespace Vulkan
} // namespace Graphics
} // namespace Dali
*/
CommandBufferRef NewCommandBuffer( bool isPrimary = true );
+ /**
+ * Releases command buffer
+ * @param buffer
+ * @return
+ */
+ bool ReleaseCommandBuffer( CommandBufferRef buffer, bool forceRelease );
+
public:
bool OnDestroy() override;
#include <dali/graphics/vulkan/vulkan-graphics.h>
#include <dali/graphics/vulkan/vulkan-image.h>
+
namespace Dali
{
namespace Graphics
Impl( Framebuffer& owner, Graphics& graphics, uint32_t width, uint32_t height )
: mInterface( owner ), mGraphics( graphics ), mColorImageViewAttachments{}, mDepthStencilImageViewAttachment()
{
+ mWidth = width;
+ mHeight = height;
}
- // Framebuffer creation may be deferred
+ // creating render pass may happen either as deferred or
+ // when framebuffer is initialised into immutable state
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
bool Initialise()
{
- if( mInitialised )
+ mAttachmentReference.clear();
+ mAttachmentDescription.clear();
+ mDefaultClearValues.clear();
+ /*
+ * COLOR ATTACHMENTS
+ */
+ auto attachments = std::vector<vk::ImageView>{};
+ auto colorAttachmentSize = 0u;
+ for( auto&& colorAttachment : mColorImageViewAttachments )
{
- return true;
+ auto attRef = vk::AttachmentReference{};
+ attRef.setLayout( vk::ImageLayout::eColorAttachmentOptimal );
+ attRef.setAttachment( colorAttachmentSize++ );
+ mAttachmentReference.emplace_back( attRef );
+ attachments.emplace_back( colorAttachment->GetVkImageView() );
+
+ vk::AttachmentDescription attDesc{};
+ attDesc.setSamples( vk::SampleCountFlagBits::e1 )
+ .setInitialLayout( vk::ImageLayout::eColorAttachmentOptimal )
+ .setFormat( colorAttachment->GetImage()->GetVkFormat() )
+ .setStencilStoreOp( vk::AttachmentStoreOp::eDontCare )
+ .setStencilLoadOp( vk::AttachmentLoadOp::eDontCare )
+ .setLoadOp( vk::AttachmentLoadOp::eClear )
+ .setStoreOp( vk::AttachmentStoreOp::eStore )
+ .setFinalLayout( vk::ImageLayout::ePresentSrcKHR );
+
+ mAttachmentDescription.emplace_back( attDesc );
+
+ // update clear color values
+ vk::ClearColorValue clear;
+ clear.setFloat32( {0.0f, 0.0f, 0.0f, 1.0f} );
+ mDefaultClearValues.emplace_back( clear );
}
- if( !Validate() )
+ /*
+ * DEPTH-STENCIL ATTACHMENT
+ */
+ if( mDepthStencilImageViewAttachment )
{
- return false;
+ auto attRef = vk::AttachmentReference{};
+ attRef.setLayout( vk::ImageLayout::eDepthStencilAttachmentOptimal );
+ attRef.setAttachment( colorAttachmentSize );
+ mAttachmentReference.emplace_back( attRef );
+ attachments.emplace_back( mDepthStencilImageViewAttachment->GetVkImageView() );
+
+ vk::AttachmentDescription attDesc{};
+ attDesc.setSamples( vk::SampleCountFlagBits::e1 )
+ .setInitialLayout( vk::ImageLayout::eDepthStencilAttachmentOptimal )
+ .setFormat( mDepthStencilImageViewAttachment->GetImage()->GetVkFormat() )
+ .setStencilStoreOp( vk::AttachmentStoreOp::eDontCare )
+ .setStencilLoadOp( vk::AttachmentLoadOp::eDontCare )
+ .setLoadOp( vk::AttachmentLoadOp::eClear )
+ .setStoreOp( vk::AttachmentStoreOp::eDontCare )
+ .setFinalLayout( vk::ImageLayout::eDepthStencilAttachmentOptimal );
+ mAttachmentDescription.emplace_back( attDesc );
+
+ // update clear depth/stencil values
+ vk::ClearDepthStencilValue clear;
+ clear.setDepth( 0.0f ).setStencil( 1.0f );
+ mDefaultClearValues.emplace_back( clear );
}
/*
- 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;
- }
-
- // creating render pass may happen either as deferred or
- // when framebuffer is initialised into immutable state
- void CreateRenderPass()
- {
- // for each attachment...
-#if 0
- auto attRef = vk::AttachmentReference{};
-
- // 1. Need to know layout during render pass ( Image::GetLayout() )
- // 2. Usually it's going to be:
- // - color_attachment_optimal
- // - depth_stencil_attachment_optimal
- //attRef.setLayout();
- //attRef.setAttachment();
-
- // Single subpass support, all attachments used
- // TODO: input, preserve, resolve
- // TODO: create subpasses
-
+ * SUBPASS
+ */
// 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 );
+ subpassDesc.setColorAttachmentCount( colorAttachmentSize );
+ if( mDepthStencilImageViewAttachment )
+ {
+ subpassDesc.setPDepthStencilAttachment( &mAttachmentReference[colorAttachmentSize] );
+ }
+ subpassDesc.setPColorAttachments( &mAttachmentReference[0] );
+ /*
+ * RENDERPASS
+ */
// create compatible render pass
auto rpInfo = vk::RenderPassCreateInfo{};
- //rpInfo.setAttachmentCount( mAttachments.size() );
- //rpInfo.setPAttachments( )
- rpInfo.setDependencyCount( 0 );
- rpInfo.setPDependencies( nullptr );
+ rpInfo.setAttachmentCount( U32(mAttachmentDescription.size()) );
+ rpInfo.setPAttachments( mAttachmentDescription.data() );
rpInfo.setPSubpasses( &subpassDesc );
rpInfo.setSubpassCount( 1 );
-#endif
- }
-
- void InitialiseAttachments()
- {
- ImageRef attachment;
- vk::ImageViewCreateInfo info;
- info.setViewType( vk::ImageViewType::e2D );
- info.setSubresourceRange( //get layercount, get level count
- vk::ImageSubresourceRange{}.setLevelCount( 1 ).setLayerCount( 1 ).setBaseMipLevel( 0 ).setBaseArrayLayer( 0 ) );
- info.setImage( attachment->GetVkImage() ); //
- info.setComponents( vk::ComponentMapping(
- vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA ) );
- info.setFormat( vk::Format::eD16Unorm ); // get format
-
- //ImageViewRef ref = ImageView::New( attachment );
- }
-
- void CreateFramebuffer()
- {
- // assert if framebuffer is already created
- InitialiseAttachments();
+ mVkRenderPass = VkAssert( mGraphics.GetDevice().createRenderPass( rpInfo, mGraphics.GetAllocator() ));
+ /*
+ * FRAMEBUFFER
+ */
vk::FramebufferCreateInfo info;
info.setRenderPass( mVkRenderPass )
- .setPAttachments( nullptr ) // attach imageviews, imageviews are created from supplied images
- .setLayers( 1 )
- .setWidth( mWidth )
- .setHeight( mHeight )
- .setAttachmentCount( 1 );
+ .setPAttachments( attachments.data() )
+ .setLayers( 1 )
+ .setWidth( mWidth )
+ .setHeight( mHeight )
+ .setAttachmentCount( U32(attachments.size()) );
mVkFramebuffer = VkAssert( mGraphics.GetDevice().createFramebuffer( info, mGraphics.GetAllocator() ) );
+
+ return true;
+ }
+#pragma GCC diagnostic pop
+
+ /**
+ * Creates immutable framebuffer object
+ */
+ bool Commit()
+ {
+ if(!mInitialised)
+ {
+ mInitialised = Initialise();
+ return mInitialised;
+ }
+ return false;
}
void SetAttachment( ImageViewRef imageViewRef, Framebuffer::AttachmentType type, uint32_t index )
}
}
- ImageViewRef GetAttachmentImageView( AttachmentType type, uint32_t index ) const
+ ImageViewRef GetAttachment( AttachmentType type, uint32_t index ) const
{
switch( type )
{
return ImageViewRef();
}
- bool Validate()
+ std::vector<ImageViewRef> GetAttachments( AttachmentType type ) const
{
- if( mWidth == 0u || mHeight == 0 )
+ std::vector<ImageViewRef> retval{};
+ switch( type )
{
- return false;
+ case AttachmentType::COLOR:
+ {
+ retval.insert( retval.end(), mColorImageViewAttachments.begin(), mColorImageViewAttachments.end() );
+ return retval;
+ }
+ case AttachmentType::DEPTH_STENCIL:
+ {
+ retval.push_back( mDepthStencilImageViewAttachment );
+ return retval;
+ }
+ case AttachmentType::DEPTH:
+ case AttachmentType::INPUT:
+ case AttachmentType::RESOLVE:
+ case AttachmentType::PRESERVE:
+ {
+ return retval;
+ }
+ }
+ return retval;
+ }
+
+ uint32_t GetAttachmentCount( AttachmentType type ) const
+ {
+ std::vector<ImageViewRef> retval{};
+ switch( type )
+ {
+ case AttachmentType::COLOR:
+ {
+ return U32(mColorImageViewAttachments.size());
+ }
+ case AttachmentType::DEPTH_STENCIL:
+ {
+ return mDepthStencilImageViewAttachment ? 1u : 0u;
+ }
+ case AttachmentType::DEPTH:
+ case AttachmentType::INPUT:
+ case AttachmentType::RESOLVE:
+ case AttachmentType::PRESERVE:
+ {
+ return 0u;
+ }
}
+ return 0u;
}
- ~Impl()
+ const std::vector<vk::ClearValue>& GetDefaultClearValues() const
{
+ return mDefaultClearValues;
}
+ ~Impl() = default;
+
vk::RenderPass GetVkRenderPass() const
{
return mVkRenderPass;
vk::Framebuffer mVkFramebuffer;
vk::RenderPass mVkRenderPass;
+ // attachment references for the main subpass
+ std::vector<vk::AttachmentReference> mAttachmentReference;
+ std::vector<vk::AttachmentDescription> mAttachmentDescription;
+
+ std::vector<vk::ClearValue> mDefaultClearValues;
bool mInitialised{false};
};
FramebufferRef Framebuffer::New( Graphics& graphics, uint32_t width, uint32_t height )
{
- return FramebufferRef();
+ FramebufferRef ref( new Framebuffer( graphics, width, height ) );
+ return ref;
+}
+
+Framebuffer::Framebuffer( Graphics& graphics, uint32_t width, uint32_t height )
+{
+ mImpl = std::make_unique<Impl>( *this, graphics, width, height );
}
void Framebuffer::SetAttachment( ImageViewRef imageViewRef, Framebuffer::AttachmentType type, uint32_t index )
return mImpl->mHeight;
}
-Handle<ImageView> Framebuffer::GetAttachmentImageView( AttachmentType type, uint32_t index ) const
+ImageViewRef Framebuffer::GetAttachment( AttachmentType type, uint32_t index ) const
+{
+ return mImpl->GetAttachment( type, index );
+}
+
+std::vector<ImageViewRef> Framebuffer::GetAttachments( AttachmentType type ) const
+{
+ return mImpl->GetAttachments( type );
+}
+
+uint32_t Framebuffer::GetAttachmentCount( AttachmentType type ) const
+{
+ return mImpl->GetAttachmentCount( type );
+}
+
+void Framebuffer::Commit()
+{
+ mImpl->Commit();
+}
+
+vk::RenderPass Framebuffer::GetVkRenderPass() const
+{
+ return mImpl->mVkRenderPass;
+}
+
+vk::Framebuffer Framebuffer::GetVkFramebuffer() const
+{
+ return mImpl->mVkFramebuffer;
+}
+
+const std::vector<vk::ClearValue>& Framebuffer::GetDefaultClearValues() const
{
- return mImpl->GetAttachmentImageView( type, index );
+ return mImpl->GetDefaultClearValues();
}
} // Namespace Vulkan
uint32_t GetHeight() const;
- ImageViewRef GetAttachmentImageView( AttachmentType type, uint32_t index ) const;
+ ImageViewRef GetAttachment( AttachmentType type, uint32_t index ) const;
+
+ std::vector<ImageViewRef> GetAttachments( AttachmentType type ) const;
+
+ uint32_t GetAttachmentCount( AttachmentType type ) const;
void SetAttachment( ImageViewRef imageViewRef, Framebuffer::AttachmentType type, uint32_t index );
+ void Commit();
+
+ vk::RenderPass GetVkRenderPass() const;
+ vk::Framebuffer GetVkFramebuffer() const;
+
+ const std::vector<vk::ClearValue>& GetDefaultClearValues() const;
private:
- class Impl;
+ Framebuffer( Graphics& graphics, uint32_t width, uint32_t height );
+
+ struct Impl;
std::unique_ptr<Impl> mImpl;
};
#include <dali/graphics/vulkan/vulkan-graphics.h>
#include <dali/graphics/vulkan/vulkan-pipeline.h>
#include <dali/graphics/vulkan/vulkan-shader.h>
+#include <dali/graphics/vulkan/vulkan-framebuffer.h>
#include <dali/graphics/vulkan/vulkan-surface.h>
using namespace glm;
mDebugPipelineState.descriptorPool = CreateDescriptorPool();
- const float halfWidth = 0.5f;
+ const float halfWidth = 0.5f;
const float halfHeight = 0.5f;
-//#if 0
- const vec3 VERTICES[4] =
- {
- { halfWidth, halfHeight, 0.0f },
- { halfWidth, -halfHeight, 0.0f },
- { -halfWidth, halfHeight, 0.0f },
- { -halfWidth, -halfHeight, 0.0f },
- };
+ //#if 0
+ const vec3 VERTICES[4] = {
+ {halfWidth, halfHeight, 0.0f},
+ {halfWidth, -halfHeight, 0.0f},
+ {-halfWidth, halfHeight, 0.0f},
+ {-halfWidth, -halfHeight, 0.0f},
+ };
//#endif
#if 0
const vec3 VERTICES[4] = {
pipeline->SetShader( state.vertexShader, Shader::Type::VERTEX );
pipeline->SetShader( state.fragmentShader, Shader::Type::FRAGMENT );
- auto size = mGraphics.GetSurface( 0u ).GetSize();
+ auto size = mGraphics.GetSurface( 0u )->GetSize();
pipeline->SetViewport( 0, 0, static_cast<float>( size.width ), static_cast<float>( size.height ) );
pipeline->SetVertexInputState(
for( auto&& buf : bufferList.Get() )
{
// TODO: @todo implement minimum offset!
- const uint32_t sizeOfUniformBuffer = U32((buf->GetSize() / drawcalls.Get()));
- const uint32_t uniformBlockOffsetStride = ((sizeOfUniformBuffer / 256)+1)*256;
- const uint32_t uniformBlockMemoryNeeded = U32(uniformBlockOffsetStride*drawcalls.Get());
+ const uint32_t sizeOfUniformBuffer = U32( ( buf->GetSize() / drawcalls.Get() ) );
+ const uint32_t uniformBlockOffsetStride = ( ( sizeOfUniformBuffer / 256 ) + 1 ) * 256;
+ const uint32_t uniformBlockMemoryNeeded = U32( uniformBlockOffsetStride * drawcalls.Get() );
// create buffer if doesn't exist
if( !state.uniformBuffer0 )
mat4 mvp;
vec4 color;
vec3 size;
- } __attribute__((aligned(16)));
+ } __attribute__( ( aligned( 16 ) ) );
auto memory = state.uniformBuffer0->GetMemoryHandle();
auto outPtr = memory->MapTyped<char>();
for( auto i = 0u; i < drawcalls.Get(); ++i )
{
// copy chunk of data
- UB* inputData = (reinterpret_cast<UB*>(buf->GetDataBase())) + i;
- UB* outputData = (reinterpret_cast<UB*>(outPtr + (i*uniformBlockOffsetStride)));
- *outputData = *inputData;
+ UB* inputData = ( reinterpret_cast<UB*>( buf->GetDataBase() ) ) + i;
+ UB* outputData = ( reinterpret_cast<UB*>( outPtr + ( i * uniformBlockOffsetStride ) ) );
+ *outputData = *inputData;
auto descriptorSets = state.descriptorPool->AllocateDescriptorSets(
vk::DescriptorSetAllocateInfo{}.setDescriptorSetCount( 1 ).setPSetLayouts(
memory->Unmap();
// execute buffer
- mGraphics.GetSurface( 0u ).GetCurrentCommandBuffer()->ExecuteCommands( executeCommands );
+ mGraphics.GetSwapchainForFBID( 0u )->GetPrimaryCommandBuffer()->ExecuteCommands( executeCommands );
// break, one pass only
break;
#pragma GCC diagnostic pop
void BeginFrame()
{
- auto& surface = mGraphics.GetSurface( 0u );
- surface.AcquireNextImage();
+ auto surface = mGraphics.GetSurface( 0u );
+
+ auto swapchain = mGraphics.GetSwapchainForFBID( 0u );
+ swapchain->AcquireNextFramebuffer();
// rewind pools
mDebugPipelineState.drawPoolIndex = 0u;
void EndFrame()
{
- auto& surface = mGraphics.GetSurface( 0u );
- surface.Present();
+ auto swapchain = mGraphics.GetSwapchainForFBID( 0u );
+ swapchain->Present();
}
DescriptorPoolRef CreateDescriptorPool()
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_RENDERDOC_Capture",
+ //"VK_LAYER_LUNARG_parameter_validation", // parameter
//"VK_LAYER_LUNARG_vktrace", // vktrace ( requires vktrace connection )
- "VK_LAYER_LUNARG_monitor", // monitor
+ //"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_GOOGLE_unique_objects", // unique objects
"VK_LAYER_LUNARG_standard_validation", // standard
};
FBID Graphics::CreateSurface(std::unique_ptr< SurfaceFactory > surfaceFactory)
{
- const auto vkFactory = dynamic_cast< const VkSurfaceFactory* >(surfaceFactory.get());
- if(!vkFactory)
+ // create surface from the factory
+ auto surfaceRef = Surface::New( *this, std::move(surfaceFactory) );
+
+ if( surfaceRef->Create() )
{
- return FBID{0u};
+
+ // map surface to FBID
+ auto fbid = ++mBaseFBID;
+ mSurfaceFBIDMap[fbid] = SwapchainSurfacePair{ SwapchainRef{}, surfaceRef };
+ return fbid;
}
+ return -1;
+}
- auto surface = vkFactory->Create(mInstance, mAllocator.get(), mPhysicalDevice);
+SwapchainRef Graphics::CreateSwapchainForSurface( SurfaceRef surface )
+{
+ auto swapchain = Swapchain::New( *this,
+ GetGraphicsQueue(0u),
+ surface, 2, 0 );
+
+ // store swapchain in the correct pair
+ for( auto&& val : mSurfaceFBIDMap )
+ {
+ if( val.second.surface == surface )
+ {
+ val.second.swapchain = swapchain;
+ break;
+ }
+ }
+
+ return swapchain;
+}
+
+SwapchainRef Graphics::GetSwapchainForSurface( SurfaceRef surface )
+{
+ for( auto&& val : mSurfaceFBIDMap )
+ {
+ if( val.second.surface == surface )
+ {
+ return val.second
+ .swapchain;
+ }
+ }
+ return SwapchainRef();
+}
- // map surface to FBID
- auto fbid = ++mBaseFBID;
- mSurfaceFBIDMap[fbid] = MakeUnique<Surface>(*this, surface, 3u);
- return fbid;
+SwapchainRef Graphics::GetSwapchainForFBID( FBID surfaceId )
+{
+ if(surfaceId == 0)
+ {
+ return mSurfaceFBIDMap.begin()->second.swapchain;
+ }
+ return mSurfaceFBIDMap[surfaceId].swapchain;
}
#pragma GCC diagnostic push
{
transferFamily = queueFamilyIndex;
}
- if(mPhysicalDevice.getSurfaceSupportKHR(queueFamilyIndex, mSurfaceFBIDMap.begin()->second.get()->GetSurfaceKHR())
+ if(mPhysicalDevice.getSurfaceSupportKHR(queueFamilyIndex, mSurfaceFBIDMap.begin()->second.surface->GetSurfaceKHR())
.value &&
presentFamily == -1u)
{
Queue& Graphics::GetPresentQueue() const
{
- return *mPresentQueue.get();
+ // fixme: should be a dedicated presentation queue
+ return GetGraphicsQueue(0);
}
Handle< CommandPool > Graphics::CreateCommandPool(const vk::CommandPoolCreateInfo& info)
return cmdpool;
}
-Surface& Graphics::GetSurface( FBID surfaceId )
+SurfaceRef 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.begin()->second.surface;
}
- return *mSurfaceFBIDMap[surfaceId].get();
+ return mSurfaceFBIDMap[surfaceId].surface;
}
// TODO: all this stuff should go into some vulkan cache
NotImplemented();
}
-Handle<Shader> Graphics::FindShader( vk::ShaderModule shaderModule )
+ShaderRef Graphics::FindShader( vk::ShaderModule shaderModule )
{
for( auto&& iter : mShaderCache )
{
return Handle<Shader>();
}
+ImageRef Graphics::FindImage( vk::Image image )
+{
+ for( auto&& iter : mImageCache )
+ {
+ if( iter->GetVkImage() == image )
+ {
+ return ImageRef(&*iter);
+ }
+ }
+ return ImageRef();
+}
+
+
} // namespace Vulkan
} // namespace Graphics
// INTERNAL INCLUDES
#include <dali/graphics/vulkan/vulkan-types.h>
#include <dali/integration-api/graphics/surface-factory.h>
-
+#include <dali/graphics/vulkan/vulkan-swapchain.h>
namespace Dali
{
namespace Graphics
class GpuMemoryManager;
class Controller;
+struct SwapchainSurfacePair
+{
+ SwapchainRef swapchain;
+ SurfaceRef surface;
+};
+
class Graphics
{
// new way
FBID CreateSurface(std::unique_ptr< SurfaceFactory > surfaceFactory);
- Surface& GetSurface( FBID surfaceId );
+ SwapchainRef CreateSwapchainForSurface( SurfaceRef surface );
+
+ SurfaceRef GetSurface( FBID surfaceId );
+
+ SwapchainRef GetSwapchainForSurface( SurfaceRef surface );
+
+ SwapchainRef GetSwapchainForFBID( FBID surfaceId );
void CreateDevice();
// queue family properties
std::vector< vk::QueueFamilyProperties > mQueueFamilyProperties;
- std::unordered_map< FBID, UniqueSurface > mSurfaceFBIDMap;
+ std::unordered_map< FBID, SwapchainSurfacePair > mSurfaceFBIDMap;
FBID mBaseFBID{0u};
// Sets of queues
std::vector< std::unique_ptr<Queue> > mGraphicsQueues;
std::vector< std::unique_ptr<Queue> > mTransferQueues;
std::vector< std::unique_ptr<Queue> > mComputeQueues;
- std::unique_ptr< Queue > mPresentQueue;
+ //std::unique_ptr< Queue > mPresentQueue;
Platform mPlatform { Platform::UNDEFINED };
public:
// TODO: all this stuff should go into some vulkan cache
- void AddBuffer( Handle<Buffer> buffer );
- void AddImage( Handle<Image> image );
- void AddPipeline( Handle<Pipeline> pipeline );
- void AddShader( Handle<Shader> shader );
- void AddCommandPool( Handle<CommandPool> pool );
- void AddDescriptorPool( Handle<DescriptorPool> pool );
- void AddFramebuffer( Handle<Framebuffer> framebuffer );
+ void AddBuffer( BufferRef buffer );
+ void AddImage( ImageRef image );
+ void AddPipeline( PipelineRef pipeline );
+ void AddShader( ShaderRef shader );
+ void AddCommandPool( CommandPoolRef pool );
+ void AddDescriptorPool( DescriptorPoolRef pool );
+ void AddFramebuffer( FramebufferRef framebuffer );
ShaderRef FindShader( vk::ShaderModule shaderModule );
+ ImageRef FindImage( vk::Image image );
void RemoveBuffer( Buffer& buffer );
void RemoveShader( Shader& shader );
#include <dali/graphics/vulkan/vulkan-graphics.h>
#include <dali/graphics/vulkan/vulkan-image.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.h>
namespace Dali
{
return true;
}
+ void BindMemory( const GpuMemoryBlockRef& handle )
+ {
+ mGraphics.GetDevice().bindImageMemory( mVkImage, *handle, 0 );
+ mDeviceMemory = handle;
+ }
+
Image& mOwner;
Graphics& mGraphics;
vk::Image mVkImage;
vk::ImageLayout mVkImageLayout;
vk::ImageCreateInfo mCreateInfo;
+ GpuMemoryBlockRef mDeviceMemory;
bool mIsExternal;
};
return mImpl->mCreateInfo.tiling;
}
-void Image::BindMemory( GpuMemoryBlockRef& handle )
+void Image::BindMemory( const GpuMemoryBlockRef& handle )
+{
+ mImpl->BindMemory( handle );
+}
+
+vk::ImageUsageFlags Image::GetVkImageUsageFlags() const
{
+ return mImpl->mCreateInfo.usage;
}
/***************************************************************************
ImageViewRef ImageView::New( Graphics& graphics, ImageRef image, vk::ImageViewCreateInfo info )
{
auto retval = ImageViewRef( new ImageView( graphics, image, info ) );
- if(!retval->mImpl->Initialise())
+ if( !retval->mImpl->Initialise() )
{
return ImageViewRef();
}
return retval;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
ImageViewRef ImageView::New( Graphics& graphics, ImageRef image )
{
- // create reference, image may be null
- auto retval = ImageViewRef( new ImageView( graphics, image, vk::ImageViewCreateInfo{} ) );
- if(image)
+ vk::ImageAspectFlags aspectFlags{};
+ if( image->GetVkImageUsageFlags() & vk::ImageUsageFlagBits::eColorAttachment )
{
+ aspectFlags |= vk::ImageAspectFlagBits::eColor;
+ }
+ if( image->GetVkImageUsageFlags() & vk::ImageUsageFlagBits::eDepthStencilAttachment )
+ {
+ aspectFlags |= (vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil);
+ }
+
+ auto subresourceRange = vk::ImageSubresourceRange{}
+ .setAspectMask( aspectFlags )
+ .setBaseArrayLayer( 0 )
+ .setBaseMipLevel( 0 )
+ .setLevelCount( image->GetLevelCount() )
+ .setLayerCount( image->GetLayerCount() );
+ // create reference, image may be null
+ auto retval = ImageViewRef( new ImageView( graphics,
+ image,
+ vk::ImageViewCreateInfo{}
+ .setViewType( vk::ImageViewType::e2D )
+ .setFormat( image->GetVkFormat() )
+ .setSubresourceRange(subresourceRange)
+ .setComponents( { vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB,vk::ComponentSwizzle::eA } )
+ .setImage( image->GetVkImage() )));
+ if(!retval->mImpl->Initialise())
+ {
+ return ImageViewRef();
}
+
return retval;
}
+#pragma GCC diagnostic pop
ImageView::ImageView( Graphics& graphics, ImageRef image, const VkImageViewCreateInfo& createInfo )
{
mImpl = MakeUnique<Impl>( *this, graphics, image, createInfo );
}
+
ImageView::~ImageView() = default;
const vk::ImageView& ImageView::GetVkImageView() const
namespace Vulkan
{
class ImageView;
+using InternalVkImage = vk::Image;
class Image : public VkManaged
{
public:
vk::ImageTiling GetVkImageTiling() const;
/**
+ *
+ * @return
+ */
+ vk::ImageUsageFlags GetVkImageUsageFlags() const;
+
+ /**
* Binds image memory
* @param handle
*/
- void BindMemory( GpuMemoryBlockRef& handle );
+ void BindMemory( const GpuMemoryBlockRef& handle );
/**
* Creates new VkImage with given specification, it doesn't
*/
Image( Graphics& graphics, const vk::ImageCreateInfo& createInfo, vk::Image externalImage );
+ operator InternalVkImage() const
+ {
+ return GetVkImage();
+ }
+
private:
class Impl;
std::unique_ptr<Impl> mImpl;
#include <dali/graphics/vulkan/vulkan-pipeline.h>
#include <dali/graphics/vulkan/vulkan-graphics.h>
#include <dali/graphics/vulkan/vulkan-surface.h>
+#include <dali/graphics/vulkan/vulkan-framebuffer.h>
#include <dali/graphics/vulkan/vulkan-descriptor-set.h>
#include <dali/graphics/vulkan/spirv/vulkan-spirv.h>
// in place of swapchain structures!
if( !mInfo.renderPass )
{
- SetRenderPass( mGraphics.GetSurface( 0 ).GetRenderPass() );
+ SetRenderPass( mGraphics.GetSwapchainForFBID(0u)->
+ GetCurrentFramebuffer()->GetVkRenderPass());
}
SetRasterizationState();
info.setPWaitSemaphores(semaphores.waitSemaphores.data());
info.setPWaitDstStageMask(semaphores.waitDstStageMasks.data());
- VkAssert(mQueue.submit(1, &info, fence->GetFence()));
+ VkAssert(mQueue.submit(1, &info, fence ? fence->GetFence() : nullptr ));
return MakeUnique< Submission >(fence);
}
namespace VulkanTest
{
Dali::Graphics::Vulkan::GpuMemoryBlockRef test_gpu_memory_manager(
- Dali::Graphics::Vulkan::Graphics& graphics,
- GpuMemoryManager& gpuManager,
- const Dali::Graphics::Vulkan::Handle<Buffer>& buffer )
+ Dali::Graphics::Vulkan::Graphics &graphics,
+ GpuMemoryManager &gpuManager,
+ const Dali::Graphics::Vulkan::Handle<Buffer> &buffer)
{
- auto device = graphics.GetDevice();
- auto& allocator = graphics.GetAllocator();
+ auto device = graphics.GetDevice();
+ auto &allocator = graphics.GetAllocator();
- auto& gpuAllocator = gpuManager.GetDefaultAllocator();
- return gpuAllocator.Allocate( buffer, vk::MemoryPropertyFlagBits::eHostVisible );
+ auto &gpuAllocator = gpuManager.GetDefaultAllocator();
+ return gpuAllocator.Allocate(buffer, vk::MemoryPropertyFlagBits::eHostVisible);
}
struct UniformData
mat4 mvp;
vec4 color;
vec3 size;
-} __attribute__( ( aligned( 16 ) ) );
+} __attribute__(( aligned( 16 )));
struct UniformClipData
{
mat4 clip;
-} __attribute__( ( aligned( 16 ) ) );
+} __attribute__(( aligned( 16 )));
mat4 MVP;
template<class T>
-void update_buffer( Dali::Graphics::Vulkan::BufferRef buffer, T& value )
+void update_buffer(Dali::Graphics::Vulkan::BufferRef buffer, T &value)
{
- auto ptr = reinterpret_cast<T*>( buffer->GetMemoryHandle()->Map() );
- *ptr = value;
- buffer->GetMemoryHandle()->Unmap();
+ auto ptr = reinterpret_cast<T *>( buffer->GetMemoryHandle()
+ ->Map());
+ *ptr = value;
+ buffer->GetMemoryHandle()
+ ->Unmap();
}
-void update_translation( Dali::Graphics::Vulkan::BufferRef buffer )
+void update_translation(Dali::Graphics::Vulkan::BufferRef buffer)
{
static float x = 0.0f;
x += 0.5f;
lookAt( vec3( 0.0f, 0.0f, 10.0f ), vec3( 0.0f, 0.0f, 0.0f ), vec3( 0.0f, 1.0f, 0.0f ) ) * modelMat;
update_buffer( buffer, ub );
- */
+ */
}
-Dali::Graphics::Vulkan::BufferRef create_uniform_buffer( Dali::Graphics::Vulkan::Graphics& gr )
+Dali::Graphics::Vulkan::BufferRef create_uniform_buffer(Dali::Graphics::Vulkan::Graphics &gr)
{
// create uniform buffer
- auto uniformBuffer = Buffer::New( gr, sizeof( UniformData ), Buffer::Type::UNIFORM );
+ auto uniformBuffer = Buffer::New(gr, sizeof(UniformData), Buffer::Type::UNIFORM);
// allocate memory
- auto memory = gr.GetDeviceMemoryManager().GetDefaultAllocator().Allocate( uniformBuffer,
- vk::MemoryPropertyFlagBits::eHostVisible );
+ auto memory = gr.GetDeviceMemoryManager()
+ .GetDefaultAllocator()
+ .Allocate(uniformBuffer,
+ vk::MemoryPropertyFlagBits::eHostVisible);
// bind memory
- uniformBuffer->BindMemory( memory );
+ uniformBuffer->BindMemory(memory);
- auto ub = reinterpret_cast<UniformData*>( memory->Map() );
+ auto ub = reinterpret_cast<UniformData *>( memory->Map());
- ub->mvp = mat4{1.0f} * ortho( 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 100.0f ) *
- lookAt( vec3( 0.0f, 0.0f, 10.0f ), vec3( 0.0f, 0.0f, 0.0f ), vec3( 0.0f, 1.0f, 0.0f ) );
- ub->color = vec4( 0.0f, 1.0f, 1.0f, 1.0f );
- ub->size = vec3( 1.0f, 1.0f, 1.0f );
+ ub->mvp = mat4{1.0f} * ortho(0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 100.0f) *
+ lookAt(vec3(0.0f, 0.0f, 10.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f));
+ ub->color = vec4(0.0f, 1.0f, 1.0f, 1.0f);
+ ub->size = vec3(1.0f, 1.0f, 1.0f);
memory->Unmap();
return uniformBuffer;
}
-Dali::Graphics::Vulkan::BufferRef create_clip_buffer( Dali::Graphics::Vulkan::Graphics& gr )
+Dali::Graphics::Vulkan::BufferRef create_clip_buffer(Dali::Graphics::Vulkan::Graphics &gr)
{
const 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 );
+ 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);
// create uniform buffer
- auto uniformBuffer = Buffer::New( gr, sizeof( UniformClipData ), Buffer::Type::UNIFORM );
+ auto uniformBuffer = Buffer::New(gr, sizeof(UniformClipData), Buffer::Type::UNIFORM);
// allocate memory
- auto memory = gr.GetDeviceMemoryManager().GetDefaultAllocator().Allocate( uniformBuffer,
- vk::MemoryPropertyFlagBits::eHostVisible );
+ auto memory = gr.GetDeviceMemoryManager()
+ .GetDefaultAllocator()
+ .Allocate(uniformBuffer,
+ vk::MemoryPropertyFlagBits::eHostVisible);
// bind memory
- uniformBuffer->BindMemory( memory );
+ uniformBuffer->BindMemory(memory);
auto dst = memory->MapTyped<mat4>();
- std::copy( &clip, &clip + 1, dst );
+ std::copy(&clip, &clip + 1, dst);
memory->Unmap();
return uniformBuffer;
}
-Dali::Graphics::Vulkan::Handle<DescriptorPool> create_descriptor_pool( Dali::Graphics::Vulkan::Graphics& gr )
+Dali::Graphics::Vulkan::Handle<DescriptorPool> create_descriptor_pool(Dali::Graphics::Vulkan::Graphics &gr)
{
vk::DescriptorPoolSize size;
- size.setDescriptorCount( 1024 ).setType( vk::DescriptorType::eUniformBuffer );
+ 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 ) );
+ gr, vk::DescriptorPoolCreateInfo{}.setMaxSets(1024)
+ .setPoolSizeCount(1)
+ .setPPoolSizes(&size));
return pool;
}
-void test_framebuffer( Dali::Graphics::Vulkan::Graphics& graphics )
+void test_framebuffer(Dali::Graphics::Vulkan::Graphics &graphics)
{
using namespace Dali::Graphics::Vulkan;
// framebuffer
- auto fb = NewRef<Framebuffer>( graphics, 640, 480 );
+ auto fb = NewRef<Framebuffer>(graphics, 640, 480);
// attachment
- auto image = NewRef<Image>( graphics,
- vk::ImageCreateInfo{}
- .setFormat( vk::Format::eR32G32B32A32Sfloat )
- .setTiling( vk::ImageTiling::eOptimal )
- .setMipLevels( 1 )
- .setImageType( vk::ImageType::e2D )
- .setExtent( vk::Extent3D( 640, 480, 1 ) )
- .setArrayLayers( 1 )
- .setUsage( vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eColorAttachment )
- .setSharingMode( vk::SharingMode::eExclusive )
- .setInitialLayout( vk::ImageLayout::eUndefined )
- .setSamples( vk::SampleCountFlagBits::e1 ) );
+ auto image = NewRef<Image>(graphics,
+ vk::ImageCreateInfo{}
+ .setFormat(vk::Format::eR32G32B32A32Sfloat)
+ .setTiling(vk::ImageTiling::eOptimal)
+ .setMipLevels(1)
+ .setImageType(vk::ImageType::e2D)
+ .setExtent(vk::Extent3D(640, 480, 1))
+ .setArrayLayers(1)
+ .setUsage(vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eColorAttachment)
+ .setSharingMode(vk::SharingMode::eExclusive)
+ .setInitialLayout(vk::ImageLayout::eUndefined)
+ .setSamples(vk::SampleCountFlagBits::e1));
auto imageView = NewRef<ImageView>(
graphics,
image,
vk::ImageViewCreateInfo{}
- .setFormat( vk::Format::eR32G32B32A32Sfloat )
- .setComponents( vk::ComponentMapping(
- vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA ) )
- .setImage( image->GetVkImage() )
- .setSubresourceRange( vk::ImageSubresourceRange{}
- .setLayerCount( 1 )
- .setLevelCount( 1 )
- .setBaseMipLevel( 0 )
- .setBaseArrayLayer( 0 )
- .setAspectMask( vk::ImageAspectFlagBits::eColor ) )
- .setViewType( vk::ImageViewType::e2D ) );
-
- fb->SetAttachment( imageView, Framebuffer::AttachmentType::COLOR, 0u );
+ .setFormat(vk::Format::eR32G32B32A32Sfloat)
+ .setComponents(vk::ComponentMapping(
+ vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA))
+ .setImage(image->GetVkImage())
+ .setSubresourceRange(vk::ImageSubresourceRange{}
+ .setLayerCount(1)
+ .setLevelCount(1)
+ .setBaseMipLevel(0)
+ .setBaseArrayLayer(0)
+ .setAspectMask(vk::ImageAspectFlagBits::eColor))
+ .setViewType(vk::ImageViewType::e2D));
+
+ fb->SetAttachment(imageView, Framebuffer::AttachmentType::COLOR, 0u);
//fb->GetRenderPass();
handle.GetRefCount();*/
}
-PipelineRef create_pipeline( Dali::Graphics::Vulkan::Graphics& graphics,
- Dali::Graphics::Vulkan::ShaderRef vertexShader,
- Dali::Graphics::Vulkan::ShaderRef fragmentShader )
+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 );
+ 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->SetShader(vertexShader, Shader::Type::VERTEX);
+ pipeline->SetShader(fragmentShader, Shader::Type::FRAGMENT);
+ pipeline->SetViewport(0, 0, 640, 480);
pipeline->SetVertexInputState(
std::vector<vk::VertexInputAttributeDescription>{
- vk::VertexInputAttributeDescription{}.setBinding( 0 ).setOffset( 0 ).setLocation( 0 ).setFormat(
- vk::Format::eR32G32B32Sfloat )},
+ vk::VertexInputAttributeDescription{}.setBinding(0)
+ .setOffset(0)
+ .setLocation(0)
+ .setFormat(
+ vk::Format::eR32G32B32Sfloat)},
std::vector<vk::VertexInputBindingDescription>{vk::VertexInputBindingDescription{}
- .setBinding( 0 )
- .setStride( sizeof( float ) * 3 )
- .setInputRate( vk::VertexInputRate::eVertex )} );
- pipeline->SetInputAssemblyState( vk::PrimitiveTopology::eTriangleList, false );
+ .setBinding(0)
+ .setStride(sizeof(float) * 3)
+ .setInputRate(vk::VertexInputRate::eVertex)});
+ pipeline->SetInputAssemblyState(vk::PrimitiveTopology::eTriangleList, false);
- if( !pipeline->Compile() )
+ if (!pipeline->Compile())
{
pipeline.Reset();
}
return pipeline;
}
+int TextureTestMain( Dali::Graphics::Vulkan::Graphics& );
+
+int RunTestMain2()
+{
+#if USE_XLIB == 1
+ auto window = Test::create_xlib_window( 640, 480 );
+ auto surfaceFactory = std::unique_ptr<VkSurfaceXlib>{new VkSurfaceXlib{window->display, window->window}};
+#else
+ auto window = Test::create_xcb_window(640, 480);
+ auto surfaceFactory = std::unique_ptr<VkSurfaceXcb>{new VkSurfaceXcb{window->connection, window->window}};
+#endif
+
+ auto graphics = MakeUnique<Graphics>();
+ auto fbid = graphics->Create(std::move(surfaceFactory));
+
+ // access internal implementation
+ auto &gr = graphics->GetImplementation<Dali::Graphics::Vulkan::Graphics>();
+
+ // GPU memory manager
+ auto &memmgr = gr.GetDeviceMemoryManager();
+
+ return TextureTestMain( gr );
+}
+
int RunTestMain()
{
#if USE_XLIB == 1
auto window = Test::create_xlib_window( 640, 480 );
auto surfaceFactory = std::unique_ptr<VkSurfaceXlib>{new VkSurfaceXlib{window->display, window->window}};
#else
- auto window = Test::create_xcb_window( 640, 480 );
+ auto window = Test::create_xcb_window(640, 480);
auto surfaceFactory = std::unique_ptr<VkSurfaceXcb>{new VkSurfaceXcb{window->connection, window->window}};
#endif
auto graphics = MakeUnique<Graphics>();
- auto fbid = graphics->Create( std::move( surfaceFactory ) );
+ auto fbid = graphics->Create(std::move(surfaceFactory));
// access internal implementation
- auto& gr = graphics->GetImplementation<Dali::Graphics::Vulkan::Graphics>();
+ auto &gr = graphics->GetImplementation<Dali::Graphics::Vulkan::Graphics>();
// GPU memory manager
- auto& memmgr = gr.GetDeviceMemoryManager();
+ 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},
+ {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() );
+ auto vertexShader = Shader::New(gr, VSH_CODE.data(), VSH_CODE.size());
- auto fragmentShader = Shader::New( gr, FSH_CODE.data(), FSH_CODE.size() );
+ 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 vertexBuffer = Buffer::New(gr, sizeof(float) * 3 * 3, Buffer::Type::VERTEX);
- auto descriptorPool = create_descriptor_pool( gr );
+ auto descriptorPool = create_descriptor_pool(gr);
- auto& gpuManager = gr.GetDeviceMemoryManager();
+ auto &gpuManager = gr.GetDeviceMemoryManager();
- auto bufferMemory = test_gpu_memory_manager( gr, gpuManager, vertexBuffer );
- vertexBuffer->BindMemory( bufferMemory );
+ auto bufferMemory = test_gpu_memory_manager(gr, gpuManager, vertexBuffer);
+ vertexBuffer->BindMemory(bufferMemory);
- auto ptr = static_cast<uint8_t*>( bufferMemory->Map() );
- std::copy( reinterpret_cast<const uint8_t*>( VERTICES ),
- reinterpret_cast<const uint8_t*>( VERTICES ) + ( sizeof( float ) * 9 ),
- ptr );
+ auto ptr = static_cast<uint8_t *>( bufferMemory->Map());
+ std::copy(reinterpret_cast<const uint8_t *>( VERTICES ),
+ reinterpret_cast<const uint8_t *>( VERTICES ) + (sizeof(float) * 9),
+ ptr);
bufferMemory->Unmap();
- auto pipeline = create_pipeline( gr, vertexShader, fragmentShader );
+ auto pipeline = create_pipeline(gr, vertexShader, fragmentShader);
auto descriptorSet = descriptorPool->AllocateDescriptorSets(
vk::DescriptorSetAllocateInfo{}
- .setPSetLayouts( pipeline->GetVkDescriptorSetLayouts().data() )
- .setDescriptorSetCount( pipeline->GetVkDescriptorSetLayouts().size() ) );
+ .setPSetLayouts(pipeline->GetVkDescriptorSetLayouts()
+ .data())
+ .setDescriptorSetCount(pipeline->GetVkDescriptorSetLayouts()
+ .size()));
- auto commandPool = CommandPool::New( gr );
+ auto commandPool = CommandPool::New(gr);
- auto uniformBuffer = create_uniform_buffer( gr );
+ auto uniformBuffer = create_uniform_buffer(gr);
- auto clipBuffer = create_clip_buffer( gr );
+ auto clipBuffer = create_clip_buffer(gr);
- descriptorSet[0]->WriteUniformBuffer( 0, uniformBuffer, 0, uniformBuffer->GetSize() );
- descriptorSet[0]->WriteUniformBuffer( 1, clipBuffer, 0, clipBuffer->GetSize() );
+ descriptorSet[0]->WriteUniformBuffer(0, uniformBuffer, 0, uniformBuffer->GetSize());
+ descriptorSet[0]->WriteUniformBuffer(1, clipBuffer, 0, clipBuffer->GetSize());
// get new buffer
- auto cmdDraw = commandPool->NewCommandBuffer( false );
+ auto cmdDraw = commandPool->NewCommandBuffer(false);
// begin recording
- cmdDraw->Begin( vk::CommandBufferUsageFlagBits::eRenderPassContinue );
+ cmdDraw->Begin(vk::CommandBufferUsageFlagBits::eRenderPassContinue);
// vertex buffer
- cmdDraw->BindVertexBuffer( 0, vertexBuffer, 0 );
+ cmdDraw->BindVertexBuffer(0, vertexBuffer, 0);
// pipeline
- cmdDraw->BindGraphicsPipeline( pipeline );
+ cmdDraw->BindGraphicsPipeline(pipeline);
// descriptor sets
- cmdDraw->BindDescriptorSets( descriptorSet, 0 );
+ cmdDraw->BindDescriptorSets(descriptorSet, 0);
// do draw
- cmdDraw->Draw( 3, 1, 0, 0 );
+ cmdDraw->Draw(3, 1, 0, 0);
// finish
cmdDraw->End();
bool running = true;
- while( running )
+ while (running)
{
- graphics->PreRender( fbid );
+ graphics->PreRender(fbid);
// queue submit draw
- auto cmdbuf = gr.GetSurface( fbid ).GetCurrentCommandBuffer();
+ auto cmdbuf = gr.GetSwapchainForFBID(fbid)
+ ->GetPrimaryCommandBuffer();
// get command buffer for current frame and execute the draw call
- cmdbuf->ExecuteCommands( {cmdDraw} );
+ cmdbuf->ExecuteCommands({cmdDraw});
- graphics->PostRender( fbid );
+ graphics->PostRender(fbid);
- update_translation( uniformBuffer );
+ update_translation(uniformBuffer);
}
return 0;
}
+void texture_test(void *data, size_t size)
+{
+
+}
using namespace Dali::Graphics::Vulkan::SpirV;
void spirv_test0( std::vector<SPIRVWord> code )
}
+
} // namespace VulkanTest
int main()
{
- VulkanTest::RunTestMain();
+ VulkanTest::RunTestMain2();
//VulkanTest::RunSPIRVTest();
}
*/
// INTERNAL INCLUDES
-#include <dali/graphics/vulkan/vulkan-command-buffer.h>
-#include <dali/graphics/vulkan/vulkan-command-pool.h>
-#include <dali/graphics/vulkan/vulkan-fence.h>
-#include <dali/graphics/vulkan/vulkan-graphics.h>
-#include <dali/graphics/vulkan/vulkan-queue.h>
#include <dali/graphics/vulkan/vulkan-surface.h>
-#include <dali/graphics/vulkan/vulkan-image.h>
+#include <dali/graphics/vulkan/vulkan-graphics.h>
+#include <dali/integration-api/graphics/vulkan/vk-surface-factory.h>
namespace Dali
{
namespace Vulkan
{
-namespace
-{
-// constants
-auto VK_COMPONENT_MAPPING_RGBA = vk::ComponentMapping{}
- .setR(vk::ComponentSwizzle::eR)
- .setG(vk::ComponentSwizzle::eG)
- .setB(vk::ComponentSwizzle::eB)
- .setA(vk::ComponentSwizzle::eA);
-}
-
-SwapchainImage::SwapchainImage() = default;
-SwapchainImage::~SwapchainImage() = default;
-
-Surface::Surface(Graphics& graphics, vk::SurfaceKHR surface, uint32_t bufferCount, bool hasDepthStencil)
-: mGraphics(graphics), mSurface(surface), mSwapchain{nullptr}, mBufferCount{bufferCount}, mHasDepthStencil(hasDepthStencil)
-{
-}
-
-Surface::~Surface()
+struct Surface::Impl
{
- if(mSwapchain)
+ Impl( Surface& owner, Graphics& graphics, std::unique_ptr<SurfaceFactory> surfaceFactory ) :
+ mOwner( owner ), mGraphics( graphics ), mSurfaceFactory( std::move(surfaceFactory) )
{
- DestroySwapchain();
+ mVulkanSurfaceFactory = dynamic_cast<Dali::Integration::Graphics::Vulkan::VkSurfaceFactory*>(mSurfaceFactory.get());
}
- if(mSurface)
- {
- mGraphics.GetInstance().destroySurfaceKHR(mSurface, mGraphics.GetAllocator());
- }
-}
-void Surface::AcquireNextImage()
-{
- // if swapchain hasn't been created yet, create it
- // TODO: deferring may bring a lag when surface is swapped very first time
- // it might be good to have an option to create swapchain regardless further usage
- if(!mSwapchain)
+ ~Impl()
{
- CreateSwapchain();
- }
- if(!mFrameFence)
- {
- mFrameFence = Fence::New(mGraphics);
}
- // acquire image, for simplicity using fence for acquiring as it is unknown what next command buffer will
- // be executed yet
- mFrameFence->Reset();
- uint32_t index = VkAssert(mGraphics.GetDevice().acquireNextImageKHR(mSwapchain, 1000000, nullptr,
- mFrameFence->GetFence()));
- mFrameFence->Wait();
- mFrameFence->Reset();
-
- mCurrentBufferIndex = index;
-
- auto& swapImage = mSwapImages[index];
-
- // change layout if necessary to color attachment
- if(swapImage.layout != vk::ImageLayout::eColorAttachmentOptimal)
+ bool Initialise()
{
- auto& queue = mGraphics.GetGraphicsQueue();
- queue.Submit(swapImage.layoutToColorCmdBuf, mFrameFence)->WaitForFence();
- }
-
- mFrameFence->Reset();
-
- // todo: anything to be done before beginning main command buffer?
- BeginRenderPass();
-}
-
-void Surface::BeginRenderPass()
-{
- auto& swapImage = mSwapImages[mCurrentBufferIndex];
-
- // begin command buffer ( can be directly obtained through Graphics( surface )
- swapImage.mainCmdBuf->Begin(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
-
- /*
- * todo: automatically start main render pass -> this may have to be done manually in future
- * if more flexibility is needed
- */
- auto vkCmdBuf = swapImage.mainCmdBuf->GetVkCommandBuffer();
- {
- std::array< vk::ClearValue, 2 > clearValues;
-
- static float r = 1.0f;
- //r += 0.01f;
- if(r > 1.0f)
- r -= 1.0f;
-
- clearValues[0].color.setFloat32({0.0f, 0.0f, 0.0f, 1.0f});
- clearValues[1].depthStencil.setDepth(1.0f).setStencil(0.0f);
-
- auto rpInfo = vk::RenderPassBeginInfo{};
- rpInfo.setRenderPass(mDefaultRenderPass)
- .setFramebuffer(swapImage.framebuffer)
- .setRenderArea(vk::Rect2D{}.setOffset({0, 0}).setExtent(mExtent))
- .setClearValueCount(mHasDepthStencil ? 2 : 1)
- .setPClearValues(clearValues.data());
-
- auto subpassContents = vk::SubpassContents{vk::SubpassContents::eSecondaryCommandBuffers};
- vkCmdBuf.beginRenderPass(rpInfo, subpassContents);
- }
-}
-
-std::vector<vk::ClearValue> 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<vk::ClearValue>{};
- retval.emplace_back( clearValues[0] );
- if( mHasDepthStencil )
- {
- retval.emplace_back( clearValues[1] );
- }
- return retval;
-}
-
-vk::Extent2D Surface::GetSize() const
-{
- return mCapabilities->currentExtent;
-}
-
-Handle<CommandBuffer> Surface::GetCommandBuffer( uint32_t index )
-{
- return mSwapImages[index].mainCmdBuf;
-}
-
-Handle<CommandBuffer> 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->GetVkCommandBuffer();
-
- // complete render pass
- vkCmdBuf.endRenderPass();
-
- // finalize command buffer
- swapImage.mainCmdBuf->End();
-
- // submit
- auto& queue = mGraphics.GetGraphicsQueue();
- queue.Submit(swapImage.mainCmdBuf, mFrameFence)->WaitForFence();
-}
-
-void Surface::Present()
-{
- // complete render pass and command buffer
- EndRenderPass();
-
- auto& swapImage = mSwapImages[mCurrentBufferIndex];
- auto result = mGraphics.GetGraphicsQueue().Present(mSwapchain, mCurrentBufferIndex);
- if(result != vk::Result::eSuccess)
- {
- //todo: handle swapchain invalidation
- }
- swapImage.layout = vk::ImageLayout::ePresentSrcKHR;
- // todo: test result against swapchain expiration
-}
-
-void Surface::CreateSwapchain()
-{
- {
- auto formats = VkAssert(mGraphics.GetPhysicalDevice().getSurfaceFormatsKHR(mSurface));
- // find first which is not UNDEFINED
- mFormat = vk::Format::eUndefined;
- for(auto& format : formats)
+ if(!mVulkanSurfaceFactory)
{
- if(format.format != vk::Format::eUndefined && mFormat == vk::Format::eUndefined)
- {
- mFormat = format.format;
- mColorSpace = format.colorSpace;
- }
+ return false;
}
- }
-
- assert(mFormat != vk::Format::eUndefined && "No supported surface format!");
-
- mCapabilities.reset(new vk::SurfaceCapabilitiesKHR(
- VkAssert(mGraphics.GetPhysicalDevice().getSurfaceCapabilitiesKHR(mSurface))));
-
- mExtent = mCapabilities->currentExtent;
- CreateVulkanSwapchain();
+ // fixme: should avoid const cast :(
+ auto* allocatorCallbacks = const_cast<vk::AllocationCallbacks*>(&mGraphics.GetAllocator());
+ mSurface = mVulkanSurfaceFactory->Create( mGraphics.GetInstance(), allocatorCallbacks, mGraphics.GetPhysicalDevice() );
- // initialise default render pass
- InitialiseRenderPass();
-
- // if successful continue with obtaining images etc. also each swapchain will obtain default renderpass
- InitialiseSwapchain();
-
- // prerecord command buffers per each image in order to provide layout transition
- CreateCommandBuffers();
-}
-
-void Surface::CreateVulkanSwapchain()
-{
- auto info = vk::SwapchainCreateInfoKHR{};
-
- info.setClipped(true)
- .setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque)
- .setImageArrayLayers(1)
- .setImageColorSpace(mColorSpace)
- .setImageExtent(mCapabilities->currentExtent)
- .setImageFormat(mFormat)
- .setImageSharingMode(vk::SharingMode::eExclusive)
- .setImageUsage(vk::ImageUsageFlagBits::eColorAttachment)
- .setMinImageCount(mBufferCount)
- .setPresentMode(vk::PresentModeKHR::eFifo)
- .setPreTransform(mCapabilities->currentTransform)
- .setOldSwapchain(nullptr)
- .setPQueueFamilyIndices(nullptr)
- .setQueueFamilyIndexCount(0)
- .setSurface(mSurface);
-
- mSwapchain = VkAssert(mGraphics.GetDevice().createSwapchainKHR(
- reinterpret_cast< vk::SwapchainCreateInfoKHR& >(info), mGraphics.GetAllocator()));
-}
-
-void Surface::DestroySwapchain()
-{
- mGraphics.GetDevice().destroySwapchainKHR(mSwapchain, mGraphics.GetAllocator());
-}
-
-void Surface::InitialiseSwapchain()
-{
- const auto& device = mGraphics.GetDevice();
-
- auto images = VkAssert(device.getSwapchainImagesKHR(mSwapchain));
- assert(mBufferCount == images.size() && "Swapchain images count not equal requested value!");
-
- {
- auto swapImages = std::vector< SwapchainImage >{};
-
- // for each image create framebuffer and image view
- for(auto& image : images)
+ if(!mSurface)
{
- AddSwapchainImage(image, swapImages);
+ return false;
}
- mSwapImages = std::move(swapImages);
+ auto caps = VkAssert( mGraphics.GetPhysicalDevice().getSurfaceCapabilitiesKHR( mSurface ) );
+ mCurrentExtent = caps.currentExtent;
+
+ return true;
}
- if(mHasDepthStencil)
+ vk::Extent2D GetSize() const
{
- CreateDepthStencil();
+ return mCurrentExtent;
}
-}
-
-void Surface::AddSwapchainImage(vk::Image image, std::vector< SwapchainImage >& swapchainImages)
-{
- auto swapImage = std::move(SwapchainImage{});
- swapImage.image = NewRef<Image>( mGraphics, vk::ImageCreateInfo{}, image );
-
- // create ImageView
- CreateImageView(swapImage);
-
- // Create framebuffer ( there must be already render pass and information whether
- // we use depth or not )
- CreateFramebuffer(swapImage);
- // initialise semaphores
- CreateSemaphores(swapImage);
+ Surface& mOwner;
+ Graphics& mGraphics;
+ std::unique_ptr<SurfaceFactory> mSurfaceFactory;
+ Dali::Integration::Graphics::Vulkan::VkSurfaceFactory* mVulkanSurfaceFactory;
+ vk::SurfaceKHR mSurface;
+ vk::Extent2D mCurrentExtent;
+};
- swapImage.layout = vk::ImageLayout::eUndefined;
-
- swapchainImages.push_back(std::move(swapImage));
-}
-
-void Surface::CreateImageView(SwapchainImage& swapImage)
-{
- // Simple image view 2D as a color attachment
- auto ivInfo = vk::ImageViewCreateInfo{};
- ivInfo.setFormat(mFormat)
- .setComponents(VK_COMPONENT_MAPPING_RGBA)
- .setImage(swapImage.image->GetVkImage())
- .setSubresourceRange(vk::ImageSubresourceRange()
- .setAspectMask(vk::ImageAspectFlagBits::eColor)
- .setBaseArrayLayer(0)
- .setBaseMipLevel(0)
- .setLayerCount(1)
- .setLevelCount(1))
- .setViewType(vk::ImageViewType::e2D);
-
- swapImage.imageView = ImageView::New( mGraphics, swapImage.image, ivInfo );
-}
-
-void Surface::CreateFramebuffer(SwapchainImage& swapImage)
-{
- vk::FramebufferCreateInfo fbInfo;
- fbInfo.setAttachmentCount(mHasDepthStencil ? 2 : 1)
- .setPAttachments(&swapImage.imageView->GetVkImageView()) // todo: add depth/stencil attachment
- .setHeight(mExtent.height)
- .setWidth(mExtent.width)
- .setLayers(1)
- .setRenderPass(mDefaultRenderPass);
-
- swapImage.framebuffer =
- VkAssert(mGraphics.GetDevice().createFramebuffer(fbInfo, mGraphics.GetAllocator()));
-}
-
-void Surface::CreateSemaphores(SwapchainImage& swapImage)
-{
- swapImage.acqSem =
- VkAssert(mGraphics.GetDevice().createSemaphore(vk::SemaphoreCreateInfo(), mGraphics.GetAllocator()));
- swapImage.presentSem =
- VkAssert(mGraphics.GetDevice().createSemaphore(vk::SemaphoreCreateInfo(), mGraphics.GetAllocator()));
-}
+/**
+ * Surface
+ */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wframe-larger-than="
-void Surface::InitialiseRenderPass()
+SurfaceRef Surface::New( Graphics& graphics, std::unique_ptr<SurfaceFactory> surfaceFactory )
{
- auto att = std::vector<vk::AttachmentDescription>{ 2 };
-
- // color attachment
- att[0]
- .setFormat(mFormat)
- .setLoadOp(vk::AttachmentLoadOp::eClear)
- .setStoreOp(vk::AttachmentStoreOp::eStore)
- .setSamples(vk::SampleCountFlagBits::e1)
- .setStencilLoadOp(vk::AttachmentLoadOp::eDontCare)
- .setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)
- .setInitialLayout(vk::ImageLayout::eColorAttachmentOptimal)
- .setFinalLayout(vk::ImageLayout::ePresentSrcKHR);
-
- // optional depth/stencil attachment
- att[1]
- .setFormat(mDepthStencilFormat)
- .setLoadOp(vk::AttachmentLoadOp::eClear)
- .setStoreOp(vk::AttachmentStoreOp::eDontCare)
- .setSamples(vk::SampleCountFlagBits::e1)
- .setStencilLoadOp(vk::AttachmentLoadOp::eDontCare)
- .setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)
- .setInitialLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal)
- .setFinalLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal);
-
- auto attRef = std::array<vk::AttachmentReference, 2>{};
- attRef[0].setLayout(vk::ImageLayout::eColorAttachmentOptimal).setAttachment(0);
- attRef[1].setLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal).setAttachment(1);
-
- // prepare default subpass
- vk::SubpassDescription subpass;
- subpass.setColorAttachmentCount(1)
- .setPColorAttachments(&attRef[0])
- .setPDepthStencilAttachment(mHasDepthStencil ? &attRef[1] : nullptr)
- .setPipelineBindPoint(vk::PipelineBindPoint::eGraphics);
-
- vk::RenderPassCreateInfo info;
- info.setPAttachments(att.data()).setAttachmentCount(mHasDepthStencil ? 2 : 1).setPSubpasses(&subpass).setSubpassCount(1);
-
- mDefaultRenderPass = VkAssert(mGraphics.GetDevice().createRenderPass(info, mGraphics.GetAllocator()));
+ return SurfaceRef( new Surface( graphics, std::move(surfaceFactory) ));
}
-#pragma GCC diagnostic pop
-void Surface::CreateDepthStencil()
+Surface::Surface(Graphics& graphics, std::unique_ptr<SurfaceFactory> surfaceFactory )
{
- assert("Surface::CreateDepthStencil() not implemented!");
- /// todo: implement
+ mImpl = std::make_unique<Impl>( *this, graphics, std::move(surfaceFactory) );
}
-void Surface::DestroyDepthStencil()
-{
- /// todo: implement
- assert("Surface::DestroyDepthStencil() not implemented!");
-}
+Surface::~Surface() = default;
-void Surface::CreateCommandBuffers()
+bool Surface::Create()
{
- if(!mCommandPool)
- {
- mCommandPool = CommandPool::New( mGraphics, vk::CommandPoolCreateInfo{}.setFlags(vk::CommandPoolCreateFlagBits::eResetCommandBuffer) );
- }
-
- // allocate command buffers
- auto cmdBuffers = std::vector< CommandBufferRef >{};
- auto cmdInfo =
- vk::CommandBufferAllocateInfo{}.setCommandBufferCount(1).setLevel(vk::CommandBufferLevel::ePrimary);
-
- for(auto& swapImage : mSwapImages)
- {
- 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
- swapImage.layoutToColorCmdBuf->Begin();
- swapImage.layoutToColorCmdBuf->ImageLayoutTransition(swapImage.image->GetVkImage(),
- swapImage.layout,
- vk::ImageLayout::eColorAttachmentOptimal,
- vk::ImageAspectFlagBits::eColor);
- swapImage.layoutToColorCmdBuf->End();
- swapImage.layout = vk::ImageLayout::eColorAttachmentOptimal;
-
- cmdBuffers.push_back(swapImage.layoutToColorCmdBuf);
- }
-
- // submit to the queue
- {
- auto& queue = mGraphics.GetGraphicsQueue();
- auto fence = Fence::New(mGraphics);
- auto submission = queue.Submit(cmdBuffers, fence);
- submission->WaitForFence();
- }
-
- // record present to color transitions for each buffer for further reusing
- for(auto& swapImage : mSwapImages)
- {
- swapImage.layoutToColorCmdBuf->Reset();
- swapImage.layoutToColorCmdBuf->Begin();
- swapImage.layoutToColorCmdBuf->ImageLayoutTransition(swapImage.image->GetVkImage(),
- vk::ImageLayout::ePresentSrcKHR,
- vk::ImageLayout::eColorAttachmentOptimal,
- vk::ImageAspectFlagBits::eColor);
- swapImage.layoutToColorCmdBuf->End();
- swapImage.layout = vk::ImageLayout::eColorAttachmentOptimal;
- }
+ return mImpl->Initialise();
}
vk::SurfaceKHR Surface::GetSurfaceKHR() const
{
- return mSurface;
+ return mImpl->mSurface;
}
-vk::RenderPass Surface::GetRenderPass() const
-{
- return mDefaultRenderPass;
-}
-
-vk::Framebuffer Surface::GetFramebuffer(uint32_t index) const
-{
- return mSwapImages[index].framebuffer;
-}
-
-ImageView& Surface::GetImageView(uint32_t index) const
-{
- return *mSwapImages[index].imageView;
-}
-
-Image& Surface::GetImage(uint32_t index) const
+vk::Extent2D Surface::GetSize() const
{
- return *mSwapImages[index].image;
+ return mImpl->GetSize();
}
} // namespace Vulkan
namespace Dali
{
+namespace Integration
+{
+namespace Graphics
+{
+class SurfaceFactory;
+}
+}
namespace Graphics
{
namespace Vulkan
{
-
-/**
- * Vulkan surface is coupled with swapchain -> one swapchain per surface
- * Swapchain won't exist until surface is used in a such way
- *
- */
+using SurfaceFactory = Dali::Integration::Graphics::SurfaceFactory;
class Graphics;
-class CommandBuffer;
-class CommandPool;
-class Surface;
-
-using UniqueSurface = std::unique_ptr< Surface >;
-using UniqueCommandBuffer = std::unique_ptr< CommandBuffer >;
-using UniqueCommandPool = std::unique_ptr< CommandPool >;
-
-// simple structure describing single image of swapchain
-// non-copyable, only movable
-struct SwapchainImage
-{
- SwapchainImage();
- ~SwapchainImage();
- SwapchainImage(const SwapchainImage&) = delete;
- SwapchainImage(SwapchainImage&&) = default;
- SwapchainImage& operator=(const SwapchainImage&) = delete;
- SwapchainImage& operator=(SwapchainImage&&) = default;
-
- ImageRef image;
- ImageViewRef imageView;
- vk::Framebuffer framebuffer;
- vk::ImageLayout layout;
- vk::Semaphore acqSem;
- vk::Semaphore presentSem;
-
- // layout transitions, prerecorded command buffers
- Handle<CommandBuffer> layoutToColorCmdBuf;
- Handle<CommandBuffer> mainCmdBuf;
-};
-
-class Surface
+class Surface : public VkManaged
{
public:
- Surface(Graphics& graphics, vk::SurfaceKHR surface, uint32_t bufferCount = 2,
- bool hasDepthStencil = false);
- ~Surface();
- /**
- * Prepares new swapchain image
- */
- void AcquireNextImage();
+ static SurfaceRef New( Graphics& graphics, std::unique_ptr<SurfaceFactory> surfaceFactory );
- /**
- * Presents image
- */
- void Present();
+ Surface(Graphics& graphics, std::unique_ptr<SurfaceFactory> surfaceFactory );
+ ~Surface() final;
/**
- *
- * @return
- */
- vk::RenderPass GetRenderPass() const;
-
- /**
- *
- * @param index
- * @return
- */
- vk::Framebuffer GetFramebuffer(uint32_t index = -1u) const;
-
- /**
- *
- * @param index
- * @return
- */
- ImageView& GetImageView(uint32_t index = -1u) const;
-
- /**
- *
- * @param index
- * @return
+ * Creates surface from given factory
*/
- Image& GetImage(uint32_t index = -1u) const;
+ bool Create();
/**
*
vk::SurfaceKHR GetSurfaceKHR() const;
/**
- * returns set of clear values for this surface
- * @return
- */
- std::vector<vk::ClearValue> GetClearValues() const;
-
- /**
* Returns size of surface
* @return
*/
vk::Extent2D GetSize() const;
- /**
- * Returns primary command buffer associated with specific buffer
- * @param index
- * @return
- */
- Handle<CommandBuffer> GetCommandBuffer( uint32_t index );
-
- /**
- * Returns primary command buffer associated with current buffer
- * @return
- */
- Handle<CommandBuffer> GetCurrentCommandBuffer();
-
-/**
- *
- */
- void CreateSwapchain();
-
private:
- void CreateVulkanSwapchain();
-
- void CreateImageView(SwapchainImage& swapImage);
- void CreateFramebuffer(SwapchainImage& swapImage);
- void CreateSemaphores(SwapchainImage& swapImage);
-
- void DestroySwapchain();
-
- void InitialiseSwapchain();
-
- void InitialiseRenderPass();
-
- void AddSwapchainImage(vk::Image image, std::vector< SwapchainImage >& swapchainImages);
-
- void CreateCommandBuffers();
-
- void CreateDepthStencil();
-
- void DestroyDepthStencil();
-
- void BeginRenderPass();
-
- void EndRenderPass();
-
- Graphics& mGraphics;
- vk::SurfaceKHR mSurface;
- vk::SwapchainKHR mSwapchain;
-
- vk::Format mDepthStencilFormat{vk::Format::eD16UnormS8Uint};
- vk::Image mDepthStencilImage;
- vk::ImageView mDepthStencilImageView;
- vk::DeviceMemory mDepthStencilMemory;
-
- Handle<CommandPool> mCommandPool;
-
- vk::Format mFormat;
- vk::ColorSpaceKHR mColorSpace;
- vk::Extent2D mExtent;
-
- std::vector< SwapchainImage > mSwapImages;
- std::unique_ptr< vk::SurfaceCapabilitiesKHR > mCapabilities;
-
- Handle<Fence> mFrameFence;
-
- vk::RenderPass mDefaultRenderPass;
- uint32_t mBufferCount;
- uint32_t mCurrentBufferIndex;
- bool mHasDepthStencil;
+ struct Impl;
+ std::unique_ptr<Impl> mImpl;
};
} // namespace Vulkan
--- /dev/null
+/*
+ * 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 <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-allocator.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.h>
+#include <dali/graphics/vulkan/vulkan-command-buffer.h>
+#include <dali/graphics/vulkan/vulkan-command-pool.h>
+#include <dali/graphics/vulkan/vulkan-fence.h>
+#include <dali/graphics/vulkan/vulkan-framebuffer.h>
+#include <dali/graphics/vulkan/vulkan-graphics.h>
+#include <dali/graphics/vulkan/vulkan-image.h>
+#include <dali/graphics/vulkan/vulkan-queue.h>
+#include <dali/graphics/vulkan/vulkan-surface.h>
+#include <dali/graphics/vulkan/vulkan-swapchain.h>
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+/**
+ * SwapchainBuffer stores all per-buffer data
+ */
+struct SwapchainBuffer
+{
+ /*
+ * Each buffer has own master command buffer which executes
+ * secondary buffers
+ */
+ CommandBufferRef masterCmdBuffer;
+
+ /*
+ * Each buffer has a command pool to allocate from
+ */
+ CommandPoolRef masterCommandPool;
+
+ /*
+ * Framebuffer object associated with the buffer
+ */
+ FramebufferRef framebuffer;
+
+ /*
+ * Sync primitives
+ */
+ FenceRef endOfFrameFence;
+
+ /*
+ * Buffer index
+ */
+ uint32_t index;
+
+ /*
+ * First use before presenting
+ */
+ bool firstUse;
+};
+
+struct Swapchain::Impl
+{
+ Impl( Swapchain& owner,
+ Graphics& graphics,
+ Queue& presentationQueue,
+ SurfaceRef surface,
+ uint32_t bufferCount,
+ uint32_t flags )
+ : mOwner( owner ),
+ mGraphics( graphics ),
+ mQueue( presentationQueue ),
+ mSurface( surface ),
+ mBufferCount( bufferCount ),
+ mFlags( flags )
+ {
+ mSwapchainCreateInfoKHR.setSurface( mSurface->GetSurfaceKHR() )
+ .setPreTransform( vk::SurfaceTransformFlagBitsKHR::eIdentity )
+ .setPresentMode( vk::PresentModeKHR::eFifo )
+ .setOldSwapchain( nullptr ) //@todo support surface replacement!
+ .setMinImageCount( mBufferCount )
+ .setImageUsage( vk::ImageUsageFlagBits::eColorAttachment )
+ .setImageSharingMode( vk::SharingMode::eExclusive )
+ .setImageArrayLayers( 1 )
+ .setCompositeAlpha( vk::CompositeAlphaFlagBitsKHR::eOpaque )
+ .setClipped( true )
+ .setQueueFamilyIndexCount( 0 )
+ .setPQueueFamilyIndices( nullptr );
+ }
+
+ ~Impl() = default;
+
+ Impl( const Impl& ) = delete;
+ Impl& operator=( const Impl& ) = delete;
+
+ bool Initialise()
+ {
+ if( !SetImageFormat() )
+ {
+ return false;
+ }
+
+ // get extents
+ mSwapchainExtent = mSurface->GetSize();
+
+ mSwapchainCreateInfoKHR.setImageFormat( mSwapchainImageFormat );
+ mSwapchainCreateInfoKHR.setImageExtent( mSwapchainExtent );
+ mSwapchainCreateInfoKHR.setImageColorSpace( mSwapchainColorSpace );
+
+ Create();
+
+ InitialiseSwapchainBuffers();
+
+ PrepareFramebuffers();
+
+ mFirstPresent = true;
+ return true;
+ }
+
+ bool InitialiseSwapchainBuffers()
+ {
+ mSwapchainBuffer.clear();
+ for( auto&& fb : mFramebuffers )
+ {
+ auto cmdPool = CommandPool::New( mGraphics, vk::CommandPoolCreateInfo{}.setFlags( vk::CommandPoolCreateFlagBits::eResetCommandBuffer ) );
+ auto masterCmd = cmdPool->NewCommandBuffer( true );
+
+ auto swapBuffer = SwapchainBuffer{};
+ swapBuffer.framebuffer = fb;
+ swapBuffer.index = 0;
+ swapBuffer.masterCmdBuffer = masterCmd;
+ swapBuffer.masterCommandPool = cmdPool;
+ swapBuffer.endOfFrameFence = Fence::New( mGraphics );
+ swapBuffer.firstUse = true;
+ mSwapchainBuffer.emplace_back( swapBuffer );
+ }
+
+ return true;
+ }
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
+ void PrepareFramebuffers()
+ {
+ /*
+ * After creating the new swapchain we need to make sure
+ * the layout of images is correct to start with. To do so
+ * we will wait till the whole device is idle ( there should
+ * be a mechanism preventing from using the GPU past that point )
+ * and submit pipeline barriers setting up the layouts of
+ * all framebuffer images in one go. There will be no fancy
+ * synchronisation here as it's not really needed at this point.
+ * Waiting for queue or device idle should be enough.
+ */
+
+ const auto& device = mGraphics.GetDevice();
+
+ device.waitIdle();
+
+ /*
+ * Create temporary command pool
+ */
+ auto commandPool = CommandPool::New( mGraphics );
+ auto cmdBuffer = commandPool->NewCommandBuffer();
+
+ std::vector<vk::ImageMemoryBarrier> barriers;
+ ImageViewRef depthStencilImage{};
+
+ for( auto&& buffer : mSwapchainBuffer )
+ {
+ auto colorImages = buffer.framebuffer->GetAttachments( Framebuffer::AttachmentType::COLOR );
+
+ // expecting to use one depth stencil image for all swapbuffers
+ if( !depthStencilImage )
+ {
+ depthStencilImage = buffer.framebuffer->GetAttachment( Framebuffer::AttachmentType::DEPTH_STENCIL, 0u );
+ }
+
+ /*
+ * Add barriers for color images
+ */
+ for( auto&& colorImageView : colorImages )
+ {
+ auto image = colorImageView->GetImage();
+ auto vkImage = image->GetVkImage();
+
+ vk::ImageSubresourceRange range;
+ range.setLayerCount( image->GetLayerCount() )
+ .setLevelCount( image->GetLevelCount() )
+ .setBaseMipLevel( 0 )
+ .setBaseArrayLayer( 0 )
+ .setAspectMask( vk::ImageAspectFlagBits::eColor );
+ auto colorBarrier = vk::ImageMemoryBarrier{}
+ .setImage( vkImage )
+ .setSubresourceRange( range )
+ .setSrcAccessMask( vk::AccessFlags{} )
+ .setDstAccessMask( vk::AccessFlagBits::eColorAttachmentWrite )
+ .setOldLayout( vk::ImageLayout::eUndefined )
+ .setNewLayout( vk::ImageLayout::eColorAttachmentOptimal );
+
+ barriers.emplace_back( colorBarrier );
+ }
+ }
+
+ /*
+ * Add barrier for depth stencil image
+ */
+ if( depthStencilImage )
+ {
+ auto image = depthStencilImage->GetImage();
+ auto vkImage = image->GetVkImage();
+
+ vk::ImageSubresourceRange range;
+ range.setLayerCount( image->GetLayerCount() )
+ .setLevelCount( image->GetLevelCount() )
+ .setBaseMipLevel( 0 )
+ .setBaseArrayLayer( 0 )
+ .setAspectMask( vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil );
+ auto depthStencilBarrier = vk::ImageMemoryBarrier{}
+ .setImage( vkImage )
+ .setSubresourceRange( range )
+ .setSrcAccessMask( vk::AccessFlags{} )
+ .setDstAccessMask( vk::AccessFlagBits::eDepthStencilAttachmentWrite )
+ .setOldLayout( vk::ImageLayout::eUndefined )
+ .setNewLayout( vk::ImageLayout::eDepthStencilAttachmentOptimal );
+ barriers.emplace_back( depthStencilBarrier );
+ }
+
+ /*
+ * Record command buffer with pipeline barrier
+ */
+ cmdBuffer->Begin( vk::CommandBufferUsageFlagBits::eOneTimeSubmit );
+ cmdBuffer->PipelineBarrier( vk::PipelineStageFlagBits::eTopOfPipe,
+ vk::PipelineStageFlagBits::eTopOfPipe,
+ vk::DependencyFlags{},
+ std::vector<vk::MemoryBarrier>{},
+ std::vector<vk::BufferMemoryBarrier>{},
+ barriers );
+ cmdBuffer->End();
+
+ // use presentation queue to submit the call
+ mQueue.Submit( cmdBuffer, FenceRef{} );
+ mQueue.WaitIdle();
+ }
+#pragma GCC diagnostic pop
+
+ bool SetImageFormat()
+ {
+ // obtain supported image format
+ auto formats = VkAssert( mGraphics.GetPhysicalDevice().getSurfaceFormatsKHR( mSurface->GetSurfaceKHR() ) );
+ mSwapchainImageFormat = vk::Format::eUndefined;
+
+ for( auto&& format : formats )
+ {
+ if( format.format != vk::Format::eUndefined )
+ {
+ mSwapchainColorSpace = format.colorSpace;
+ mSwapchainImageFormat = format.format;
+ break;
+ }
+ }
+
+ if( vk::Format::eUndefined == mSwapchainImageFormat )
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Creates swapchain immediately
+ * @return
+ */
+ bool Create()
+ {
+ const auto& device = mGraphics.GetDevice();
+ const auto& allocator = mGraphics.GetAllocator();
+
+ //@todo validation
+ mSwapchainKHR = VkAssert( device.createSwapchainKHR( mSwapchainCreateInfoKHR, allocator ) );
+
+ if( !mSwapchainKHR )
+ {
+ return false;
+ }
+
+ // pull images and create Framebuffers
+ auto images = VkAssert( device.getSwapchainImagesKHR( mSwapchainKHR ) );
+
+ // number of images must match requested buffering mode
+ if( images.size() != mBufferCount )
+ {
+ device.destroySwapchainKHR( mSwapchainKHR );
+ mSwapchainKHR = nullptr;
+ return false;
+ }
+
+ //@todo create depth-stencil image
+ auto depthStencilImageView = CreateDepthStencil();
+
+ /*
+ * CREATE FRAMEBUFFERS
+ */
+ for( auto&& image : images )
+ {
+ mFramebuffers.emplace_back( CreateFramebuffer( image ) );
+
+ // set depth/stencil if supported
+ if( depthStencilImageView )
+ {
+ mFramebuffers.back()->SetAttachment( depthStencilImageView, Framebuffer::AttachmentType::DEPTH_STENCIL, 0u );
+ }
+
+ // create framebuffer and compatible render pass right now, no need to defer it
+ mFramebuffers.back()->Commit();
+ }
+
+ return true;
+ }
+
+ /**
+ * Creates depth stencil if necessary
+ * @return
+ */
+ ImageViewRef CreateDepthStencil()
+ {
+ // create depth stencil image
+ auto dsImageRef = Image::New( mGraphics,
+ vk::ImageCreateInfo{}
+ .setFormat( vk::Format::eD24UnormS8Uint )
+ .setMipLevels( 1 )
+ .setTiling( vk::ImageTiling::eOptimal )
+ .setImageType( vk::ImageType::e2D )
+ .setArrayLayers( 1 )
+ .setExtent( {mSwapchainExtent.width, mSwapchainExtent.height, 1} )
+ .setUsage( vk::ImageUsageFlagBits::eDepthStencilAttachment )
+ .setSharingMode( vk::SharingMode::eExclusive )
+ .setInitialLayout( vk::ImageLayout::eUndefined )
+ .setSamples( vk::SampleCountFlagBits::e1 ) );
+
+ auto memory = mGraphics.GetDeviceMemoryManager().GetDefaultAllocator().Allocate(
+ dsImageRef, vk::MemoryPropertyFlagBits::eDeviceLocal );
+
+ dsImageRef->BindMemory( memory );
+
+ // create imageview to be used within framebuffer
+ auto dsImageViewRef = ImageView::New( mGraphics, dsImageRef );
+ return dsImageViewRef;
+ }
+
+ /**
+ * Creates a Framebuffer and compatible RenderPass
+ * @param image
+ * @return
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
+ FramebufferRef CreateFramebuffer( vk::Image& image )
+ {
+ auto fbRef = Framebuffer::New( mGraphics, mSwapchainExtent.width, mSwapchainExtent.height );
+
+ // Create external Image reference
+ // Note that despite we don't create VkImage, we still fill the createinfo structure
+ // as this data will be used later
+ ImageRef imageRef = Image::New( mGraphics,
+ vk::ImageCreateInfo{}
+ .setFormat( mSwapchainImageFormat )
+ .setSamples( vk::SampleCountFlagBits::e1 )
+ .setInitialLayout( vk::ImageLayout::eUndefined )
+ .setSharingMode( vk::SharingMode::eExclusive )
+ .setUsage( vk::ImageUsageFlagBits::eColorAttachment )
+ .setExtent( {mSwapchainExtent.width, mSwapchainExtent.height, 1} )
+ .setArrayLayers( 1 )
+ .setImageType( vk::ImageType::e2D )
+ .setTiling( vk::ImageTiling::eOptimal )
+ .setMipLevels( 1 ),
+ image );
+
+ // Create basic imageview ( all mipmaps, all layers )
+ ImageViewRef iv = ImageView::New( mGraphics, imageRef );
+
+ fbRef->SetAttachment( iv, Framebuffer::AttachmentType::COLOR, 0u );
+
+ return fbRef;
+ }
+#pragma GCC diagnostic pop
+
+ /**
+ * This function acquires next framebuffer
+ * @todo we should rather use roundrobin method
+ * @return
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
+ FramebufferRef AcquireNextFramebuffer()
+ {
+ const auto& device = mGraphics.GetDevice();
+
+ if( !mFrameFence )
+ {
+ mFrameFence = Fence::New( mGraphics );
+ }
+
+ mCurrentBufferIndex =
+ VkAssert( device.acquireNextImageKHR( mSwapchainKHR, 1000000, nullptr, mFrameFence->GetFence() ) );
+
+ mFrameFence->Wait();
+ mFrameFence->Reset();
+
+ auto& swapBuffer = mSwapchainBuffer[mCurrentBufferIndex];
+
+ // start recording
+ auto inheritanceInfo = vk::CommandBufferInheritanceInfo{}
+ .setFramebuffer( swapBuffer.framebuffer->GetVkFramebuffer() )
+ .setRenderPass(swapBuffer.framebuffer->GetVkRenderPass())
+ .setSubpass( 0 );
+ swapBuffer.masterCmdBuffer->Reset();
+ swapBuffer.masterCmdBuffer->Begin( vk::CommandBufferUsageFlagBits::eRenderPassContinue, &inheritanceInfo );
+
+ // change layout from present to color attachment if not done yet
+ // ( swapchain must track that )
+ if(!swapBuffer.firstUse)
+ {
+ UpdateLayoutPresentToColorAttachment(swapBuffer);
+ }
+ swapBuffer.firstUse = false;
+
+ // Begins primary render pass
+ BeginPrimaryRenderPass( swapBuffer );
+
+ return swapBuffer.framebuffer;
+ }
+#pragma GCC diagnostic pop
+ void BeginPrimaryRenderPass( SwapchainBuffer& currentBuffer )
+ {
+ vk::RenderPassBeginInfo rpInfo{};
+ rpInfo.setRenderPass( currentBuffer.framebuffer->GetVkRenderPass() )
+ .setFramebuffer( currentBuffer.framebuffer->GetVkFramebuffer() )
+ .setPClearValues( currentBuffer.framebuffer->GetDefaultClearValues().data() )
+ .setClearValueCount( U32( currentBuffer.framebuffer->GetDefaultClearValues().size() ) )
+ .setRenderArea( vk::Rect2D( {0, 0}, mSurface->GetSize() ) );
+
+ currentBuffer.masterCmdBuffer->BeginRenderPass( rpInfo, vk::SubpassContents::eSecondaryCommandBuffers );
+ }
+
+ void EndPrimaryRenderPass( SwapchainBuffer& currentBuffer )
+ {
+ currentBuffer.masterCmdBuffer->EndRenderPass();
+ }
+
+ /**
+ * Performs layout transition for all the color attachments
+ * in the current framebuffer.
+ * The master command buffer must be in the recording state
+ * @param swapBuffer
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
+ void UpdateLayoutPresentToColorAttachment( SwapchainBuffer& swapBuffer )
+ {
+ auto& cmdBuf = swapBuffer.masterCmdBuffer;
+
+ //todo: test the state of th ebuffer, must be recording
+
+ auto attachments = swapBuffer.framebuffer->GetAttachments( Framebuffer::AttachmentType::COLOR );
+
+ std::vector<vk::ImageMemoryBarrier> barriers;
+ vk::ImageMemoryBarrier barrier;
+ barrier.setSrcAccessMask( vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eColorAttachmentRead )
+ .setDstAccessMask( vk::AccessFlagBits::eColorAttachmentWrite )
+ .setOldLayout( vk::ImageLayout::ePresentSrcKHR )
+ .setNewLayout( vk::ImageLayout::eColorAttachmentOptimal )
+ .setSubresourceRange( vk::ImageSubresourceRange{}.setAspectMask( vk::ImageAspectFlagBits::eColor ).setBaseArrayLayer(0)
+ .setBaseMipLevel(0)
+ .setLevelCount(1)
+ .setLayerCount(1));
+
+ for( auto&& imageView : attachments )
+ {
+ barriers.emplace_back( barrier.setImage( *imageView->GetImage() ) );
+ }
+
+ cmdBuf->PipelineBarrier( vk::PipelineStageFlagBits::eBottomOfPipe,
+ vk::PipelineStageFlagBits::eColorAttachmentOutput,
+ vk::DependencyFlags{},
+ std::vector<vk::MemoryBarrier>{},
+ std::vector<vk::BufferMemoryBarrier>{},
+ barriers );
+ }
+#pragma GCC diagnostic pop
+
+ CommandBufferRef GetPrimaryCommandBuffer() const
+ {
+ return mSwapchainBuffer[mCurrentBufferIndex].masterCmdBuffer;
+ }
+
+ bool Present()
+ {
+ auto& swapBuffer = mSwapchainBuffer[mCurrentBufferIndex];
+
+ // end render pass
+ EndPrimaryRenderPass( swapBuffer );
+
+ // end command buffer
+ swapBuffer.masterCmdBuffer->End();
+
+ // submit
+ swapBuffer.endOfFrameFence->Reset();
+ mQueue.Submit( swapBuffer.masterCmdBuffer, swapBuffer.endOfFrameFence );
+ swapBuffer.endOfFrameFence->Wait( 0u );
+
+ // fixme: use semaphores to synchronize all previously submitted command buffers!
+ vk::PresentInfoKHR presentInfo{};
+ vk::Result result;
+ presentInfo.setPImageIndices( &mCurrentBufferIndex )
+ .setPResults( &result )
+ .setPSwapchains( &mSwapchainKHR )
+ .setSwapchainCount( 1 )
+ .setPWaitSemaphores( nullptr )
+ .setWaitSemaphoreCount( 0 );
+ mQueue.Present( presentInfo );
+
+ // just to speed things up :P
+ mQueue.WaitIdle();
+
+ return true;
+ }
+
+ // same as present but additionally waits for semaphores
+ // needed when present queue is different from graphics queue
+ bool Present( std::vector<vk::Semaphore> semaphores )
+ {
+ vk::PresentInfoKHR presentInfo{};
+ vk::Result result{};
+ presentInfo.setPImageIndices( &mCurrentBufferIndex )
+ .setPResults( &result )
+ .setPSwapchains( &mSwapchainKHR )
+ .setSwapchainCount( 1 )
+ .setPWaitSemaphores( nullptr )
+ .setWaitSemaphoreCount( 0 );
+
+ mQueue.Present( presentInfo );
+
+ return true;
+ }
+
+ Swapchain& mOwner;
+ Graphics& mGraphics;
+ Queue& mQueue;
+ SurfaceRef mSurface;
+
+ uint32_t mBufferCount;
+ uint32_t mFlags;
+ uint32_t mCurrentBufferIndex;
+
+ FenceRef mFrameFence;
+
+ // swapchain framebuffers
+ std::vector<FramebufferRef> mFramebuffers;
+
+ vk::SwapchainKHR mSwapchainKHR;
+ vk::SwapchainCreateInfoKHR mSwapchainCreateInfoKHR;
+
+ vk::Format mSwapchainImageFormat;
+ vk::ColorSpaceKHR mSwapchainColorSpace;
+ vk::Extent2D mSwapchainExtent;
+
+ std::vector<SwapchainBuffer> mSwapchainBuffer;
+
+ bool mFirstPresent;
+};
+
+/**
+ * Swapchain API
+ */
+SwapchainRef Swapchain::New(
+ Graphics& graphics, Queue& presentationQueue, SurfaceRef surface, uint8_t bufferCount, uint32_t flags )
+{
+ auto retval = SwapchainRef( new Swapchain( graphics, presentationQueue, surface, bufferCount, flags ) );
+
+ if( retval->mImpl->Initialise() )
+ {
+ return retval;
+ }
+
+ return SwapchainRef();
+}
+
+Swapchain::Swapchain(
+ Graphics& graphics, Queue& presentationQueue, SurfaceRef surface, uint8_t bufferCount, uint32_t flags )
+{
+ mImpl = std::make_unique<Impl>( *this, graphics, presentationQueue, surface, bufferCount, flags );
+}
+
+Swapchain::Swapchain() = default;
+Swapchain::~Swapchain() = default;
+
+FramebufferRef Swapchain::GetCurrentFramebuffer() const
+{
+ return GetFramebuffer( mImpl->mCurrentBufferIndex );
+}
+
+FramebufferRef Swapchain::GetFramebuffer( uint32_t index ) const
+{
+ return mImpl->mSwapchainBuffer[index].framebuffer;
+}
+
+FramebufferRef Swapchain::AcquireNextFramebuffer()
+{
+ return mImpl->AcquireNextFramebuffer();
+}
+
+void Swapchain::Present()
+{
+ mImpl->Present();
+}
+
+void Swapchain::Present( std::vector<vk::Semaphore> waitSemaphores )
+{
+ mImpl->Present( waitSemaphores );
+}
+
+CommandBufferRef Swapchain::GetPrimaryCommandBuffer() const
+{
+ return mImpl->GetPrimaryCommandBuffer();
+}
+
+} // namespace Vulkan
+} // namespace Graphics
+} // namespace Dali
--- /dev/null
+#ifndef DALI_GRAPHICS_VULKAN_SWAPCHAIN_H
+#define DALI_GRAPHICS_VULKAN_SWAPCHAIN_H
+
+/*
+ * 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 <dali/graphics/vulkan/vulkan-types.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class Surface;
+class Queue;
+
+/**
+ * Creates swapchain for given surface and queue
+ */
+class Swapchain : public VkManaged
+{
+public:
+
+ static SwapchainRef New( Graphics& graphics, Queue& presentationQueue, SurfaceRef surface, uint8_t bufferCount, uint32_t flags );
+
+public:
+
+ Swapchain( const Swapchain& ) = delete;
+ Swapchain& operator=( const Swapchain& ) = delete;
+
+ /**
+ * Returns current framebuffer ( the one which is rendering to )
+ * @return
+ */
+ FramebufferRef GetCurrentFramebuffer() const;
+
+ /**
+ * Returns any framebuffer from the queue
+ * @param index
+ * @return
+ */
+ FramebufferRef GetFramebuffer( uint32_t index ) const;
+
+ /**
+ * Requests for next framebuffer
+ * @return
+ */
+ FramebufferRef AcquireNextFramebuffer();
+
+ /**
+ * Returns primary command buffer associated with currently
+ * being recorded frame
+ * @return
+ */
+ CommandBufferRef GetPrimaryCommandBuffer() const;
+
+ /**
+ * Presents using default present queue, asynchronously
+ */
+ void Present();
+
+ /**
+ * Presents using default queue, synchronized with supplied semaphores
+ * @param waitSemaphores
+ */
+ void Present( std::vector<vk::Semaphore> waitSemaphores );
+
+private:
+
+ Swapchain();
+ Swapchain( Graphics& graphics, Queue& presentationQueue, SurfaceRef surface, uint8_t bufferCount, uint32_t flags );
+ ~Swapchain() override;
+
+private:
+
+ struct Impl;
+ std::unique_ptr<Impl> mImpl;
+};
+
+} // namespace Vulkan
+} // namespace Graphics
+} // namespace Dali
+#endif //DALI_GRAPHICS_VULKAN_SWAPCHAIN_H
/**
* Unique pointers to Vulkan types
*/
-using UniqueSurface = std::unique_ptr< Surface >;
using UniqueQueue = std::unique_ptr< Queue >;
/**
* Reference wrappers
*/
using QueueRef = std::reference_wrapper< Queue >;
-using SurfaceRef = std::reference_wrapper< Surface >;
-
template< typename T >
T VkAssert(const vk::ResultValue< T >& result, vk::Result expected = vk::Result::eSuccess)
std::atomic_uint mRefCount { 0u };
};
-using FBID = uint32_t;
+using FBID = int32_t;
#define NotImplemented() \
{\
using CommandBufferRef = Handle<class CommandBuffer>;
using GpuMemoryBlockRef = Handle<class GpuMemoryBlock>;
using DescriptorSetRef = Handle<class DescriptorSet>;
+using SwapchainRef = Handle<class Swapchain>;
+using SurfaceRef = Handle<class Surface>;
+
/*
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wframe-larger-than="
#include <dali/graphics/vulkan/vulkan-types.h>
#include <dali/graphics/vulkan/vulkan-graphics.h>
#include <dali/graphics/vulkan/vulkan-surface.h>
+#include <dali/graphics/vulkan/vulkan-framebuffer.h>
#include <dali/graphics-api/graphics-api-controller.h>
#include <dali/integration-api/graphics/graphics.h>
+
namespace Dali
{
/// fixme: substituting directly the vulkan implementation
{
namespace Graphics
{
+using Swapchain = Dali::Graphics::Vulkan::Swapchain;
+using SwapchainRef = Dali::Graphics::Vulkan::SwapchainRef;
Graphics::Graphics()
{
Dali::Graphics::FBID Graphics::Create(
std::unique_ptr<Dali::Integration::Graphics::SurfaceFactory> surfaceFactory)
{
+ //@todo do we really need to have a surface that early???
// create surface
auto retval = mGraphicsImpl->CreateSurface(std::move(surfaceFactory));
// create device
mGraphicsImpl->CreateDevice();
+ // create swapchain from surface
+ auto surface = mGraphicsImpl->GetSurface( retval );
+
// create swapchain
- mGraphicsImpl->GetSurface( retval ).CreateSwapchain();
+ mGraphicsImpl->CreateSwapchainForSurface( surface );
return retval;
}
void Graphics::PreRender(Dali::Graphics::FBID framebufferId)
{
- assert(framebufferId != 0u && "Invalid FBID!");
- auto &surface = mGraphicsImpl->GetSurface(framebufferId);
- surface.AcquireNextImage();
+ assert(framebufferId != 0 && "Invalid FBID!");
+ auto swapchain = mGraphicsImpl->GetSwapchainForFBID( framebufferId );
+ swapchain->AcquireNextFramebuffer();
}
Dali::Graphics::API::Controller& Graphics::GetController()
*/
void Graphics::PostRender(Dali::Graphics::FBID framebufferId)
{
- assert(framebufferId != 0u && "Invalid FBID!");
- auto &surface = mGraphicsImpl->GetSurface(framebufferId);
- surface.Present();
+ auto swapchain = mGraphicsImpl->GetSwapchainForFBID( framebufferId );
+ swapchain->Present();
}
void IncludeThisLibrary()
class Controller;
}
// frame buffer id
-using FBID = uint32_t;
+using FBID = int32_t;
namespace Vulkan
{
public:
SurfaceFactory() = default;
virtual ~SurfaceFactory() = default;
+
+ SurfaceFactory( const SurfaceFactory& ) = delete;
+ SurfaceFactory& operator=( const SurfaceFactory& ) = delete;
};
} // Namespace Graphics