From 731bae1985c3b97f37ae588e126608db4a947617 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Sun, 6 Nov 2016 21:02:41 +0100 Subject: [PATCH 01/20] Add script for SPIR-V compiling Signed-off-by: Kristof Kosztyo --- src/engines/vulkan/gepard-vulkan.cpp | 4 +- tools/scripts/build-vulkan-shaders.py | 60 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 tools/scripts/build-vulkan-shaders.py diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index a30c98f4..67b71ed7 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -241,10 +241,10 @@ void GepardVulkan::fillRect(Float x, Float y, Float w, Float h) //! \todo (kkristof) better file handling is needed. { - std::ifstream vertexInput( "src/engines/vulkan/shaders/vert.spv", std::ios::binary ); + std::ifstream vertexInput( "src/engines/vulkan/shaders/fill-rect.vert.spv", std::ios::binary ); std::vector vertexCode((std::istreambuf_iterator(vertexInput)), (std::istreambuf_iterator())); - std::ifstream fragmentInput( "src/engines/vulkan/shaders/frag.spv", std::ios::binary ); + std::ifstream fragmentInput( "src/engines/vulkan/shaders/fill-rect.frag.spv", std::ios::binary ); std::vector fragmentCode((std::istreambuf_iterator(fragmentInput)), (std::istreambuf_iterator())); const VkShaderModuleCreateInfo vertexModulInfo = { diff --git a/tools/scripts/build-vulkan-shaders.py b/tools/scripts/build-vulkan-shaders.py new file mode 100644 index 00000000..93360178 --- /dev/null +++ b/tools/scripts/build-vulkan-shaders.py @@ -0,0 +1,60 @@ +#! /usr/bin/python -B +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016, Gepard Graphics +# Copyright (C) 2016, Kristóf Kosztyó +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import fnmatch +import os +import subprocess +import util + +glslang_path = os.path.join(util.get_base_path(), 'thirdparty', 'glslang') +glslang_path_build = os.path.join(glslang_path, 'build') +glslang_git_url = 'https://github.com/KhronosGroup/glslang.git' + +shader_source_directory = os.path.join(util.get_base_path(), 'src', 'engines', 'vulkan', 'shaders') + +def prepare_glslang(): + if (not os.path.exists(glslang_path)): + util.call(['git', 'clone', glslang_git_url, glslang_path]) + util.call(['cmake', '-B' + glslang_path_build, '-H' + glslang_path]) + util.call(['make', '-C' + glslang_path_build]) + +def collect_shader_sources(): + shader_files = [] + for file in os.listdir(shader_source_directory): + if fnmatch.fnmatch(file, '*.frag') or fnmatch.fnmatch(file, '*.vert'): + shader_files.append(file) + return shader_files + +def compile_shader(shader): + glslang_binary = os.path.join(glslang_path_build, 'StandAlone', 'glslangValidator') + shader_path = os.path.join(shader_source_directory, shader) + util.call([glslang_binary, '-V', shader_path, '-o', shader_path + '.spv']) + +if __name__ == '__main__': + prepare_glslang() + for shader in collect_shader_sources(): + compile_shader(shader) From a05f278aa8debdf6534b38c26e72f3466ac073c6 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Thu, 17 Nov 2016 17:55:26 +0100 Subject: [PATCH 02/20] Store the SPIR-V binaries in auto-generated source files Signed-off-by: Kristof Kosztyo --- src/CMakeLists.txt | 2 + src/engines/vulkan/gepard-vulkan.cpp | 16 ++--- src/engines/vulkan/gepard-vulkan.h | 1 + tools/scripts/build-vulkan-shaders.py | 93 ++++++++++++++++++++++++++- 4 files changed, 99 insertions(+), 13 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 81b94a3f..dbeb5bf9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,7 @@ set(GLES2_SOURCES set(VULKAN_SOURCES engines/vulkan/gepard-vulkan-interface.cpp engines/vulkan/gepard-vulkan.cpp + engines/vulkan/shaders/gepard-vulkan-spirv-binaries.cpp ) set(SOFTWARE_SOURCES @@ -33,6 +34,7 @@ set(GLES2_INCLUDE_DIRS set(VULKAN_INCLUDE_DIRS engines/vulkan + engines/vulkan/shaders ) set(SOFTWARE_INCLUDE_DIRS diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index 67b71ed7..e8cfe4ad 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -239,20 +239,13 @@ void GepardVulkan::fillRect(Float x, Float y, Float w, Float h) VkShaderModule vertex; VkShaderModule fragment; - //! \todo (kkristof) better file handling is needed. { - std::ifstream vertexInput( "src/engines/vulkan/shaders/fill-rect.vert.spv", std::ios::binary ); - std::vector vertexCode((std::istreambuf_iterator(vertexInput)), (std::istreambuf_iterator())); - - std::ifstream fragmentInput( "src/engines/vulkan/shaders/fill-rect.frag.spv", std::ios::binary ); - std::vector fragmentCode((std::istreambuf_iterator(fragmentInput)), (std::istreambuf_iterator())); - const VkShaderModuleCreateInfo vertexModulInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType; nullptr, // const void* pNext; 0, // VkShaderModuleCreateFlags flags; - vertexCode.size(), // size_t codeSize; - reinterpret_cast(vertexCode.data()), // const uint32_t* pCode; + sizeof(fillRectVert), // size_t codeSize; + fillRectVert, // const uint32_t* pCode; }; _vk.vkCreateShaderModule(_device, &vertexModulInfo, _allocator, &vertex); @@ -260,9 +253,10 @@ void GepardVulkan::fillRect(Float x, Float y, Float w, Float h) VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType; nullptr, // const void* pNext; 0, // VkShaderModuleCreateFlags flags; - fragmentCode.size(), // size_t codeSize; - reinterpret_cast(fragmentCode.data()), // const uint32_t* pCode; + sizeof(fillRectFrag), // size_t codeSize; + fillRectFrag, // const uint32_t* pCode; }; + _vk.vkCreateShaderModule(_device, &fragmentModulInfo, _allocator, &fragment); } diff --git a/src/engines/vulkan/gepard-vulkan.h b/src/engines/vulkan/gepard-vulkan.h index d00846c7..9dbddf05 100644 --- a/src/engines/vulkan/gepard-vulkan.h +++ b/src/engines/vulkan/gepard-vulkan.h @@ -34,6 +34,7 @@ #include "gepard-image.h" #include "gepard-types.h" #include "gepard-vulkan-interface.h" +#include "gepard-vulkan-spirv-binaries.h" #include namespace gepard { diff --git a/tools/scripts/build-vulkan-shaders.py b/tools/scripts/build-vulkan-shaders.py index 93360178..53dd5323 100644 --- a/tools/scripts/build-vulkan-shaders.py +++ b/tools/scripts/build-vulkan-shaders.py @@ -27,6 +27,7 @@ import fnmatch import os +import re import subprocess import util @@ -36,6 +37,35 @@ shader_source_directory = os.path.join(util.get_base_path(), 'src', 'engines', 'vulkan', 'shaders') +c_file_name = 'gepard-vulkan-spirv-binaries' +generated_warning = '/* This file was auto-generated by {0}! */\n\n'.format(__file__) + +header_begin = ''' +#ifndef {0}_H +#define {0}_H + +#include +'''.format(re.sub('-', '_', c_file_name).upper()) +header_end = ''' +#endif // {0}_H +'''.format(re.sub('-', '_', c_file_name).upper()) + +namespace_begin = ''' +namespace gepard { +namespace vulkan { + +''' + +namespace_end = ''' +} // namespace vulkan +} // namespace gepard +''' + +c_header = '#include "{0}"\n'.format(c_file_name + '.h') +c_header += namespace_begin + +c_footer = namespace_end + def prepare_glslang(): if (not os.path.exists(glslang_path)): util.call(['git', 'clone', glslang_git_url, glslang_path]) @@ -49,12 +79,71 @@ def collect_shader_sources(): shader_files.append(file) return shader_files +def get_spirv_path(shader): + return os.path.join(shader_source_directory, shader) + '.spv' + def compile_shader(shader): glslang_binary = os.path.join(glslang_path_build, 'StandAlone', 'glslangValidator') shader_path = os.path.join(shader_source_directory, shader) - util.call([glslang_binary, '-V', shader_path, '-o', shader_path + '.spv']) + util.call([glslang_binary, '-V', shader_path, '-o', get_spirv_path(shader)]) + +def to_camel_case(mathcobj): + return mathcobj.group(1).upper() + +def normailze_shader_name(shader_name): + return re.sub('[\.-](\w)', to_camel_case, shader_name) + +def prepare_header_declaration(shaders): + declaration_string = '' + for shader, length in shaders.iteritems(): + declaration_string += 'extern const uint32_t {0}[{1}];\n'.format(normailze_shader_name(shader), length) + return declaration_string + +def write_header(declaration_string): + header_path = os.path.join(shader_source_directory, c_file_name+'.h') + header_file = open(header_path, 'w') + header_string = generated_warning + header_begin + namespace_begin + declaration_string + namespace_end + header_end + header_file.write(header_string) + header_file.close() + +def get_spirv_sizes(shaders): + shader_size_map = {} + for shader in shaders: + shader_size_map[shader] = os.path.getsize(get_spirv_path(shader)) / 4 + return shader_size_map + +def create_binary_data(shader, length): + binary_data = '{\n' + spirv_file = open(get_spirv_path(shader), 'rb') + for i in range(length): + word = (ord(spirv_file.read(1))) + (ord(spirv_file.read(1)) << 8) + (ord(spirv_file.read(1)) << 16) + (ord(spirv_file.read(1)) << 24) + binary_data += ' {0},\n'.format(word) + spirv_file.close() + binary_data += '}' + return binary_data + +def prepare_c_source(shaders): + source = '' + for shader, length in shaders.iteritems(): + source += 'const uint32_t {0}[{1}] = {2};\n\n'.format(normailze_shader_name(shader), length, create_binary_data(shader, length)) + return source + +def write_c_source(source): + source_path = os.path.join(shader_source_directory, c_file_name+'.cpp') + source_file = open(source_path, 'w') + source_file.write(generated_warning) + source_file.write(c_header) + source_file.write(source) + source_file.write(c_footer) + source_file.close() if __name__ == '__main__': prepare_glslang() - for shader in collect_shader_sources(): + shader_souces = collect_shader_sources() + for shader in shader_souces: compile_shader(shader) + shader_size_map = get_spirv_sizes(shader_souces) + + write_header(prepare_header_declaration(shader_size_map)) + source = prepare_c_source(shader_size_map) + write_c_source(source) From 5d20ddf4d47c159f3dea679ece42337b7014b241 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Fri, 13 Jan 2017 22:44:21 +0100 Subject: [PATCH 03/20] WIP: Add intel vulkan support Signed-off-by: Kristof Kosztyo --- examples/fill-rect/CMakeLists.txt | 2 +- examples/savanna-benchmark/CMakeLists.txt | 2 +- .../vulkan/gepard-vulkan-interface.cpp | 3 ++ src/engines/vulkan/gepard-vulkan-interface.h | 7 ++++- src/engines/vulkan/gepard-vulkan.cpp | 30 +++++++++++++++++-- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/examples/fill-rect/CMakeLists.txt b/examples/fill-rect/CMakeLists.txt index 616b80a3..4dc1357e 100644 --- a/examples/fill-rect/CMakeLists.txt +++ b/examples/fill-rect/CMakeLists.txt @@ -5,4 +5,4 @@ set(SOURCES add_executable(fill-rect EXCLUDE_FROM_ALL ${SOURCES}) add_dependencies(examples fill-rect) -target_link_libraries(fill-rect gepard X11 png ${LIB_DEPENDENCIES}) +target_link_libraries(fill-rect gepard X11 X11-xcb png ${LIB_DEPENDENCIES}) diff --git a/examples/savanna-benchmark/CMakeLists.txt b/examples/savanna-benchmark/CMakeLists.txt index 955c045f..806924db 100644 --- a/examples/savanna-benchmark/CMakeLists.txt +++ b/examples/savanna-benchmark/CMakeLists.txt @@ -13,4 +13,4 @@ include_directories(${INCLUDE_DIRS}) add_executable(savanna-benchmark EXCLUDE_FROM_ALL ${SOURCES}) add_dependencies(examples savanna-benchmark) -target_link_libraries(savanna-benchmark gepard X11 ${LIB_DEPENDENCIES}) +target_link_libraries(savanna-benchmark gepard X11 X11-xcb ${LIB_DEPENDENCIES}) diff --git a/src/engines/vulkan/gepard-vulkan-interface.cpp b/src/engines/vulkan/gepard-vulkan-interface.cpp index bb98e07a..25fa4689 100644 --- a/src/engines/vulkan/gepard-vulkan-interface.cpp +++ b/src/engines/vulkan/gepard-vulkan-interface.cpp @@ -71,6 +71,9 @@ void GepardVulkanInterface::loadInstanceFunctions(const VkInstance instance) #if defined(VK_USE_PLATFORM_XLIB_KHR) GD_VK_LOAD_FUNCTION(vkCreateXlibSurfaceKHR); #endif // VK_USE_PLATFORM_XLIB_KHR +#if defined(VK_USE_PLATFORM_XCB_KHR) + GD_VK_LOAD_FUNCTION(vkCreateXcbSurfaceKHR); +#endif // VK_USE_PLATFORM_XCB_KHR #undef GD_VK_LOAD_FUNCTION } diff --git a/src/engines/vulkan/gepard-vulkan-interface.h b/src/engines/vulkan/gepard-vulkan-interface.h index b1374962..b3886efa 100644 --- a/src/engines/vulkan/gepard-vulkan-interface.h +++ b/src/engines/vulkan/gepard-vulkan-interface.h @@ -31,7 +31,8 @@ #include "gepard-defs.h" // TODO: move this define to the build system -#define VK_USE_PLATFORM_XLIB_KHR +//#define VK_USE_PLATFORM_XLIB_KHR +#define VK_USE_PLATFORM_XCB_KHR #include @@ -105,6 +106,7 @@ namespace vulkan { FUNC(vkCmdDrawIndexedIndirect); \ FUNC(vkCreateFence); \ FUNC(vkDestroyFence); \ + FUNC(vkResetFences); \ FUNC(vkWaitForFences); \ FUNC(vkCmdBindVertexBuffers); \ FUNC(vkCmdBindIndexBuffer); \ @@ -141,6 +143,9 @@ class GepardVulkanInterface { #if defined(VK_USE_PLATFORM_XLIB_KHR) GD_VK_DECLARE_FUNCTION(vkCreateXlibSurfaceKHR); #endif // VK_USE_PLATFORM_XLIB_KHR +#if defined(VK_USE_PLATFORM_XCB_KHR) + GD_VK_DECLARE_FUNCTION(vkCreateXcbSurfaceKHR); +#endif // VK_USE_PLATFORM_XCB_KHR GD_VK_DEVICE_FUNTION_LIST(GD_VK_DECLARE_FUNCTION) diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index e8cfe4ad..63cc662e 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -38,16 +38,22 @@ #include #include #endif // VK_USE_PLATFORM_XLIB_KHR +#ifdef VK_USE_PLATFORM_XCB_KHR +#include +#endif // VK_USE_PLATFORM_XCB_KHR namespace gepard { namespace vulkan { static const uint64_t oneMiliSec = 1000000; static const uint64_t timeout = (uint64_t)16 * oneMiliSec; // 16 ms +#ifdef VK_USE_PLATFORM_XCB_KHR +static xcb_connection_t* xcbConnection; +#endif GepardVulkan::GepardVulkan(GepardContext& context) : _context(context) - , _vk("libvulkan.so") + , _vk("libvulkan.so.1") , _allocator(nullptr) , _instance(0) , _imageFormat(VK_FORMAT_R8G8B8A8_UNORM) @@ -544,6 +550,9 @@ void GepardVulkan::createDefaultInstance() VK_KHR_SURFACE_EXTENSION_NAME, #ifdef VK_USE_PLATFORM_XLIB_KHR VK_KHR_XLIB_SURFACE_EXTENSION_NAME, +#endif // VK_USE_PLATFORM_XLIB_KHR +#ifdef VK_USE_PLATFORM_XCB_KHR + VK_KHR_XCB_SURFACE_EXTENSION_NAME, #endif // VK_USE_PLATFORM_XLIB_KHR }; @@ -561,7 +570,8 @@ void GepardVulkan::createDefaultInstance() enabledExtensionNames, // const char* const* ppEnabledExtensionNames; }; - _vk.vkCreateInstance(&instanceCreateInfo, _allocator, &_instance); + VkResult result = _vk.vkCreateInstance(&instanceCreateInfo, _allocator, &_instance); + GD_ASSERT(_instance); } @@ -942,6 +952,20 @@ void GepardVulkan::createSwapChain() }; _vk.vkCreateXlibSurfaceKHR(_instance, &surfaceCreateInfo, _allocator, &_wsiSurface); +#elif defined(VK_USE_PLATFORM_XCB_KHR) + XSync((Display*)_context.surface->getDisplay(), false); + + xcbConnection = XGetXCBConnection((Display*)_context.surface->getDisplay()); + + const VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = { + VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkXlibSurfaceCreateFlagsKHR flags; + xcbConnection, // xcb_connection_t* connection; + (xcb_window_t)_context.surface->getWindow(), // xcb_window_t window; + }; + + _vk.vkCreateXcbSurfaceKHR(_instance, &surfaceCreateInfo, _allocator, &_wsiSurface); #else GD_CRASH("Unimplemented WSI platform!"); #endif // VK_USE_PLATFORM_XLIB_KHR @@ -1029,7 +1053,9 @@ void GepardVulkan::presentImage() _vk.vkCreateFence(_device, &fenceInfo, _allocator, &fence); uint32_t imageIndex; + //! /todo: handle if the timeout is triggered _vk.vkAcquireNextImageKHR(_device, _wsiSwapChain, timeout, VK_NULL_HANDLE, fence, &imageIndex); + _vk.vkResetFences(_device, 1, &fence); VkQueue queue; _vk.vkGetDeviceQueue(_device, _queueFamilyIndex, 0, &queue); From 39db3ced350a8b135f97c164035a8ad28d9fe6c1 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Sun, 25 Jun 2017 20:22:50 +0200 Subject: [PATCH 04/20] Change the default timeout to 32 ms In some cases the default 16 ms timeout value wasn't enough. Signed-off-by: Kristof Kosztyo --- src/engines/vulkan/gepard-vulkan.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index 63cc662e..5a086959 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -46,7 +46,7 @@ namespace gepard { namespace vulkan { static const uint64_t oneMiliSec = 1000000; -static const uint64_t timeout = (uint64_t)16 * oneMiliSec; // 16 ms +static const uint64_t timeout = (uint64_t)32 * oneMiliSec; // 32 ms #ifdef VK_USE_PLATFORM_XCB_KHR static xcb_connection_t* xcbConnection; #endif @@ -516,9 +516,12 @@ void GepardVulkan::fillRect(Float x, Float y, Float w, Float h) }; VkFence fence; + VkResult vkResult; _vk.vkCreateFence(_device, &fenceInfo, _allocator, &fence); _vk.vkQueueSubmit(queue, 1, &submitInfo, fence); - _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); + vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); + if (vkResult == VK_TIMEOUT) + GD_LOG1("TIMEOUT!"); if(_context.surface->getDisplay()) { presentImage(); @@ -871,7 +874,9 @@ void GepardVulkan::createSurfaceImage() VkFence fence; _vk.vkCreateFence(_device, &fenceInfo, _allocator, &fence); _vk.vkQueueSubmit(queue, 1, &submitInfo, fence); - _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); + vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); + if (vkResult == VK_TIMEOUT) + GD_LOG1("TIMEOUT!"); _vk.vkDestroyFence(_device, fence, _allocator); } @@ -1184,8 +1189,11 @@ void GepardVulkan::presentImage() nullptr, // const VkSemaphore* pSignalSemaphores; }; + VkResult vkResult; _vk.vkQueueSubmit(queue, 1, &submitInfo, fence); - _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); + vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); + if (vkResult == VK_TIMEOUT) + GD_LOG1("TIMEOUT!"); const VkPresentInfoKHR presentInfo = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType; @@ -1341,9 +1349,12 @@ void GepardVulkan::readImage() }; VkFence fence; + VkResult vkResult; _vk.vkCreateFence(_device, &fenceInfo, _allocator, &fence); _vk.vkQueueSubmit(queque, 1, &submitInfo, fence); - _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); + vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); + if (vkResult == VK_TIMEOUT) + GD_LOG1("TIMEOUT!"); void* data; _vk.vkMapMemory(_device, bufferAlloc, 0, dataSize, 0, &data); From 3f5511d1dfe32a7ddcf20159a8e0ea08234e5110 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Thu, 18 Jan 2018 19:05:47 +0100 Subject: [PATCH 05/20] Push the X11-xcb dependency to the Vulkan port Signed-off-by: Kristof Kosztyo --- cmake/deps/FindVULKAN.cmake | 3 +++ examples/fill-rect/CMakeLists.txt | 2 +- examples/savanna-benchmark/CMakeLists.txt | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmake/deps/FindVULKAN.cmake b/cmake/deps/FindVULKAN.cmake index 3da9618f..aad431fb 100644 --- a/cmake/deps/FindVULKAN.cmake +++ b/cmake/deps/FindVULKAN.cmake @@ -6,3 +6,6 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(VULKAN REQUIRED_VARS VULKAN_INCLUDE_DIR) include_directories(${VULKAN_INCLUDE_DIR}) + +# TODO: Find a way to remove this dependency of the vulkan port +list(APPEND LIB_DEPENDENCIES X11-xcb) diff --git a/examples/fill-rect/CMakeLists.txt b/examples/fill-rect/CMakeLists.txt index 4dc1357e..616b80a3 100644 --- a/examples/fill-rect/CMakeLists.txt +++ b/examples/fill-rect/CMakeLists.txt @@ -5,4 +5,4 @@ set(SOURCES add_executable(fill-rect EXCLUDE_FROM_ALL ${SOURCES}) add_dependencies(examples fill-rect) -target_link_libraries(fill-rect gepard X11 X11-xcb png ${LIB_DEPENDENCIES}) +target_link_libraries(fill-rect gepard X11 png ${LIB_DEPENDENCIES}) diff --git a/examples/savanna-benchmark/CMakeLists.txt b/examples/savanna-benchmark/CMakeLists.txt index 806924db..955c045f 100644 --- a/examples/savanna-benchmark/CMakeLists.txt +++ b/examples/savanna-benchmark/CMakeLists.txt @@ -13,4 +13,4 @@ include_directories(${INCLUDE_DIRS}) add_executable(savanna-benchmark EXCLUDE_FROM_ALL ${SOURCES}) add_dependencies(examples savanna-benchmark) -target_link_libraries(savanna-benchmark gepard X11 X11-xcb ${LIB_DEPENDENCIES}) +target_link_libraries(savanna-benchmark gepard X11 ${LIB_DEPENDENCIES}) From e9bd0cef7a183bc6fea56cf48c8f96756f1d3952 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Sun, 1 Jul 2018 20:33:34 +0200 Subject: [PATCH 06/20] Add basic image class --- apps/examples/CMakeLists.txt | 1 + apps/examples/image/CMakeLists.txt | 12 ++++ apps/examples/image/image.cpp | 66 ++++++++++++++++++ src/CMakeLists.txt | 1 + src/engines/vulkan/gepard-vulkan-interface.h | 4 +- src/engines/vulkan/gepard-vulkan.cpp | 5 ++ src/engines/vulkan/gepard-vulkan.h | 1 + src/gepard-engine.cpp | 22 ++++++ src/gepard-engine.h | 2 + src/gepard-image.cpp | 71 ++++++++++++++++++++ src/gepard-image.h | 20 +++++- src/gepard.cpp | 23 ++++--- 12 files changed, 212 insertions(+), 16 deletions(-) create mode 100644 apps/examples/image/CMakeLists.txt create mode 100644 apps/examples/image/image.cpp create mode 100644 src/gepard-image.cpp diff --git a/apps/examples/CMakeLists.txt b/apps/examples/CMakeLists.txt index 05b9b98d..77157708 100644 --- a/apps/examples/CMakeLists.txt +++ b/apps/examples/CMakeLists.txt @@ -4,5 +4,6 @@ include_directories(${PROJECT_BINARY_DIR}/include/) add_subdirectory(fill-path) add_subdirectory(fill-rect) +add_subdirectory(image) add_subdirectory(path-clock) add_subdirectory(savanna-benchmark) diff --git a/apps/examples/image/CMakeLists.txt b/apps/examples/image/CMakeLists.txt new file mode 100644 index 00000000..d649f4fd --- /dev/null +++ b/apps/examples/image/CMakeLists.txt @@ -0,0 +1,12 @@ +set(SOURCES + image.cpp +) + +add_executable(image ${SOURCES}) +add_dependencies(examples image) + +find_package(PNG) +find_package(X11) + +message("deps " ${GEPARD_DEP_LIBS}) +target_link_libraries(image gepard ${X11_LIBRARIES} ${PNG_LIBRARIES} ${GEPARD_DEP_LIBS}) diff --git a/apps/examples/image/image.cpp b/apps/examples/image/image.cpp new file mode 100644 index 00000000..3519eb63 --- /dev/null +++ b/apps/examples/image/image.cpp @@ -0,0 +1,66 @@ +/* Copyright (C) 2018, Gepard Graphics + * Copyright (C) 2018, Kristof Kosztyo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gepard.h" +#include "gepard-image.h" +#include "surfaces/gepard-png-surface.h" +#include + +#define SURFACE_SIZE 600 + +void generateCheckerBoard(gepard::Gepard& gepard) +{ + int cellWidth = SURFACE_SIZE / 8; + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + if ((i+j) % 2) { + gepard.setFillColor(0.3f, 0.3f, 0.3f, 1.0f); + } else { + gepard.setFillColor(0.8f, 0.8f, 0.8f, 1.0f); + } + gepard.fillRect(i * cellWidth, j * cellWidth, cellWidth, cellWidth); + } + } +} + +int main() +{ + gepard::PNGSurface surface(SURFACE_SIZE, SURFACE_SIZE); + gepard::Gepard gepard(&surface); + + generateCheckerBoard(gepard); + + gepard::Image image = gepard.createImageData(200.0, 200.0); + + std::cout << image.width() << " " << image.height() << std::endl; + gepard::Image image2 = gepard.createImageData(image); + std::cout << image2.width() << " " << image2.height() << std::endl; + + gepard.putImageData(image, 20, 20); + + surface.save("image.png"); + + return 0; +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6bbeb5bf..642796a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ set(COMMON_SOURCES engines/gepard-path.cpp gepard.cpp gepard-engine.cpp + gepard-image.cpp utils/gepard-types.cpp utils/gepard-defs.cpp ) diff --git a/src/engines/vulkan/gepard-vulkan-interface.h b/src/engines/vulkan/gepard-vulkan-interface.h index b3886efa..f7ba8a32 100644 --- a/src/engines/vulkan/gepard-vulkan-interface.h +++ b/src/engines/vulkan/gepard-vulkan-interface.h @@ -31,8 +31,8 @@ #include "gepard-defs.h" // TODO: move this define to the build system -//#define VK_USE_PLATFORM_XLIB_KHR -#define VK_USE_PLATFORM_XCB_KHR +#define VK_USE_PLATFORM_XLIB_KHR +//#define VK_USE_PLATFORM_XCB_KHR #include diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index 944c767f..c4b13491 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -545,6 +545,11 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F _vk.vkFreeMemory(_device, indexBufferMemory, _allocator); } +void GepardVulkan::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight) +{ + GD_LOG2("putImage " << dx << " " << dy << " " << dirtyWidth << " " << dirtyHeight); +} + void GepardVulkan::fill() { GD_NOT_IMPLEMENTED(); diff --git a/src/engines/vulkan/gepard-vulkan.h b/src/engines/vulkan/gepard-vulkan.h index b30fa9c7..a140cb54 100644 --- a/src/engines/vulkan/gepard-vulkan.h +++ b/src/engines/vulkan/gepard-vulkan.h @@ -51,6 +51,7 @@ class GepardVulkan { ~GepardVulkan(); void fillRect(const Float x, const Float y, const Float w, const Float h); + void putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight); void fill(); void stroke(); diff --git a/src/gepard-engine.cpp b/src/gepard-engine.cpp index a86a633c..8938ac5d 100644 --- a/src/gepard-engine.cpp +++ b/src/gepard-engine.cpp @@ -250,6 +250,28 @@ void GepardEngine::fillRect(Float x, Float y, Float w, Float h) #endif // GD_USE_GLES2 } +/*! + * \brief GepardEngine::putImage + * \param imagedata + * \param dx Horizontal position on the _destination_ + * \param dy Vertical position on the _destination_ + * \param dirtyX Horizontal position on the _source_ + * \param dirtyY Vertical position on the _source_ + * \param dirtyWidth width of the rectangle to be painted + * \param dirtyHeight height of the rectangle to be painted. + * + * Copy the imageData into the canvas. + */ +void GepardEngine::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight) +{ + GD_ASSERT(_engineBackend); +#ifdef GD_USE_VULKAN + _engineBackend->putImage(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight); +#else // !GD_USE_VULKAN + GD_NOT_IMPLEMENTED(); +#endif // GD_USE_VULKAN +} + void GepardEngine::setFillColor(const Color& color) { GD_LOG1("Set fill color (" << color.r << ", " << color.g << ", " << color.b << ", " << color.a << ")"); diff --git a/src/gepard-engine.h b/src/gepard-engine.h index d1d90700..966fee30 100644 --- a/src/gepard-engine.h +++ b/src/gepard-engine.h @@ -82,6 +82,8 @@ class GepardEngine { void fillRect(Float x, Float y, Float w, Float h); + void putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight); + void setFillColor(const Color& color); void setFillColor(const Float red, const Float green, const Float blue, const Float alpha = 1.0f); diff --git a/src/gepard-image.cpp b/src/gepard-image.cpp new file mode 100644 index 00000000..671fa8a4 --- /dev/null +++ b/src/gepard-image.cpp @@ -0,0 +1,71 @@ +/* Copyright (C) 2018, Gepard Graphics + * Copyright (C) 2018, Kristof Kosztyo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gepard-image.h" + +#include + +namespace gepard { + +Image::Image() + : _width(0) + , _height(0) +{ +} + +Image::Image(uint32_t width, uint32_t height) + : _width(width) + , _height(height) +{ + _data.resize(width * height); +} + +Image::Image(uint32_t width, uint32_t height, std::vector data) + : _width(width) + , _height(height) + , _data(data) +{ +} + +Image::~Image() +{ +} + +const uint32_t Image::width() +{ + return _width; +} + +const uint32_t Image::height() +{ + return _height; +} + +std::vector Image::data() +{ + return _data; +} + +} // namespace gepard diff --git a/src/gepard-image.h b/src/gepard-image.h index 4f288725..25301ddf 100644 --- a/src/gepard-image.h +++ b/src/gepard-image.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2015-2016, Gepard Graphics - * Copyright (C) 2016, Kristof Kosztyo +/* Copyright (C) 2015-2018, Gepard Graphics + * Copyright (C) 2016, 2018 Kristof Kosztyo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,10 +28,24 @@ #include "gepard-defs.h" +#include + namespace gepard { class Image { -/*! \todo Implement Image */ +public: + Image(); + Image(uint32_t width, uint32_t height); + Image(uint32_t width, uint32_t height, std::vector data); + virtual ~Image(); + + const uint32_t width(); + const uint32_t height(); + std::vector data(); +private: + uint32_t _width; + uint32_t _height; + std::vector _data; }; } // namespace gepard diff --git a/src/gepard.cpp b/src/gepard.cpp index c03b5c64..cbdf97bd 100644 --- a/src/gepard.cpp +++ b/src/gepard.cpp @@ -598,16 +598,17 @@ void Gepard::drawImage(Image /*image*/, float sx, float sy, float sw, float sh, Image Gepard::createImageData(float sw, float sh) { -/*! \todo unimplemented function */ - GD_NOT_IMPLEMENTED(); - return Image(); + GD_ASSERT(sw >= 0.0 && sh >= 0.0); + uint32_t width = (uint32_t) sw; + uint32_t height = (uint32_t) sh; + return Image(width, height); } -Image Gepard::createImageData(Image /*imagedata*/) +Image Gepard::createImageData(Image imagedata) { -/*! \todo unimplemented function */ - GD_NOT_IMPLEMENTED(); - return Image(); + uint32_t width = imagedata.width(); + uint32_t height = imagedata.height(); + return Image(width, height); } Image Gepard::getImageData(double sx, double sy, double sw, double sh) @@ -617,15 +618,15 @@ Image Gepard::getImageData(double sx, double sy, double sw, double sh) return Image(); } -void Gepard::putImageData(Image /*imagedata*/, double dx, double dy) +void Gepard::putImageData(Image imagedata, double dx, double dy) { -/*! \todo unimplemented function */ + _engine->putImage(imagedata, dx, dy, 0.0, 0.0, imagedata.width(), imagedata.height()); } -void Gepard::putImageData(Image /*imagedata*/, double dx, double dy, double dirtyX, double dirtyY, +void Gepard::putImageData(Image imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight) { - /*! \todo unimplemented function */ + _engine->putImage(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight); } void Gepard::setFillColor(const std::string& color) From 7db46551eff30b5be3d175a982b40b7798d5bf17 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Sun, 1 Jul 2018 23:12:18 +0200 Subject: [PATCH 07/20] Implement putImage function for the vulkan backend Signed-off-by: Kristof Kosztyo --- apps/examples/image/image.cpp | 17 +- src/engines/vulkan/gepard-vulkan.cpp | 239 ++++++++++++++++++++++++++- src/gepard-image.cpp | 2 +- src/gepard-image.h | 2 +- 4 files changed, 256 insertions(+), 4 deletions(-) diff --git a/apps/examples/image/image.cpp b/apps/examples/image/image.cpp index 3519eb63..c01c8928 100644 --- a/apps/examples/image/image.cpp +++ b/apps/examples/image/image.cpp @@ -45,6 +45,18 @@ void generateCheckerBoard(gepard::Gepard& gepard) } } +void fillImage(gepard::Image& image) +{ + for (int i = 0; i < image.width(); i++) { + for (int j = 0; j < image.height(); j++) { + uint32_t color = 0x7f7f7f7f; + + image.data()[i * image.width() + j] = color; + std::cout << image.data()[i * image.width() + j] << std::endl; + } + } +} + int main() { gepard::PNGSurface surface(SURFACE_SIZE, SURFACE_SIZE); @@ -53,12 +65,15 @@ int main() generateCheckerBoard(gepard); gepard::Image image = gepard.createImageData(200.0, 200.0); + fillImage(image); std::cout << image.width() << " " << image.height() << std::endl; gepard::Image image2 = gepard.createImageData(image); std::cout << image2.width() << " " << image2.height() << std::endl; - gepard.putImageData(image, 20, 20); + gepard.putImageData(image, 100, 100, 10, 10, 50, 50); + + gepard.putImageData(image2, 0, 0); surface.save("image.png"); diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index c4b13491..08b80abd 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -547,7 +547,244 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F void GepardVulkan::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight) { - GD_LOG2("putImage " << dx << " " << dy << " " << dirtyWidth << " " << dirtyHeight); + GD_LOG2("putImage " << dx << " " << dy << " " << dirtyX << " " << dirtyY << " " << dirtyWidth << " " << dirtyHeight); + VkResult vkResult; + VkBuffer buffer; + VkDeviceMemory bufferAlloc; + const uint32_t width = imagedata.width(); + const uint32_t height = imagedata.height(); + + const VkDeviceSize dataSize = width * height * sizeof(uint32_t); // r8g8b8a8 format + // TODO: create function for buffer creation + const VkBufferCreateInfo bufferInfo = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + dataSize, // VkDeviceSize size; + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // uint32_t queueFamilyIndexCount; + &_queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; + }; + + vkResult = _vk.vkCreateBuffer(_device, &bufferInfo, _allocator, &buffer); + GD_ASSERT(vkResult == VK_SUCCESS && "Creating the buffer is failed!"); + VkMemoryRequirements bufferMemoryRequirements; + + _vk.vkGetBufferMemoryRequirements(_device, buffer, &bufferMemoryRequirements); + const VkMemoryAllocateInfo allocationInfo = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + bufferMemoryRequirements.size, // VkDeviceSize allocationSize; + getMemoryTypeIndex(bufferMemoryRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT), // uint32_t memoryTypeIndex; + }; + + _vk.vkAllocateMemory(_device, &allocationInfo, _allocator, &bufferAlloc); + _vk.vkBindBufferMemory(_device, buffer, bufferAlloc, 0); + + void* bufferPtr; + _vk.vkMapMemory(_device, bufferAlloc, 0, bufferMemoryRequirements.size, 0, &bufferPtr); + memcpy(bufferPtr, imagedata.data().data(), dataSize); + _vk.vkUnmapMemory(_device, bufferAlloc); + + VkImage image; + + // TODO: implement funiction for image creation + const VkExtent3D imageSize = { + width, // uint32_t width; + height, // uint32_t height; + 1u, // uint32_t depth; + }; + + const VkImageCreateInfo imageCreateInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0u, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + _imageFormat, // VkFormat format; + imageSize, // VkExtent3D extent; + 1u, // uint32_t mipLevels; + 1u, // uint32_t arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // uint32_t queueFamilyIndexCount; + &_queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + + vkResult = _vk.vkCreateImage(_device, &imageCreateInfo, _allocator, &image); + GD_ASSERT(vkResult == VK_SUCCESS && "Creating the image is failed!"); + + VkMemoryRequirements imageMemoryRequirements; + _vk.vkGetImageMemoryRequirements(_device, _surfaceImage, &imageMemoryRequirements); + + const VkMemoryAllocateInfo imageAllocateInfo = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + imageMemoryRequirements.size, // VkDeviceSize allocationSize; + getMemoryTypeIndex(imageMemoryRequirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT), // uint32_t memoryTypeIndex; + }; + VkDeviceMemory imageMemory; + vkResult = _vk.vkAllocateMemory(_device, &imageAllocateInfo, _allocator, &imageMemory); + GD_ASSERT(vkResult == VK_SUCCESS && "Memory allocation failed!"); + + vkResult = _vk.vkBindImageMemory(_device, image, imageMemory, static_cast(0u)); + GD_ASSERT(vkResult == VK_SUCCESS && "Memory bind failed!"); + + const VkCommandBuffer commandBuffer = _primaryCommandBuffers[0]; + const VkCommandBufferBeginInfo commandBufferBeginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags; + nullptr, // const VkCommandBufferInheritanceInfo* pInheritanceInfo; + }; + + VkImageSubresourceLayers subResourceLayers = { + VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask; + 0u, //uint32_t mipLevel; + 0u, //uint32_t baseArrayLayer; + 1u, //uint32_t layerCount; + }; + + VkBufferImageCopy bufferToImage = { + 0, // VkDeviceSize bufferOffset; + 0, // uint32_t bufferRowLength; + 0, // uint32_t bufferImageHeight; + subResourceLayers, // VkImageSubresourceLayers imageSubresource; + { 0, 0, 0 }, // VkOffset3D imageOffset; + { + imagedata.width(), + imagedata.height(), + 1u, + }, // VkExtent3D imageExtent; + }; + + const VkImageSubresourceRange subresourceRange = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; + 0u, // uint32_t baseMipLevel; + 1u, // uint32_t levelCount; + 0u, // uint32_t baseArrayLayer; + 1u, // uint32_t layerCount; + }; + + const VkImageMemoryBarrier srcImageBarrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + nullptr, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; + image, // VkImage image; + subresourceRange, // VkImageSubresourceRange subresourceRange; + }; + + const VkImageMemoryBarrier dstImageBarrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + nullptr, // const void* pNext; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; + _surfaceImage, // VkImage image; + subresourceRange, // VkImageSubresourceRange subresourceRange; + }; + + const VkImageMemoryBarrier postImageBarrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + nullptr, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; + _queueFamilyIndex, // uint32_t srcQueueFamilyIndex; + _queueFamilyIndex, // uint32_t dstQueueFamilyIndex; + _surfaceImage, // VkImage image; + subresourceRange, // VkImageSubresourceRange subresourceRange; + }; + + const VkImageMemoryBarrier imageBarriers[] = { srcImageBarrier, dstImageBarrier }; + + const VkOffset3D srcOffset = { + dirtyX, + dirtyY, + 0, + }; + const VkOffset3D dstOffset{ + dx, + dy, + 0, + }; + const VkExtent3D extent = { + dirtyWidth, + dirtyHeight, + 1, + }; + const VkImageCopy imageCopy = { + subResourceLayers, // VkImageSubresourceLayers srcSubresource; + srcOffset, // VkOffset3D srcOffset; + subResourceLayers, // VkImageSubresourceLayers dstSubresource; + dstOffset, // VkOffset3D dstOffset; + extent, // VkExtent3D extent; + }; + + _vk.vkBeginCommandBuffer(commandBuffer, &commandBufferBeginInfo); + + _vk.vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferToImage); + _vk.vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)nullptr, 0, (const VkBufferMemoryBarrier*)nullptr, 2, imageBarriers); + _vk.vkCmdCopyImage(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, _surfaceImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy); + _vk.vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)nullptr, 0, (const VkBufferMemoryBarrier*)nullptr, 1, &postImageBarrier); + + _vk.vkEndCommandBuffer(commandBuffer); + + const VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0u, // uint32_t waitSemaphoreCount; + nullptr, // const VkSemaphore* pWaitSemaphores; + nullptr, // const VkPipelineStageFlags* pWaitDstStageMask; + 1u, // uint32_t commandBufferCount; + &commandBuffer, // const VkCommandBuffer* pCommandBuffers; + 0u, // uint32_t signalSemaphoreCount; + nullptr, // const VkSemaphore* pSignalSemaphores; + }; + + VkQueue queue; + _vk.vkGetDeviceQueue(_device, _queueFamilyIndex, 0, &queue); + + const VkFenceCreateInfo fenceInfo = { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkFenceCreateFlags flags; + }; + + VkFence fence; + _vk.vkCreateFence(_device, &fenceInfo, _allocator, &fence); + vkResult = _vk.vkQueueSubmit(queue, 1, &submitInfo, fence); + GD_ASSERT(vkResult == VK_SUCCESS && "Queue submit failed!"); + + vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); + if (vkResult == VK_TIMEOUT) + GD_LOG1("TIMEOUT!"); + + if(_context.surface->getDisplay()) { + presentImage(); + } else if(_context.surface->getBuffer()) { + readImage(); + } + + // Clean up + _vk.vkFreeMemory(_device, imageMemory, _allocator); + _vk.vkFreeMemory(_device, bufferAlloc, _allocator); + _vk.vkDestroyFence(_device, fence, _allocator); + _vk.vkDestroyImage(_device, image, _allocator); + _vk.vkDestroyBuffer(_device, buffer, _allocator); } void GepardVulkan::fill() diff --git a/src/gepard-image.cpp b/src/gepard-image.cpp index 671fa8a4..e9789a02 100644 --- a/src/gepard-image.cpp +++ b/src/gepard-image.cpp @@ -63,7 +63,7 @@ const uint32_t Image::height() return _height; } -std::vector Image::data() +std::vector &Image::data() { return _data; } diff --git a/src/gepard-image.h b/src/gepard-image.h index 25301ddf..c404c560 100644 --- a/src/gepard-image.h +++ b/src/gepard-image.h @@ -41,7 +41,7 @@ class Image { const uint32_t width(); const uint32_t height(); - std::vector data(); + std::vector &data(); private: uint32_t _width; uint32_t _height; From c06b91747907990cceb9204a7b06b8cd5b92cb09 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Sun, 8 Jul 2018 20:29:57 +0200 Subject: [PATCH 08/20] Implement getImage function for the vulkan backend Signed-off-by: Kristof Kosztyo --- src/engines/vulkan/gepard-vulkan.cpp | 29 +++++++++++++++++++++------- src/engines/vulkan/gepard-vulkan.h | 4 +++- src/gepard-engine.cpp | 27 ++++++++++++++++++++++++++ src/gepard-engine.h | 2 ++ src/gepard.cpp | 18 ++++++++--------- 5 files changed, 63 insertions(+), 17 deletions(-) diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index 08b80abd..be304988 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -526,7 +526,7 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F if(_context.surface->getDisplay()) { presentImage(); } else if(_context.surface->getBuffer()) { - readImage(); + presentToMemoryBuffer(); } // Clean up @@ -776,7 +776,7 @@ void GepardVulkan::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, F if(_context.surface->getDisplay()) { presentImage(); } else if(_context.surface->getBuffer()) { - readImage(); + presentToMemoryBuffer(); } // Clean up @@ -787,6 +787,18 @@ void GepardVulkan::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, F _vk.vkDestroyBuffer(_device, buffer, _allocator); } +Image GepardVulkan::getImage(Float sx, Float sy, Float sw, Float sh) +{ + std::vector imageData; + int32_t x = sx; + int32_t y = sy; + uint32_t w = sw; + uint32_t h = sh; + imageData.resize(w * h); + readImage(imageData.data(), x, y, w, h); + return Image(w, h, imageData); +} + void GepardVulkan::fill() { GD_NOT_IMPLEMENTED(); @@ -1464,13 +1476,16 @@ void GepardVulkan::presentImage() _vk.vkDestroyFence(_device, fence, _allocator); } -void GepardVulkan::readImage() +void GepardVulkan::presentToMemoryBuffer() +{ + readImage((uint32_t*)_context.surface->getBuffer(), 0, 0, _context.surface->width(), _context.surface->height()); +} + +void GepardVulkan::readImage(uint32_t* memoryBuffer, int32_t x, int32_t y, uint32_t width, uint32_t height) { VkBuffer buffer; VkDeviceMemory bufferAlloc; const VkCommandBuffer commandBuffer = _primaryCommandBuffers[0]; - const uint32_t width = _context.surface->width(); - const uint32_t height = _context.surface->width(); const VkDeviceSize dataSize = width * height * 4; // r8g8b8a8 format // Create destination buffer @@ -1557,7 +1572,7 @@ void GepardVulkan::readImage() width, // uint32_t bufferRowLength; height, // uint32_t bufferImageHeight; imageSubresource, // VkImageSubresourceLayers imageSubresource; - { 0, 0, 0 }, // VkOffset3D imageOffset; + { x, y, 0 }, // VkOffset3D imageOffset; { width, height, @@ -1620,7 +1635,7 @@ void GepardVulkan::readImage() }; _vk.vkInvalidateMappedMemoryRanges(_device, 1, &range); - std::memcpy(_context.surface->getBuffer(), data, dataSize); + std::memcpy(memoryBuffer, data, dataSize); // Clean up _vk.vkUnmapMemory(_device, bufferAlloc); diff --git a/src/engines/vulkan/gepard-vulkan.h b/src/engines/vulkan/gepard-vulkan.h index a140cb54..035e2dae 100644 --- a/src/engines/vulkan/gepard-vulkan.h +++ b/src/engines/vulkan/gepard-vulkan.h @@ -52,6 +52,7 @@ class GepardVulkan { void fillRect(const Float x, const Float y, const Float w, const Float h); void putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight); + Image getImage(Float sx, Float sy, Float sw, Float sh); void fill(); void stroke(); @@ -90,7 +91,8 @@ class GepardVulkan { uint32_t getMemoryTypeIndex(const VkMemoryRequirements memoryRequirements, const VkMemoryPropertyFlags properties); void createSwapChain(); void presentImage(); - void readImage(); + void presentToMemoryBuffer(); + void readImage(uint32_t* memoryBuffer, int32_t x, int32_t y, uint32_t width, uint32_t height); }; } // namespace vulkan diff --git a/src/gepard-engine.cpp b/src/gepard-engine.cpp index 8938ac5d..621e61a1 100644 --- a/src/gepard-engine.cpp +++ b/src/gepard-engine.cpp @@ -272,6 +272,33 @@ void GepardEngine::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, F #endif // GD_USE_VULKAN } +void GepardEngine::drawImage(Image imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh) +{ + GD_ASSERT(_engineBackend); + GD_NOT_IMPLEMENTED(); +} + +/*! + * \brief GepardEngine::getImage + * \param sx Horizontal position on the _canvas_ + * \param sy Vertical position on the _canvas_ + * \param sw width of the rectangle to be copied + * \param sh height of the rectangle to be copied + * \return imageData + * + * Read back the canvas' data on the given rectangle. + */ +Image GepardEngine::getImage(Float sx, Float sy, Float sw, Float sh) +{ + GD_ASSERT(_engineBackend); +#ifdef GD_USE_VULKAN + return _engineBackend->getImage(sx, sy, sw, sh); +#else // !GD_USE_VULKAN + GD_NOT_IMPLEMENTED(); + return Image(); +#endif // GD_USE_VULKAN +} + void GepardEngine::setFillColor(const Color& color) { GD_LOG1("Set fill color (" << color.r << ", " << color.g << ", " << color.b << ", " << color.a << ")"); diff --git a/src/gepard-engine.h b/src/gepard-engine.h index 966fee30..08f56917 100644 --- a/src/gepard-engine.h +++ b/src/gepard-engine.h @@ -82,6 +82,8 @@ class GepardEngine { void fillRect(Float x, Float y, Float w, Float h); + void drawImage(Image imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh); + Image getImage(Float sx, Float sy, Float sw, Float sh); void putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight); void setFillColor(const Color& color); diff --git a/src/gepard.cpp b/src/gepard.cpp index cbdf97bd..c7cd380b 100644 --- a/src/gepard.cpp +++ b/src/gepard.cpp @@ -580,20 +580,22 @@ bool Gepard::isPointInPath(float x, float y) return false; } -void Gepard::drawImage(Image /*image*/, float dx, float dy) +void Gepard::drawImage(Image image, float dx, float dy) { -/*! \todo unimplemented function */ + float width = image.width(); + float height = image.height(); + _engine->drawImage(image, 0.0, 0.0, width, height, dx, dy, width, height); } -void Gepard::drawImage(Image /*image*/, float dx, float dy, float dw, float dh) +void Gepard::drawImage(Image image, float dx, float dy, float dw, float dh) { -/*! \todo unimplemented function */ + _engine->drawImage(image, 0.0, 0.0, image.width(), image.height(), dx, dy, dw, dh); } -void Gepard::drawImage(Image /*image*/, float sx, float sy, float sw, float sh, +void Gepard::drawImage(Image image, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh) { -/*! \todo unimplemented function */ + _engine->drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh); } Image Gepard::createImageData(float sw, float sh) @@ -613,9 +615,7 @@ Image Gepard::createImageData(Image imagedata) Image Gepard::getImageData(double sx, double sy, double sw, double sh) { -/*! \todo unimplemented function */ - GD_NOT_IMPLEMENTED(); - return Image(); + return _engine->getImage(sx, sy, sw, sh); } void Gepard::putImageData(Image imagedata, double dx, double dy) From 018beb87ec9a159b4ada0d8ddaac919763b6f008 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Mon, 9 Jul 2018 19:43:06 +0200 Subject: [PATCH 09/20] Add utility functions for the vulkan backend Signed-off-by: Kristof Kosztyo --- src/engines/vulkan/gepard-vulkan.cpp | 272 ++++++++++++--------------- src/engines/vulkan/gepard-vulkan.h | 5 + src/gepard-engine.cpp | 4 + src/gepard-image.cpp | 2 +- src/gepard-image.h | 2 +- 5 files changed, 130 insertions(+), 155 deletions(-) diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index be304988..39a17961 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -545,49 +545,33 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F _vk.vkFreeMemory(_device, indexBufferMemory, _allocator); } +void GepardVulkan::drawImage(Image imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh) +{ + GD_LOG2("drawImage " << sx << " " << sy << " " << sw << " " << sh << " " << dx << " " << dy << " " << dw << " " << dh); +} + void GepardVulkan::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight) { GD_LOG2("putImage " << dx << " " << dy << " " << dirtyX << " " << dirtyY << " " << dirtyWidth << " " << dirtyHeight); VkResult vkResult; - VkBuffer buffer; - VkDeviceMemory bufferAlloc; const uint32_t width = imagedata.width(); const uint32_t height = imagedata.height(); - const VkDeviceSize dataSize = width * height * sizeof(uint32_t); // r8g8b8a8 format - // TODO: create function for buffer creation - const VkBufferCreateInfo bufferInfo = { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0u, // VkBufferCreateFlags flags; - dataSize, // VkDeviceSize size; - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // uint32_t queueFamilyIndexCount; - &_queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; - }; - - vkResult = _vk.vkCreateBuffer(_device, &bufferInfo, _allocator, &buffer); - GD_ASSERT(vkResult == VK_SUCCESS && "Creating the buffer is failed!"); + VkBuffer buffer; + VkDeviceMemory bufferAlloc; VkMemoryRequirements bufferMemoryRequirements; + const VkDeviceSize bufferSize = width * height * sizeof(uint32_t); // r8g8b8a8 format - _vk.vkGetBufferMemoryRequirements(_device, buffer, &bufferMemoryRequirements); - const VkMemoryAllocateInfo allocationInfo = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - bufferMemoryRequirements.size, // VkDeviceSize allocationSize; - getMemoryTypeIndex(bufferMemoryRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT), // uint32_t memoryTypeIndex; - }; - - _vk.vkAllocateMemory(_device, &allocationInfo, _allocator, &bufferAlloc); - _vk.vkBindBufferMemory(_device, buffer, bufferAlloc, 0); + createBuffer(buffer, bufferAlloc, bufferMemoryRequirements, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); void* bufferPtr; _vk.vkMapMemory(_device, bufferAlloc, 0, bufferMemoryRequirements.size, 0, &bufferPtr); - memcpy(bufferPtr, imagedata.data().data(), dataSize); + memcpy(bufferPtr, imagedata.data().data(), bufferSize); _vk.vkUnmapMemory(_device, bufferAlloc); VkImage image; + VkDeviceMemory imageMemory; + VkMemoryRequirements imageMemoryRequirements; // TODO: implement funiction for image creation const VkExtent3D imageSize = { @@ -596,43 +580,7 @@ void GepardVulkan::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, F 1u, // uint32_t depth; }; - const VkImageCreateInfo imageCreateInfo = { - VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0u, // VkImageCreateFlags flags; - VK_IMAGE_TYPE_2D, // VkImageType imageType; - _imageFormat, // VkFormat format; - imageSize, // VkExtent3D extent; - 1u, // uint32_t mipLevels; - 1u, // uint32_t arrayLayers; - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; - VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; - VK_IMAGE_USAGE_TRANSFER_SRC_BIT - | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // uint32_t queueFamilyIndexCount; - &_queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; - }; - - vkResult = _vk.vkCreateImage(_device, &imageCreateInfo, _allocator, &image); - GD_ASSERT(vkResult == VK_SUCCESS && "Creating the image is failed!"); - - VkMemoryRequirements imageMemoryRequirements; - _vk.vkGetImageMemoryRequirements(_device, _surfaceImage, &imageMemoryRequirements); - - const VkMemoryAllocateInfo imageAllocateInfo = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - imageMemoryRequirements.size, // VkDeviceSize allocationSize; - getMemoryTypeIndex(imageMemoryRequirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT), // uint32_t memoryTypeIndex; - }; - VkDeviceMemory imageMemory; - vkResult = _vk.vkAllocateMemory(_device, &imageAllocateInfo, _allocator, &imageMemory); - GD_ASSERT(vkResult == VK_SUCCESS && "Memory allocation failed!"); - - vkResult = _vk.vkBindImageMemory(_device, image, imageMemory, static_cast(0u)); - GD_ASSERT(vkResult == VK_SUCCESS && "Memory bind failed!"); + createImage(image, imageMemory, imageMemoryRequirements, imageSize, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); const VkCommandBuffer commandBuffer = _primaryCommandBuffers[0]; const VkCommandBufferBeginInfo commandBufferBeginInfo = { @@ -1043,50 +991,14 @@ void GepardVulkan::createSurfaceImage() 1u, // uint32_t depth; }; - const VkImageCreateInfo imageCreateInfo = { - VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0u, // VkImageCreateFlags flags; - VK_IMAGE_TYPE_2D, // VkImageType imageType; - _imageFormat, // VkFormat format; - imageSize, // VkExtent3D extent; - 1u, // uint32_t mipLevels; - 1u, // uint32_t arrayLayers; - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; - VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; - VK_IMAGE_USAGE_TRANSFER_SRC_BIT - | VK_IMAGE_USAGE_TRANSFER_DST_BIT - | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // uint32_t queueFamilyIndexCount; - &_queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; - }; - - vkResult = _vk.vkCreateImage(_device, &imageCreateInfo, _allocator, &_surfaceImage); - GD_ASSERT(vkResult == VK_SUCCESS && "Creating the surface backing image failed!"); - - VkMemoryRequirements memoryRequirements; - _vk.vkGetImageMemoryRequirements(_device, _surfaceImage, &memoryRequirements); - - const VkMemoryAllocateInfo memoryAllocateInfo = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - memoryRequirements.size, // VkDeviceSize allocationSize; - getMemoryTypeIndex(memoryRequirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT), // uint32_t memoryTypeIndex; - }; - VkDeviceMemory deviceMemory; - vkResult = _vk.vkAllocateMemory(_device, &memoryAllocateInfo, _allocator, &deviceMemory); - GD_ASSERT(vkResult == VK_SUCCESS && "Memory allocation failed!"); + VkMemoryRequirements memoryRequirements; + VkImageUsageFlags usageFlag = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + createImage(_surfaceImage, deviceMemory, memoryRequirements, imageSize, usageFlag); _memoryAllocations.push_back(deviceMemory); - vkResult = _vk.vkBindImageMemory(_device, _surfaceImage, deviceMemory, static_cast(0u)); - GD_ASSERT(vkResult == VK_SUCCESS && "Memory bind failed!"); - // Clear the surface image - const VkCommandBuffer commandBuffer = _primaryCommandBuffers[0]; const VkCommandBufferBeginInfo commandBufferBeginInfo = { @@ -1148,31 +1060,7 @@ void GepardVulkan::createDefaultFrameBuffer() { VkResult vkResult; - const VkImageViewCreateInfo imageViewCreateInfo = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkImageViewCreateFlags flags; - _surfaceImage, // VkImage image; - VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; - _imageFormat, // VkFormat format; - { - VK_COMPONENT_SWIZZLE_IDENTITY, // swizzle r - VK_COMPONENT_SWIZZLE_IDENTITY, // swizzle g - VK_COMPONENT_SWIZZLE_IDENTITY, // swizzle b - VK_COMPONENT_SWIZZLE_IDENTITY, // swizzle a - }, // VkComponentMapping components; - { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; - 0u, // uint32_t baseMipLevel; - 1u, // uint32_t levelCount; - 0u, // uint32_t baseArrayLayer; - 1u, // uint32_t layerCount; - }, // VkImageSubresourceRange subresourceRange; - }; - - vkResult = _vk.vkCreateImageView(_device, &imageViewCreateInfo, _allocator, &_frameBufferColorAttachmentImageView); - GD_ASSERT(vkResult == VK_SUCCESS && "Creating the default frame buffer failed!"); - + createImageView(_frameBufferColorAttachmentImageView, _surfaceImage); std::vector attachments; attachments.push_back(_frameBufferColorAttachmentImageView); @@ -1485,34 +1373,12 @@ void GepardVulkan::readImage(uint32_t* memoryBuffer, int32_t x, int32_t y, uint3 { VkBuffer buffer; VkDeviceMemory bufferAlloc; + VkMemoryRequirements memoryRequirements; const VkCommandBuffer commandBuffer = _primaryCommandBuffers[0]; const VkDeviceSize dataSize = width * height * 4; // r8g8b8a8 format // Create destination buffer - const VkBufferCreateInfo bufferInfo = { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0u, // VkBufferCreateFlags flags; - dataSize, // VkDeviceSize size; - VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // uint32_t queueFamilyIndexCount; - &_queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; - }; - - _vk.vkCreateBuffer(_device, &bufferInfo, _allocator, &buffer); - - VkMemoryRequirements memoryRequirements; - _vk.vkGetBufferMemoryRequirements(_device, buffer, &memoryRequirements); - const VkMemoryAllocateInfo allocationInfo = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - memoryRequirements.size, // VkDeviceSize allocationSize; - getMemoryTypeIndex(memoryRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT), // uint32_t memoryTypeIndex; - }; - - _vk.vkAllocateMemory(_device, &allocationInfo, _allocator, &bufferAlloc); - _vk.vkBindBufferMemory(_device, buffer, bufferAlloc, 0); + createBuffer(buffer, bufferAlloc, memoryRequirements, dataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); const VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; @@ -1645,6 +1511,106 @@ void GepardVulkan::readImage(uint32_t* memoryBuffer, int32_t x, int32_t y, uint3 _vk.vkDestroyBuffer(_device, buffer, _allocator); } +void GepardVulkan::createBuffer(VkBuffer &buffer, VkDeviceMemory &bufferAlloc, VkMemoryRequirements &bufferRequirements, VkDeviceSize size, VkBufferUsageFlags usageFlag) +{ + VkResult vkResult; + const VkDeviceSize dataSize = size; + const VkBufferCreateInfo bufferInfo = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + dataSize, // VkDeviceSize size; + usageFlag, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // uint32_t queueFamilyIndexCount; + &_queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; + }; + + vkResult = _vk.vkCreateBuffer(_device, &bufferInfo, _allocator, &buffer); + GD_ASSERT(vkResult == VK_SUCCESS && "Creating the buffer is failed!"); + + _vk.vkGetBufferMemoryRequirements(_device, buffer, &bufferRequirements); + const VkMemoryAllocateInfo allocationInfo = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + bufferRequirements.size, // VkDeviceSize allocationSize; + getMemoryTypeIndex(bufferRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT), // uint32_t memoryTypeIndex; + }; + + _vk.vkAllocateMemory(_device, &allocationInfo, _allocator, &bufferAlloc); + _vk.vkBindBufferMemory(_device, buffer, bufferAlloc, 0); +} + +void GepardVulkan::createImage(VkImage &image, VkDeviceMemory &imageAlloc, VkMemoryRequirements &memReq, VkExtent3D imageSize, VkImageUsageFlags usageFlag) +{ + VkResult vkResult; + const VkImageCreateInfo imageCreateInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0u, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + _imageFormat, // VkFormat format; + imageSize, // VkExtent3D extent; + 1u, // uint32_t mipLevels; + 1u, // uint32_t arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + usageFlag, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // uint32_t queueFamilyIndexCount; + &_queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + + vkResult = _vk.vkCreateImage(_device, &imageCreateInfo, _allocator, &image); + GD_ASSERT(vkResult == VK_SUCCESS && "Creating the image is failed!"); + + _vk.vkGetImageMemoryRequirements(_device, _surfaceImage, &memReq); + + const VkMemoryAllocateInfo imageAllocateInfo = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + memReq.size, // VkDeviceSize allocationSize; + getMemoryTypeIndex(memReq, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT), // uint32_t memoryTypeIndex; + }; + + vkResult = _vk.vkAllocateMemory(_device, &imageAllocateInfo, _allocator, &imageAlloc); + GD_ASSERT(vkResult == VK_SUCCESS && "Memory allocation failed!"); + + vkResult = _vk.vkBindImageMemory(_device, image, imageAlloc, static_cast(0u)); + GD_ASSERT(vkResult == VK_SUCCESS && "Memory bind failed!"); +} + +void GepardVulkan::createImageView(VkImageView &imageView, VkImage image) +{ + VkResult vkResult; + + const VkImageViewCreateInfo imageViewCreateInfo = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkImageViewCreateFlags flags; + image, // VkImage image; + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; + _imageFormat, // VkFormat format; + { + VK_COMPONENT_SWIZZLE_IDENTITY, // swizzle r + VK_COMPONENT_SWIZZLE_IDENTITY, // swizzle g + VK_COMPONENT_SWIZZLE_IDENTITY, // swizzle b + VK_COMPONENT_SWIZZLE_IDENTITY, // swizzle a + }, // VkComponentMapping components; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; + 0u, // uint32_t baseMipLevel; + 1u, // uint32_t levelCount; + 0u, // uint32_t baseArrayLayer; + 1u, // uint32_t layerCount; + }, // VkImageSubresourceRange subresourceRange; + }; + + vkResult = _vk.vkCreateImageView(_device, &imageViewCreateInfo, _allocator, &imageView); + GD_ASSERT(vkResult == VK_SUCCESS && "Creating the image view failed!"); +} + } // namespace vulkan } // namespace gepard diff --git a/src/engines/vulkan/gepard-vulkan.h b/src/engines/vulkan/gepard-vulkan.h index 035e2dae..20ef044f 100644 --- a/src/engines/vulkan/gepard-vulkan.h +++ b/src/engines/vulkan/gepard-vulkan.h @@ -51,6 +51,7 @@ class GepardVulkan { ~GepardVulkan(); void fillRect(const Float x, const Float y, const Float w, const Float h); + void drawImage(Image imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh); void putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight); Image getImage(Float sx, Float sy, Float sw, Float sh); void fill(); @@ -93,6 +94,10 @@ class GepardVulkan { void presentImage(); void presentToMemoryBuffer(); void readImage(uint32_t* memoryBuffer, int32_t x, int32_t y, uint32_t width, uint32_t height); + + void createBuffer(VkBuffer& buffer, VkDeviceMemory& bufferAlloc, VkMemoryRequirements& bufferRequirements, VkDeviceSize size, VkBufferUsageFlags usageFlag); + void createImage(VkImage& image, VkDeviceMemory& imageAlloc, VkMemoryRequirements& memReq, VkExtent3D size, VkImageUsageFlags usageFlag); + void createImageView(VkImageView& imageView, VkImage image); }; } // namespace vulkan diff --git a/src/gepard-engine.cpp b/src/gepard-engine.cpp index 621e61a1..98fea850 100644 --- a/src/gepard-engine.cpp +++ b/src/gepard-engine.cpp @@ -275,7 +275,11 @@ void GepardEngine::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, F void GepardEngine::drawImage(Image imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh) { GD_ASSERT(_engineBackend); +#ifdef GD_USE_VULKAN + _engineBackend->drawImage(imagedata, sx, sy, sw, sh, dx, dy, dw, dh); +#else // !GD_USE_VULKAN GD_NOT_IMPLEMENTED(); +#endif // GD_USE_VULKAN } /*! diff --git a/src/gepard-image.cpp b/src/gepard-image.cpp index e9789a02..f41f6875 100644 --- a/src/gepard-image.cpp +++ b/src/gepard-image.cpp @@ -42,7 +42,7 @@ Image::Image(uint32_t width, uint32_t height) _data.resize(width * height); } -Image::Image(uint32_t width, uint32_t height, std::vector data) +Image::Image(uint32_t width, uint32_t height, const std::vector &data) : _width(width) , _height(height) , _data(data) diff --git a/src/gepard-image.h b/src/gepard-image.h index c404c560..346b691a 100644 --- a/src/gepard-image.h +++ b/src/gepard-image.h @@ -36,7 +36,7 @@ class Image { public: Image(); Image(uint32_t width, uint32_t height); - Image(uint32_t width, uint32_t height, std::vector data); + Image(uint32_t width, uint32_t height, const std::vector &data); virtual ~Image(); const uint32_t width(); From 2effe91e4a770189274ed2d64680417b7860d90b Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Sun, 15 Jul 2018 13:34:33 +0200 Subject: [PATCH 10/20] Implement drawimage for the vulkan backend Updated the shader generator. Implemented simple shader for images. Applied minor refactoring to the vulkan backend. Signed-off-by: Kristof Kosztyo --- apps/examples/image/image.cpp | 18 +- src/engines/vulkan/gepard-vulkan-interface.h | 12 +- src/engines/vulkan/gepard-vulkan.cpp | 812 +++++++++++++------ src/engines/vulkan/gepard-vulkan.h | 28 + tools/{scripts => }/build-vulkan-shaders.py | 2 +- 5 files changed, 609 insertions(+), 263 deletions(-) rename tools/{scripts => }/build-vulkan-shaders.py (98%) diff --git a/apps/examples/image/image.cpp b/apps/examples/image/image.cpp index c01c8928..11356c3d 100644 --- a/apps/examples/image/image.cpp +++ b/apps/examples/image/image.cpp @@ -50,9 +50,7 @@ void fillImage(gepard::Image& image) for (int i = 0; i < image.width(); i++) { for (int j = 0; j < image.height(); j++) { uint32_t color = 0x7f7f7f7f; - image.data()[i * image.width() + j] = color; - std::cout << image.data()[i * image.width() + j] << std::endl; } } } @@ -62,19 +60,29 @@ int main() gepard::PNGSurface surface(SURFACE_SIZE, SURFACE_SIZE); gepard::Gepard gepard(&surface); + generateCheckerBoard(gepard); gepard::Image image = gepard.createImageData(200.0, 200.0); fillImage(image); - std::cout << image.width() << " " << image.height() << std::endl; gepard::Image image2 = gepard.createImageData(image); - std::cout << image2.width() << " " << image2.height() << std::endl; - gepard.putImageData(image, 100, 100, 10, 10, 50, 50); + gepard.putImageData(image, 100, 400, 10, 10, 50, 50); gepard.putImageData(image2, 0, 0); + gepard.setFillColor(0.0f, 1.0f, 0.0f, 1.0f); + gepard.fillRect(400, 400, 10, 10); + gepard::Image greenImage = gepard.getImageData(400, 400, 10, 10); + gepard.setFillColor(1.0f, 0.0f, 0.0f, 1.0f); + gepard.fillRect(400, 400, 10, 10); + gepard.putImageData(greenImage, 405, 405); + + gepard::Image testImage = gepard.getImageData(380, 380, 50, 50); + gepard.setFillColor(1.0f, 0.0f, 0.0f, 1.0f); + gepard.drawImage(testImage, 200.0, 200.0, 100, 100); + surface.save("image.png"); return 0; diff --git a/src/engines/vulkan/gepard-vulkan-interface.h b/src/engines/vulkan/gepard-vulkan-interface.h index f7ba8a32..9324918f 100644 --- a/src/engines/vulkan/gepard-vulkan-interface.h +++ b/src/engines/vulkan/gepard-vulkan-interface.h @@ -122,7 +122,17 @@ namespace vulkan { FUNC(vkDestroySwapchainKHR); \ FUNC(vkGetSwapchainImagesKHR); \ FUNC(vkAcquireNextImageKHR); \ - FUNC(vkQueuePresentKHR); + FUNC(vkQueuePresentKHR); \ + FUNC(vkCreateDescriptorSetLayout); \ + FUNC(vkDestroyDescriptorSetLayout); \ + FUNC(vkCreateDescriptorPool); \ + FUNC(vkDestroyDescriptorPool); \ + FUNC(vkAllocateDescriptorSets); \ + FUNC(vkFreeDescriptorSets); \ + FUNC(vkCreateSampler); \ + FUNC(vkDestroySampler); \ + FUNC(vkUpdateDescriptorSets); \ + FUNC(vkCmdBindDescriptorSets); class GepardVulkanInterface { public: diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index 39a17961..41dfa8eb 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -145,147 +145,28 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F const uint32_t rectIndicies[] = {0, 1, 2, 2, 1, 3}; - const VkBufferCreateInfo vertexBufferInfo = { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkBufferCreateFlags flags; - (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // uint32_t queueFamilyIndexCount; - &_queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; - }; - VkBuffer vertexBuffer; VkDeviceMemory vertexBufferMemory; + VkMemoryRequirements vertexMemoryRequirements; VkDeviceSize vertexBufferOffset = 0; - _vk.vkCreateBuffer(_device, &vertexBufferInfo, _allocator, &vertexBuffer); - - // Upload vertex data. - { - VkMemoryRequirements memoryRequirements; - _vk.vkGetBufferMemoryRequirements(_device, vertexBuffer, &memoryRequirements); - const VkMemoryAllocateInfo allocationInfo = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - memoryRequirements.size, // VkDeviceSize allocationSize; - getMemoryTypeIndex(memoryRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT), // uint32_t memoryTypeIndex; - }; - - _vk.vkAllocateMemory(_device, &allocationInfo, _allocator, &vertexBufferMemory); - _vk.vkBindBufferMemory(_device, vertexBuffer, vertexBufferMemory, vertexBufferOffset); - - void* data; - _vk.vkMapMemory(_device, vertexBufferMemory, 0, (VkDeviceSize)sizeof(vertexData), 0, &data); - - std::memcpy(data, vertexData, (VkDeviceSize)sizeof(vertexData)); - - const VkMappedMemoryRange range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; - nullptr, // const void* pNext; - vertexBufferMemory, // VkDeviceMemory memory; - 0, // VkDeviceSize offset; - (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; - }; - - _vk.vkFlushMappedMemoryRanges(_device, 1, &range); - _vk.vkUnmapMemory(_device, vertexBufferMemory); - } + createBuffer(vertexBuffer, vertexBufferMemory, vertexMemoryRequirements, (VkDeviceSize)sizeof(vertexData), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + uploadToDeviceMemory(vertexBufferMemory, (void*)vertexData, vertexMemoryRequirements.size, vertexBufferOffset); VkBuffer indexBuffer; VkDeviceMemory indexBufferMemory; + VkMemoryRequirements indexMemoryRequirements; - // Upload index data. - { - const VkBufferCreateInfo indexBufferInfo = { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkBufferCreateFlags flags; - (VkDeviceSize)sizeof(rectIndicies), // VkDeviceSize size; - VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // uint32_t queueFamilyIndexCount; - &_queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; - }; - - _vk.vkCreateBuffer(_device, &indexBufferInfo, _allocator, &indexBuffer); - - VkMemoryRequirements memoryRequirements; - _vk.vkGetBufferMemoryRequirements(_device, indexBuffer, &memoryRequirements); - const VkMemoryAllocateInfo allocationInfo = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - memoryRequirements.size, // VkDeviceSize allocationSize; - getMemoryTypeIndex(memoryRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT), // uint32_t memoryTypeIndex; - }; - - _vk.vkAllocateMemory(_device, &allocationInfo, _allocator, &indexBufferMemory); - _vk.vkBindBufferMemory(_device, indexBuffer, indexBufferMemory, 0); - - void* data; - _vk.vkMapMemory(_device, indexBufferMemory, 0, (VkDeviceSize)sizeof(rectIndicies), 0, &data); - - std::memcpy(data, rectIndicies, (VkDeviceSize)sizeof(rectIndicies)); - - const VkMappedMemoryRange range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; - nullptr, // const void* pNext; - indexBufferMemory, // VkDeviceMemory memory; - 0, // VkDeviceSize offset; - (VkDeviceSize)sizeof(rectIndicies), // VkDeviceSize size; - }; - - _vk.vkFlushMappedMemoryRanges(_device, 1, &range); - _vk.vkUnmapMemory(_device, indexBufferMemory); - } + createBuffer(indexBuffer, indexBufferMemory, indexMemoryRequirements, (VkDeviceSize)sizeof(rectIndicies), VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + uploadToDeviceMemory(indexBufferMemory, (void*)rectIndicies, indexMemoryRequirements.size); // Pipeline creation VkShaderModule vertex; VkShaderModule fragment; - { - const VkShaderModuleCreateInfo vertexModulInfo = { - VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkShaderModuleCreateFlags flags; - sizeof(fillRectVert), // size_t codeSize; - fillRectVert, // const uint32_t* pCode; - }; - _vk.vkCreateShaderModule(_device, &vertexModulInfo, _allocator, &vertex); - - const VkShaderModuleCreateInfo fragmentModulInfo = { - VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkShaderModuleCreateFlags flags; - sizeof(fillRectFrag), // size_t codeSize; - fillRectFrag, // const uint32_t* pCode; - }; - - _vk.vkCreateShaderModule(_device, &fragmentModulInfo, _allocator, &fragment); - } - - const VkPipelineShaderStageCreateInfo stages[] = { - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkPipelineShaderStageCreateFlags flags; - VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; - vertex, // VkShaderModule module; - "main", // const char* pName; - nullptr, // const VkSpecializationInfo* pSpecializationInfo; - }, - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkPipelineShaderStageCreateFlags flags; - VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; - fragment, // VkShaderModule module; - "main", // const char* pName; - nullptr, // const VkSpecializationInfo* pSpecializationInfo; - } - }; + createShaderModule(vertex, fillRectVert, sizeof(fillRectVert)); + createShaderModule(fragment, fillRectFrag, sizeof(fillRectFrag)); const VkVertexInputBindingDescription bindingDescription = { 0u, // uint32_t binding; @@ -318,106 +199,9 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F vertexAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; }; - const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType - nullptr, // const void* pNext - 0, // VkPipelineInputAssemblyStateCreateFlags flags - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology - VK_FALSE, // VkBool32 primitiveRestartEnable - }; - - const uint32_t width = _context.surface->width(); - const uint32_t height = _context.surface->height(); - const VkViewport viewports[] = { - { - 0.0f, // float x; - 0.0f, // float y; - (float)width, // float width; - (float)height, // float height; - 0.0f, // float minDepth; - 1.0f, // float maxDepth; - } - }; - - const VkRect2D scissors[] = { - { - { - 0, // int32_t x - 0, // int32_t y - }, // VkOffset2D offset; - { - width, // uint32_t width - height, // uint32_t height - }, // VkExtent2D extent; - } - }; - - const VkPipelineViewportStateCreateInfo viewportState = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkPipelineViewportStateCreateFlags flags; - 1u, // uint32_t viewportCount; - viewports, // const VkViewport* pViewports; - 1u, // uint32_t scissorCount; - scissors, // const VkRect2D* pScissors; - }; - - const VkPipelineRasterizationStateCreateInfo rasterizationState = { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkPipelineRasterizationStateCreateFlags flags; - VK_FALSE, // VkBool32 depthClampEnable; - VK_FALSE, // VkBool32 rasterizerDiscardEnable; - VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; - VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; - VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; - VK_FALSE, // VkBool32 depthBiasEnable; - 0.0f, // float depthBiasConstantFactor; - 0.0f, // float depthBiasClamp; - 0.0f, // float depthBiasSlopeFactor; - 1.0f, // float lineWidth; - }; - - const VkPipelineMultisampleStateCreateInfo multisampleState = { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkPipelineMultisampleStateCreateFlags flags; - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; - VK_FALSE, // VkBool32 sampleShadingEnable; - 0.0, // float minSampleShading; - nullptr, // const VkSampleMask* pSampleMask; - VK_FALSE, // VkBool32 alphaToCoverageEnable; - VK_FALSE, // VkBool32 alphaToOneEnable; - }; - - const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = { - VK_TRUE, // VkBool32 blendEnable; - VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor; - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor; - VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; - VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor; - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstAlphaBlendFactor; - VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT // VkColorComponentFlags colorWriteMask; - }; - - const VkPipelineColorBlendStateCreateInfo colorBlendState = { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkPipelineColorBlendStateCreateFlags flags; - VK_FALSE, // VkBool32 logicOpEnable; - VK_LOGIC_OP_COPY, // VkLogicOp logicOp; - 1u, // uint32_t attachmentCount; - &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; - { - 0.0f, // float R - 0.0f, // float G - 0.0f, // float B - 0.0f, // float A - }, // float blendConstants[4]; - }; - VkPipelineLayout layout; + VkPipeline pipeline; + const VkPipelineLayoutCreateInfo layoutCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType nullptr, // const void *pNext @@ -427,37 +211,9 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F 0u, // uint32_t pushConstantRangeCount nullptr // const VkPushConstantRange *pPushConstantRanges }; - - _vk.vkCreatePipelineLayout(_device, &layoutCreateInfo, _allocator, &layout); - - const VkGraphicsPipelineCreateInfo pipelineCreateInfo = { - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkPipelineCreateFlags flags; - 2u, // uint32_t stageCount; - stages, // const VkPipelineShaderStageCreateInfo* pStages; - &vertexInputState, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; - &inputAssemblyState, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; - nullptr, // const VkPipelineTessellationStateCreateInfo* pTessellationState; - &viewportState, // const VkPipelineViewportStateCreateInfo* pViewportState; - &rasterizationState, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; - &multisampleState, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; - nullptr, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; - &colorBlendState, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; - nullptr, // const VkPipelineDynamicStateCreateInfo* pDynamicState; - layout, // VkPipelineLayout layout; - _renderPass, // VkRenderPass renderPass; - 0u, // uint32_t subpass; - VK_NULL_HANDLE, // VkPipeline basePipelineHandle; - 0, // int32_t basePipelineIndex; - }; - - VkPipeline pipeline; - - _vk.vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, _allocator, &pipeline); + createSimplePipeline(pipeline, layout, vertex, fragment, vertexInputState, blendMode::oneMinusSrcAlpha, layoutCreateInfo); // Drawing - const VkCommandBuffer commandBuffer = _primaryCommandBuffers[0]; const VkCommandBufferBeginInfo commandBufferBeginInfo = { @@ -476,7 +232,7 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F nullptr, // const void* pNext; _renderPass, // VkRenderPass renderPass; _frameBuffer, // VkFramebuffer framebuffer; - scissors[0], // VkRect2D renderArea; + getDefaultRenderArea(), // VkRect2D renderArea; 1u, // uint32_t clearValueCount; &clearValue, // const VkClearValue* pClearValues; }; @@ -548,6 +304,331 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F void GepardVulkan::drawImage(Image imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh) { GD_LOG2("drawImage " << sx << " " << sy << " " << sw << " " << sh << " " << dx << " " << dy << " " << dw << " " << dh); + VkResult vkResult; + const uint32_t width = imagedata.width(); + const uint32_t height = imagedata.height(); + VkBuffer buffer; + VkDeviceMemory bufferAlloc; + VkMemoryRequirements bufferMemoryRequirements; + const VkDeviceSize bufferSize = width * height * sizeof(uint32_t); // r8g8b8a8 format + createBuffer(buffer, bufferAlloc, bufferMemoryRequirements, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + uploadToDeviceMemory(bufferAlloc, imagedata.data().data(), bufferSize); + + VkImage image; + VkImageView imageView; + VkDeviceMemory imageMemory; + VkMemoryRequirements imageMemoryRequirements; + + const VkExtent3D imageSize = { + width, // uint32_t width; + height, // uint32_t height; + 1u, // uint32_t depth; + }; + + createImage(image, imageMemory, imageMemoryRequirements, imageSize, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + createImageView(imageView, image); + + // Vertex data setup + + const float texLeft = static_cast(sx / imagedata.width()); + const float texRight = static_cast((sx + sw) / imagedata.width()); + const float texTop = static_cast(sy / imagedata.height()); + const float texBottom = static_cast((sy + sh) / imagedata.height()); + // TODO: create utility function for this + const float left = static_cast((2.0 * dx / _context.surface->width()) - 1.0); + const float right = static_cast((2.0 * (dx + dw) / _context.surface->width()) - 1.0); + const float top = static_cast((2.0 * dy / _context.surface->height()) - 1.0); + const float bottom = static_cast((2.0 * (dy + dh) / _context.surface->height()) - 1.0); + + const float vertexData[] = { + left, top, texLeft, texTop, + right, top, texRight, texTop, + left, bottom, texLeft, texBottom, + right, bottom, texRight, texBottom, + }; + + const uint32_t rectIndicies[] = {0, 1, 2, 2, 1, 3}; + + VkBuffer vertexBuffer; + VkDeviceMemory vertexBufferMemory; + VkMemoryRequirements vertexMemoryRequirements; + VkDeviceSize vertexBufferOffset = 0; + + createBuffer(vertexBuffer, vertexBufferMemory, vertexMemoryRequirements, (VkDeviceSize)sizeof(vertexData), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + uploadToDeviceMemory(vertexBufferMemory, (void*)vertexData, vertexMemoryRequirements.size, vertexBufferOffset); + + VkBuffer indexBuffer; + VkDeviceMemory indexBufferMemory; + VkMemoryRequirements indexMemoryRequirements; + + createBuffer(indexBuffer, indexBufferMemory, indexMemoryRequirements, (VkDeviceSize)sizeof(rectIndicies), VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + uploadToDeviceMemory(indexBufferMemory, rectIndicies, indexMemoryRequirements.size); + + // Pipeline creation + // TODO: use proper descriptors + + VkShaderModule vertex; + VkShaderModule fragment; + + createShaderModule(vertex, imageVert, sizeof(imageVert)); + createShaderModule(fragment, imageFrag, sizeof(imageFrag)); + + const VkVertexInputBindingDescription bindingDescription = { + 0u, // uint32_t binding; + 2 * (2 * sizeof(float)), // uint32_t stride; + VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; + }; + + const VkVertexInputAttributeDescription vertexAttributeDescriptions[] = { + { + 0u, // uint32_t location + 0u, // uint32_t binding + VK_FORMAT_R32G32_SFLOAT, // VkFormat format + 0u, // uint32_t offset + }, + { + 1u, // uint32_t location + 0u, // uint32_t binding + VK_FORMAT_R32G32_SFLOAT, // VkFormat format + sizeof(float) * 2, // uint32_t offset + }, + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputState = { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkPipelineVertexInputStateCreateFlags flags; + 1u, // uint32_t vertexBindingDescriptionCount; + &bindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + 2u, // uint32_t vertexAttributeDescriptionCount; + vertexAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + VkPipelineLayout layout; + VkPipeline pipeline; + VkDescriptorPool descriptorPool; + VkDescriptorSetLayout descriptorSetLayout; + VkDescriptorSet descriptorSet; + VkSampler sampler; + + const VkSamplerCreateInfo samplerInfo = { + VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkSamplerCreateFlags flags; + VK_FILTER_LINEAR, // VkFilter magFilter; + VK_FILTER_LINEAR, // VkFilter minFilter; + VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode; + VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeU; + VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeV; + VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeW; + 0.0f, // float mipLodBias; + VK_FALSE, // VkBool32 anisotropyEnable; + 16.0f, // float maxAnisotropy; + VK_FALSE, // VkBool32 compareEnable; + VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp; + 0.0f, // float minLod; + 0.0f, // float maxLod; + VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, // VkBorderColor borderColor; + VK_FALSE, // VkBool32 unnormalizedCoordinates; + }; + _vk.vkCreateSampler(_device, &samplerInfo, _allocator, &sampler); + + const VkDescriptorPoolSize descriptorPoolSize = { + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType type; + 1u, // uint32_t descriptorCount; + }; + + const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags flags; + 1u, // uint32_t maxSets; + 1u, // uint32_t poolSizeCount; + &descriptorPoolSize, // const VkDescriptorPoolSize* pPoolSizes; + }; + + // TODO: this might be moved to gepard instance level instead of function level + _vk.vkCreateDescriptorPool(_device, &descriptorPoolCreateInfo, _allocator, &descriptorPool); + + const VkDescriptorSetLayoutBinding descriptoSetrLayoutBinding = { + 0u, // uint32_t binding; + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType; + 1u, // uint32_t descriptorCount; + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags; + nullptr, // const VkSampler* pImmutableSamplers; + }; + + const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkDescriptorSetLayoutCreateFlags flags; + 1u, // uint32_t bindingCount; + &descriptoSetrLayoutBinding, // const VkDescriptorSetLayoutBinding* pBindings; + }; + + _vk.vkCreateDescriptorSetLayout(_device, &descriptorSetLayoutCreateInfo, _allocator, &descriptorSetLayout); + + const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + descriptorPool, // VkDescriptorPool descriptorPool; + 1u, // uint32_t descriptorSetCount; + &descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts; + }; + + _vk.vkAllocateDescriptorSets(_device, &descriptorSetAllocateInfo, &descriptorSet); + + const VkDescriptorImageInfo descriptorImageInfo = { + sampler, // VkSampler sampler; + imageView, // VkImageView imageView; + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout imageLayout; + }; + + const VkWriteDescriptorSet writeDescriptorSet = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType; + nullptr, // const void* pNext; + descriptorSet, // VkDescriptorSet dstSet; + 0u, // uint32_t dstBinding; + 0u, // uint32_t dstArrayElement; + 1u, // uint32_t descriptorCount; + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // VkDescriptorType descriptorType; + &descriptorImageInfo, // const VkDescriptorImageInfo* pImageInfo; + nullptr, // const VkDescriptorBufferInfo* pBufferInfo; + nullptr, // const VkBufferView* pTexelBufferView; + }; + + _vk.vkUpdateDescriptorSets(_device, 1u, &writeDescriptorSet, 0u, nullptr); + + const VkPipelineLayoutCreateInfo layoutCreateInfo = { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType + nullptr, // const void *pNext + 0, // VkPipelineLayoutCreateFlags flags + 1u, // uint32_t setLayoutCount + &descriptorSetLayout, // const VkDescriptorSetLayout *pSetLayouts + 0u, // uint32_t pushConstantRangeCount + nullptr // const VkPushConstantRange *pPushConstantRanges + }; + createSimplePipeline(pipeline, layout, vertex, fragment, vertexInputState, blendMode::oneMinusSrcAlpha, layoutCreateInfo); + + const VkCommandBuffer commandBuffer = _primaryCommandBuffers[0]; + const VkCommandBufferBeginInfo commandBufferBeginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags; + nullptr, // const VkCommandBufferInheritanceInfo* pInheritanceInfo; + }; + + VkImageSubresourceLayers subResourceLayers = { + VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask; + 0u, //uint32_t mipLevel; + 0u, //uint32_t baseArrayLayer; + 1u, //uint32_t layerCount; + }; + + VkBufferImageCopy bufferToImage = { + 0, // VkDeviceSize bufferOffset; + 0, // uint32_t bufferRowLength; + 0, // uint32_t bufferImageHeight; + subResourceLayers, // VkImageSubresourceLayers imageSubresource; + { 0, 0, 0 }, // VkOffset3D imageOffset; + { + imagedata.width(), + imagedata.height(), + 1u, + }, // VkExtent3D imageExtent; + }; + + const VkImageSubresourceRange subresourceRange = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; + 0u, // uint32_t baseMipLevel; + 1u, // uint32_t levelCount; + 0u, // uint32_t baseArrayLayer; + 1u, // uint32_t layerCount; + }; + + const VkImageMemoryBarrier uploadImageBarrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkAccessFlags srcAccessMask; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; + image, // VkImage image; + subresourceRange, // VkImageSubresourceRange subresourceRange; + }; + + const VkImageMemoryBarrier sampleImageBarrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + nullptr, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask; + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; + image, // VkImage image; + subresourceRange, // VkImageSubresourceRange subresourceRange; + }; + + _vk.vkBeginCommandBuffer(commandBuffer, &commandBufferBeginInfo); + + const VkClearValue clearValue = { 0.0, 0.0, 0.0, 0.0 }; + + const VkRenderPassBeginInfo renderPassInfo = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + _renderPass, // VkRenderPass renderPass; + _frameBuffer, // VkFramebuffer framebuffer; + getDefaultRenderArea(), // VkRect2D renderArea; + 1u, // uint32_t clearValueCount; + &clearValue, // const VkClearValue* pClearValues; + }; + + // TODO: check if we need preCopy barrier + _vk.vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)nullptr, 0, (const VkBufferMemoryBarrier*)nullptr, 1, &uploadImageBarrier); + _vk.vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferToImage); + _vk.vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)nullptr, 0, (const VkBufferMemoryBarrier*)nullptr, 1, &sampleImageBarrier); + + _vk.vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + _vk.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + + _vk.vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset); + _vk.vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT32); + + _vk.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0u, 1u, &descriptorSet, 0u, nullptr); + + const uint32_t indexCount = sizeof(rectIndicies) / sizeof(uint32_t); + _vk.vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0); + + _vk.vkCmdEndRenderPass(commandBuffer); + + _vk.vkEndCommandBuffer(commandBuffer); + + submitAndWait(commandBuffer); + updateSurface(); + + // Clean up + _vk.vkFreeDescriptorSets(_device, descriptorPool, 1u, &descriptorSet); + _vk.vkDestroySampler(_device, sampler, _allocator); + + _vk.vkDestroyDescriptorSetLayout(_device, descriptorSetLayout, _allocator); + _vk.vkDestroyDescriptorPool(_device, descriptorPool, _allocator); + + _vk.vkDestroyPipeline(_device, pipeline, _allocator); + _vk.vkDestroyPipelineLayout(_device, layout, _allocator); + + _vk.vkDestroyShaderModule(_device, vertex, _allocator); + _vk.vkDestroyShaderModule(_device, fragment, _allocator); + + _vk.vkDestroyImageView(_device, imageView, _allocator); + + _vk.vkFreeMemory(_device, imageMemory, _allocator); + _vk.vkFreeMemory(_device, bufferAlloc, _allocator); + + _vk.vkDestroyImage(_device, image, _allocator); + _vk.vkDestroyBuffer(_device, buffer, _allocator); } void GepardVulkan::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight) @@ -618,6 +699,7 @@ void GepardVulkan::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, F 1u, // uint32_t layerCount; }; + // TODO: check the barriers! const VkImageMemoryBarrier srcImageBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; nullptr, // const void* pNext; @@ -1611,6 +1693,224 @@ void GepardVulkan::createImageView(VkImageView &imageView, VkImage image) GD_ASSERT(vkResult == VK_SUCCESS && "Creating the image view failed!"); } +void GepardVulkan::createShaderModule(VkShaderModule &shader, const uint32_t *code, const size_t codeSize) +{ + const VkShaderModuleCreateInfo shaderModulInfo = { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkShaderModuleCreateFlags flags; + codeSize, // size_t codeSize; + code, // const uint32_t* pCode; + }; + + _vk.vkCreateShaderModule(_device, &shaderModulInfo, _allocator, &shader); +} + +void GepardVulkan::uploadToDeviceMemory(VkDeviceMemory buffer, const void *data, VkDeviceSize size, VkDeviceSize offset) +{ + void* rawPointer; + _vk.vkMapMemory(_device, buffer, offset, size, 0, &rawPointer); + + std::memcpy(rawPointer, data, size); + + const VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + nullptr, // const void* pNext; + buffer, // VkDeviceMemory memory; + offset, // VkDeviceSize offset; + size, // VkDeviceSize size; + }; + + _vk.vkFlushMappedMemoryRanges(_device, 1, &range); + _vk.vkUnmapMemory(_device, buffer); +} + +void GepardVulkan::createSimplePipeline(VkPipeline &pipeline, VkPipelineLayout &layout, const VkShaderModule vertex, const VkShaderModule fragment, const VkPipelineVertexInputStateCreateInfo vertexInputState, const VkPipelineColorBlendAttachmentState blendState, const VkPipelineLayoutCreateInfo layoutInfo) +{ + // Simple two stage pipeline + const VkPipelineShaderStageCreateInfo stages[] = { + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; + vertex, // VkShaderModule module; + "main", // const char* pName; + nullptr, // const VkSpecializationInfo* pSpecializationInfo; + }, + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; + fragment, // VkShaderModule module; + "main", // const char* pName; + nullptr, // const VkSpecializationInfo* pSpecializationInfo; + } + }; + + const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0, // VkPipelineInputAssemblyStateCreateFlags flags + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology + VK_FALSE, // VkBool32 primitiveRestartEnable + }; + + const VkViewport viewport = getDefaultViewPort(); + const VkRect2D scissor = getDefaultRenderArea(); + + const VkPipelineViewportStateCreateInfo viewportState = { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkPipelineViewportStateCreateFlags flags; + 1u, // uint32_t viewportCount; + &viewport, // const VkViewport* pViewports; + 1u, // uint32_t scissorCount; + &scissor, // const VkRect2D* pScissors; + }; + + const VkPipelineRasterizationStateCreateInfo rasterizationState = { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkPipelineRasterizationStateCreateFlags flags; + VK_FALSE, // VkBool32 depthClampEnable; + VK_FALSE, // VkBool32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; + VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBiasConstantFactor; + 0.0f, // float depthBiasClamp; + 0.0f, // float depthBiasSlopeFactor; + 1.0f, // float lineWidth; + }; + + const VkPipelineMultisampleStateCreateInfo multisampleState = { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkPipelineMultisampleStateCreateFlags flags; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; + VK_FALSE, // VkBool32 sampleShadingEnable; + 0.0, // float minSampleShading; + nullptr, // const VkSampleMask* pSampleMask; + VK_FALSE, // VkBool32 alphaToCoverageEnable; + VK_FALSE, // VkBool32 alphaToOneEnable; + }; + + const VkPipelineColorBlendStateCreateInfo colorBlendState = { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkPipelineColorBlendStateCreateFlags flags; + VK_FALSE, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // uint32_t attachmentCount; + &blendState, // const VkPipelineColorBlendAttachmentState* pAttachments; + { + 0.0f, // float R + 0.0f, // float G + 0.0f, // float B + 0.0f, // float A + }, // float blendConstants[4]; + }; + _vk.vkCreatePipelineLayout(_device, &layoutInfo, _allocator, &layout); + + const VkGraphicsPipelineCreateInfo pipelineCreateInfo = { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkPipelineCreateFlags flags; + 2u, // uint32_t stageCount; + stages, // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputState, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &inputAssemblyState, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + nullptr, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &viewportState, // const VkPipelineViewportStateCreateInfo* pViewportState; + &rasterizationState, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + &multisampleState, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + nullptr, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &colorBlendState, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + nullptr, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + layout, // VkPipelineLayout layout; + _renderPass, // VkRenderPass renderPass; + 0u, // uint32_t subpass; + VK_NULL_HANDLE, // VkPipeline basePipelineHandle; + 0, // int32_t basePipelineIndex; + }; + + _vk.vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, _allocator, &pipeline); +} + +VkRect2D GepardVulkan::getDefaultRenderArea() +{ + VkRect2D renderArea = { + { + 0, // int32_t x + 0, // int32_t y + }, // VkOffset2D offset; + { + _context.surface->width(), // uint32_t width + _context.surface->height(), // uint32_t height + }, // VkExtent2D extent; + }; + return renderArea; +} + +VkViewport GepardVulkan::getDefaultViewPort() +{ + VkViewport viewPort = { + 0.0f, // float x; + 0.0f, // float y; + (float)_context.surface->width(), // float width; + (float)_context.surface->height(), // float height; + 0.0f, // float minDepth; + 1.0f, // float maxDepth; + }; + return viewPort; +} + +void GepardVulkan::submitAndWait(const VkCommandBuffer commandBuffer) +{ + VkResult vkResult; + + const VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0u, // uint32_t waitSemaphoreCount; + nullptr, // const VkSemaphore* pWaitSemaphores; + nullptr, // const VkPipelineStageFlags* pWaitDstStageMask; + 1u, // uint32_t commandBufferCount; + &commandBuffer, // const VkCommandBuffer* pCommandBuffers; + 0u, // uint32_t signalSemaphoreCount; + nullptr, // const VkSemaphore* pSignalSemaphores; + }; + + VkQueue queue; + _vk.vkGetDeviceQueue(_device, _queueFamilyIndex, 0, &queue); + + const VkFenceCreateInfo fenceInfo = { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkFenceCreateFlags flags; + }; + + VkFence fence; + _vk.vkCreateFence(_device, &fenceInfo, _allocator, &fence); + _vk.vkQueueSubmit(queue, 1, &submitInfo, fence); + vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); + if (vkResult == VK_TIMEOUT) + GD_LOG1("TIMEOUT!"); + _vk.vkDestroyFence(_device, fence, _allocator); +} + +void GepardVulkan::updateSurface() +{ + if(_context.surface->getDisplay()) { + presentImage(); + } else if(_context.surface->getBuffer()) { + presentToMemoryBuffer(); + } +} + } // namespace vulkan } // namespace gepard diff --git a/src/engines/vulkan/gepard-vulkan.h b/src/engines/vulkan/gepard-vulkan.h index 20ef044f..6b1fd01f 100644 --- a/src/engines/vulkan/gepard-vulkan.h +++ b/src/engines/vulkan/gepard-vulkan.h @@ -98,8 +98,36 @@ class GepardVulkan { void createBuffer(VkBuffer& buffer, VkDeviceMemory& bufferAlloc, VkMemoryRequirements& bufferRequirements, VkDeviceSize size, VkBufferUsageFlags usageFlag); void createImage(VkImage& image, VkDeviceMemory& imageAlloc, VkMemoryRequirements& memReq, VkExtent3D size, VkImageUsageFlags usageFlag); void createImageView(VkImageView& imageView, VkImage image); + void createShaderModule(VkShaderModule& shader, const uint32_t* code, const size_t codeSize); + + void uploadToDeviceMemory(VkDeviceMemory buffer, const void* data, VkDeviceSize size, VkDeviceSize offset = 0); + void createSimplePipeline(VkPipeline& pipeline, VkPipelineLayout& layout, + const VkShaderModule vertex, const VkShaderModule fragment, + const VkPipelineVertexInputStateCreateInfo vertexInputState, + const VkPipelineColorBlendAttachmentState blendState, + const VkPipelineLayoutCreateInfo layoutInfo); + + VkRect2D getDefaultRenderArea(); + VkViewport getDefaultViewPort(); + + void submitAndWait(const VkCommandBuffer commandBuffer); + void updateSurface(); }; +// TODO: create a header for these constants +namespace blendMode { + const VkPipelineColorBlendAttachmentState oneMinusSrcAlpha = { + VK_TRUE, // VkBool32 blendEnable; + VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor; + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; + VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor; + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstAlphaBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT // VkColorComponentFlags colorWriteMask; + }; +} // namespace blendMode + } // namespace vulkan typedef vulkan::GepardVulkan GepardEngineBackend; diff --git a/tools/scripts/build-vulkan-shaders.py b/tools/build-vulkan-shaders.py similarity index 98% rename from tools/scripts/build-vulkan-shaders.py rename to tools/build-vulkan-shaders.py index 53dd5323..87052895 100644 --- a/tools/scripts/build-vulkan-shaders.py +++ b/tools/build-vulkan-shaders.py @@ -32,7 +32,7 @@ import util glslang_path = os.path.join(util.get_base_path(), 'thirdparty', 'glslang') -glslang_path_build = os.path.join(glslang_path, 'build') +glslang_path_build = os.path.join(glslang_path, 'build', 'vulkan') glslang_git_url = 'https://github.com/KhronosGroup/glslang.git' shader_source_directory = os.path.join(util.get_base_path(), 'src', 'engines', 'vulkan', 'shaders') From 957bd744d5e928989a4025df1f255d9442b9bcd7 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Fri, 7 Sep 2018 08:46:42 +0200 Subject: [PATCH 11/20] Add the shaders for the drawimage function Signed-off-by: Kristof Kosztyo --- src/engines/vulkan/shaders/image.frag | 11 +++++++++++ src/engines/vulkan/shaders/image.vert | 12 ++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/engines/vulkan/shaders/image.frag create mode 100644 src/engines/vulkan/shaders/image.vert diff --git a/src/engines/vulkan/shaders/image.frag b/src/engines/vulkan/shaders/image.frag new file mode 100644 index 00000000..20c63c0f --- /dev/null +++ b/src/engines/vulkan/shaders/image.frag @@ -0,0 +1,11 @@ +# version 450 + +layout(location = 0) in vec2 fragTexCoord; +layout(set = 0, binding = 0) uniform sampler2D texSampler; + +layout(location = 0) out vec4 uFragColor; + +void main() +{ + uFragColor = texture(texSampler, fragTexCoord); +} diff --git a/src/engines/vulkan/shaders/image.vert b/src/engines/vulkan/shaders/image.vert new file mode 100644 index 00000000..638eee1a --- /dev/null +++ b/src/engines/vulkan/shaders/image.vert @@ -0,0 +1,12 @@ +# version 450 + +layout(location = 0) in vec2 position; +layout(location = 1) in vec2 texcoord; + +layout(location = 0) out vec2 fragTexCoord; + +void main() +{ + gl_Position = vec4(position.x, position.y, 1.0, 1.0); + fragTexCoord = texcoord; +} From 36c6eb57be55f1ec2d5317d14041956afa6112ab Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Wed, 26 Sep 2018 23:08:45 +0200 Subject: [PATCH 12/20] Add some TODO based on the GeCo18 --- src/gepard-image.h | 2 ++ src/gepard.h | 2 +- tools/build-vulkan-shaders.py | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gepard-image.h b/src/gepard-image.h index 346b691a..350981c3 100644 --- a/src/gepard-image.h +++ b/src/gepard-image.h @@ -41,7 +41,9 @@ class Image { const uint32_t width(); const uint32_t height(); + // TODO: check array implementation std::vector &data(); + private: uint32_t _width; uint32_t _height; diff --git a/src/gepard.h b/src/gepard.h index 3e503020..e86966a4 100644 --- a/src/gepard.h +++ b/src/gepard.h @@ -402,7 +402,7 @@ class Gepard { * \endcond */ /// \{ - +// TODO use reference! void drawImage(Image image, float dx, float dy); void drawImage(Image image, float dx, float dy, float dw, float dh); void drawImage(Image image, float sx, float sy, float sw, float sh, diff --git a/tools/build-vulkan-shaders.py b/tools/build-vulkan-shaders.py index 87052895..c2e36b3e 100644 --- a/tools/build-vulkan-shaders.py +++ b/tools/build-vulkan-shaders.py @@ -117,6 +117,7 @@ def create_binary_data(shader, length): spirv_file = open(get_spirv_path(shader), 'rb') for i in range(length): word = (ord(spirv_file.read(1))) + (ord(spirv_file.read(1)) << 8) + (ord(spirv_file.read(1)) << 16) + (ord(spirv_file.read(1)) << 24) + # TODO: write hexa instead of decimals binary_data += ' {0},\n'.format(word) spirv_file.close() binary_data += '}' From d0f22a6663584a02a03ced16d9a8057956ce9651 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Wed, 26 Sep 2018 23:30:55 +0200 Subject: [PATCH 13/20] Adapt the image example to the API change Signed-off-by: Kristof Kosztyo --- apps/examples/image/image.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/examples/image/image.cpp b/apps/examples/image/image.cpp index 11356c3d..86fc5d67 100644 --- a/apps/examples/image/image.cpp +++ b/apps/examples/image/image.cpp @@ -36,9 +36,9 @@ void generateCheckerBoard(gepard::Gepard& gepard) for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if ((i+j) % 2) { - gepard.setFillColor(0.3f, 0.3f, 0.3f, 1.0f); + gepard.setFillColor(77, 77, 77, 1.0f); } else { - gepard.setFillColor(0.8f, 0.8f, 0.8f, 1.0f); + gepard.setFillColor(204, 204, 204, 1.0f); } gepard.fillRect(i * cellWidth, j * cellWidth, cellWidth, cellWidth); } @@ -47,8 +47,8 @@ void generateCheckerBoard(gepard::Gepard& gepard) void fillImage(gepard::Image& image) { - for (int i = 0; i < image.width(); i++) { - for (int j = 0; j < image.height(); j++) { + for (uint32_t i = 0; i < image.width(); i++) { + for (uint32_t j = 0; j < image.height(); j++) { uint32_t color = 0x7f7f7f7f; image.data()[i * image.width() + j] = color; } @@ -72,15 +72,15 @@ int main() gepard.putImageData(image2, 0, 0); - gepard.setFillColor(0.0f, 1.0f, 0.0f, 1.0f); + gepard.setFillColor(0, 255, 0, 1.0f); gepard.fillRect(400, 400, 10, 10); gepard::Image greenImage = gepard.getImageData(400, 400, 10, 10); - gepard.setFillColor(1.0f, 0.0f, 0.0f, 1.0f); + gepard.setFillColor(255, 0, 0, 1.0f); gepard.fillRect(400, 400, 10, 10); gepard.putImageData(greenImage, 405, 405); gepard::Image testImage = gepard.getImageData(380, 380, 50, 50); - gepard.setFillColor(1.0f, 0.0f, 0.0f, 1.0f); + gepard.setFillColor(255, 0, 0, 1.0f); gepard.drawImage(testImage, 200.0, 200.0, 100, 100); surface.save("image.png"); From 661c4c1ec3925627c8f75912b91bc18be70f6c2e Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Sat, 29 Sep 2018 16:17:17 +0200 Subject: [PATCH 14/20] Compile the vulkan shaders at build-time Signed-off-by: Kristof Kosztyo --- cmake/Dependencies.cmake | 9 +++++++++ src/CMakeLists.txt | 5 ++++- src/engines/vulkan/gepard-vulkan.cpp | 2 ++ tools/build-vulkan-shaders.py | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index d30950cd..7de60269 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -27,6 +27,15 @@ elseif (BACKEND STREQUAL "VULKAN") set(VULKAN_INCLUDE_DIR ${PROJECT_BINARY_DIR}/thirdparty/include) endif() + add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/gepard-vulkan-spirv-binaries.h + ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/gepard-vulkan-spirv-binaries.inc.h + COMMAND python ${PROJECT_SOURCE_DIR}/tools/build-vulkan-shaders.py + DEPENDS ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/*.vert + ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/*.frag) + + add_custom_target(vulkan_shaders + DEPENDS ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/gepard-vulkan-spirv-binaries.h + ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/gepard-vulkan-spirv-binaries.inc.h) # TODO(kkristof) remove this once XSync has been removed from GepardVulkan::createSwapChain find_package(X11) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c41ded10..112c0ff6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,7 +21,6 @@ set(GLES2_SOURCES set(VULKAN_SOURCES engines/vulkan/gepard-vulkan-interface.cpp engines/vulkan/gepard-vulkan.cpp - engines/vulkan/shaders/gepard-vulkan-spirv-binaries.cpp ) set(SOFTWARE_SOURCES @@ -57,6 +56,10 @@ if (BACKEND STREQUAL "VULKAN" AND NOT VULKAN_FOUND) add_dependencies(gepard vulkan_headers) endif() +if (BACKEND STREQUAL "VULKAN") + add_dependencies(gepard vulkan_shaders) +endif() + target_compile_definitions(gepard PUBLIC "GD_USE_${BACKEND}") target_include_directories(gepard PUBLIC ${COMMON_INCLUDE_DIRS}) diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index 41dfa8eb..d3b5cf09 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -42,6 +42,8 @@ #include #endif // VK_USE_PLATFORM_XCB_KHR +#include "gepard-vulkan-spirv-binaries.inc.h" + namespace gepard { namespace vulkan { diff --git a/tools/build-vulkan-shaders.py b/tools/build-vulkan-shaders.py index c2e36b3e..931b5e3c 100644 --- a/tools/build-vulkan-shaders.py +++ b/tools/build-vulkan-shaders.py @@ -130,7 +130,7 @@ def prepare_c_source(shaders): return source def write_c_source(source): - source_path = os.path.join(shader_source_directory, c_file_name+'.cpp') + source_path = os.path.join(shader_source_directory, c_file_name+'.inc.h') source_file = open(source_path, 'w') source_file.write(generated_warning) source_file.write(c_header) From c02ba4e6fc49915f73c046f6e9553ef0116f9a46 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Sat, 29 Sep 2018 16:46:18 +0200 Subject: [PATCH 15/20] Use hexa output in the generated SPIR-V header Signed-off-by: Kristof Kosztyo --- tools/build-vulkan-shaders.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/build-vulkan-shaders.py b/tools/build-vulkan-shaders.py index 931b5e3c..3a64c1c4 100644 --- a/tools/build-vulkan-shaders.py +++ b/tools/build-vulkan-shaders.py @@ -117,8 +117,7 @@ def create_binary_data(shader, length): spirv_file = open(get_spirv_path(shader), 'rb') for i in range(length): word = (ord(spirv_file.read(1))) + (ord(spirv_file.read(1)) << 8) + (ord(spirv_file.read(1)) << 16) + (ord(spirv_file.read(1)) << 24) - # TODO: write hexa instead of decimals - binary_data += ' {0},\n'.format(word) + binary_data += ' 0x{0:x},\n'.format(word) spirv_file.close() binary_data += '}' return binary_data From 420decb00aea01571b8bf5546bc41bfb1bbfb7c6 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Sat, 29 Sep 2018 18:24:01 +0200 Subject: [PATCH 16/20] Use image references Signed-off-by: Kristof Kosztyo --- src/engines/vulkan/gepard-vulkan.cpp | 4 ++-- src/engines/vulkan/gepard-vulkan.h | 4 ++-- src/gepard-engine.cpp | 4 ++-- src/gepard-engine.h | 4 ++-- src/gepard.cpp | 12 ++++++------ src/gepard.h | 13 ++++++------- 6 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index d3b5cf09..211764fe 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -303,7 +303,7 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F _vk.vkFreeMemory(_device, indexBufferMemory, _allocator); } -void GepardVulkan::drawImage(Image imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh) +void GepardVulkan::drawImage(Image& imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh) { GD_LOG2("drawImage " << sx << " " << sy << " " << sw << " " << sh << " " << dx << " " << dy << " " << dw << " " << dh); VkResult vkResult; @@ -633,7 +633,7 @@ void GepardVulkan::drawImage(Image imagedata, Float sx, Float sy, Float sw, Floa _vk.vkDestroyBuffer(_device, buffer, _allocator); } -void GepardVulkan::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight) +void GepardVulkan::putImage(Image& imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight) { GD_LOG2("putImage " << dx << " " << dy << " " << dirtyX << " " << dirtyY << " " << dirtyWidth << " " << dirtyHeight); VkResult vkResult; diff --git a/src/engines/vulkan/gepard-vulkan.h b/src/engines/vulkan/gepard-vulkan.h index 6b1fd01f..b07987cc 100644 --- a/src/engines/vulkan/gepard-vulkan.h +++ b/src/engines/vulkan/gepard-vulkan.h @@ -51,8 +51,8 @@ class GepardVulkan { ~GepardVulkan(); void fillRect(const Float x, const Float y, const Float w, const Float h); - void drawImage(Image imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh); - void putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight); + void drawImage(Image& imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh); + void putImage(Image& imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight); Image getImage(Float sx, Float sy, Float sw, Float sh); void fill(); void stroke(); diff --git a/src/gepard-engine.cpp b/src/gepard-engine.cpp index ea3456d3..16f766a8 100644 --- a/src/gepard-engine.cpp +++ b/src/gepard-engine.cpp @@ -317,7 +317,7 @@ void GepardEngine::fillRect(Float x, Float y, Float w, Float h) * * Copy the imageData into the canvas. */ -void GepardEngine::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight) +void GepardEngine::putImage(Image& imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight) { GD_ASSERT(_engineBackend); #ifdef GD_USE_VULKAN @@ -327,7 +327,7 @@ void GepardEngine::putImage(Image imagedata, Float dx, Float dy, Float dirtyX, F #endif // GD_USE_VULKAN } -void GepardEngine::drawImage(Image imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh) +void GepardEngine::drawImage(Image& imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh) { GD_ASSERT(_engineBackend); #ifdef GD_USE_VULKAN diff --git a/src/gepard-engine.h b/src/gepard-engine.h index 605a0783..38963d27 100644 --- a/src/gepard-engine.h +++ b/src/gepard-engine.h @@ -93,9 +93,9 @@ class GepardEngine { void fillRect(Float x, Float y, Float w, Float h); - void drawImage(Image imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh); + void drawImage(Image& imagedata, Float sx, Float sy, Float sw, Float sh, Float dx, Float dy, Float dw, Float dh); Image getImage(Float sx, Float sy, Float sw, Float sh); - void putImage(Image imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight); + void putImage(Image& imagedata, Float dx, Float dy, Float dirtyX, Float dirtyY, Float dirtyWidth, Float dirtyHeight); void setFillColor(const Color& color); void setFillColor(const Float red, const Float green, const Float blue, const Float alpha = 1.0f); diff --git a/src/gepard.cpp b/src/gepard.cpp index 85120469..bd730586 100644 --- a/src/gepard.cpp +++ b/src/gepard.cpp @@ -587,19 +587,19 @@ bool Gepard::isPointInPath(float x, float y) return false; } -void Gepard::drawImage(Image image, float dx, float dy) +void Gepard::drawImage(Image& image, float dx, float dy) { float width = image.width(); float height = image.height(); _engine->drawImage(image, 0.0, 0.0, width, height, dx, dy, width, height); } -void Gepard::drawImage(Image image, float dx, float dy, float dw, float dh) +void Gepard::drawImage(Image& image, float dx, float dy, float dw, float dh) { _engine->drawImage(image, 0.0, 0.0, image.width(), image.height(), dx, dy, dw, dh); } -void Gepard::drawImage(Image image, float sx, float sy, float sw, float sh, +void Gepard::drawImage(Image& image, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh) { _engine->drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh); @@ -613,7 +613,7 @@ Image Gepard::createImageData(float sw, float sh) return Image(width, height); } -Image Gepard::createImageData(Image imagedata) +Image Gepard::createImageData(Image& imagedata) { uint32_t width = imagedata.width(); uint32_t height = imagedata.height(); @@ -625,12 +625,12 @@ Image Gepard::getImageData(double sx, double sy, double sw, double sh) return _engine->getImage(sx, sy, sw, sh); } -void Gepard::putImageData(Image imagedata, double dx, double dy) +void Gepard::putImageData(Image& imagedata, double dx, double dy) { _engine->putImage(imagedata, dx, dy, 0.0, 0.0, imagedata.width(), imagedata.height()); } -void Gepard::putImageData(Image imagedata, double dx, double dy, double dirtyX, double dirtyY, +void Gepard::putImageData(Image& imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight) { _engine->putImage(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight); diff --git a/src/gepard.h b/src/gepard.h index a64a8afd..c87613ad 100644 --- a/src/gepard.h +++ b/src/gepard.h @@ -402,10 +402,9 @@ class Gepard { * \endcond */ /// \{ -// TODO use reference! - void drawImage(Image image, float dx, float dy); - void drawImage(Image image, float dx, float dy, float dw, float dh); - void drawImage(Image image, float sx, float sy, float sw, float sh, + void drawImage(Image& image, float dx, float dy); + void drawImage(Image& image, float dx, float dy, float dw, float dh); + void drawImage(Image& image, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); /// \} 12. CanvasAPI Drawing images @@ -418,10 +417,10 @@ class Gepard { /// \{ Image createImageData(float sw, float sh); - Image createImageData(Image imagedata); + Image createImageData(Image& imagedata); Image getImageData(double sx, double sy, double sw, double sh); - void putImageData(Image imagedata, double dx, double dy); - void putImageData(Image imagedata, double dx, double dy, double dirtyX, double dirtyY, + void putImageData(Image& imagedata, double dx, double dy); + void putImageData(Image& imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight); /// \} 14. CanvasAPI Pixel manipulation From c6a567a0a47c89164838ffdeec5830d38d193703 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Wed, 3 Oct 2018 20:52:14 +0200 Subject: [PATCH 17/20] Add glslang to the thirdparties Signed-off-by: Kristof Kosztyo --- thirdparty/CMakeLists.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 28495823..458f6fb1 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -22,7 +22,8 @@ set(INCLUDE_OUTPUT_DIR ${PROJECT_SOURCE_DIR}/include) # - A subdirectory in PROJECT_BINARY_DIR can be used as a build directory. add_custom_target(common ALL - DEPENDS gtest) + DEPENDS gtest + glslang) add_custom_target(gles2 ALL DEPENDS common) @@ -44,6 +45,15 @@ ExternalProject_Add(gtest BUILD_COMMAND make gtest INSTALL_COMMAND make install > /dev/null) +ExternalProject_Add(glslang + PREFIX ${PROJECT_SOURCE_DIR}/src/glslang + GIT_REPOSITORY https://github.com/KhronosGroup/glslang.git + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PROJECT_SOURCE_DIR} -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_INSTALL_INCLUDEDIR=include + GIT_TAG master-tot + BINARY_DIR ${PROJECT_BINARY_DIR}/glslang + BUILD_COMMAND make glslangValidator + INSTALL_COMMAND make install > /dev/null) + file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/stamps) add_custom_command(TARGET gles2 POST_BUILD From a8e85cad22a3b924ea7fed586498727a16e62e5e Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Wed, 3 Oct 2018 21:48:18 +0200 Subject: [PATCH 18/20] Rework the SPIR-V handling for the vulkan backend Signed-off-by: Kristof Kosztyo --- cmake/Dependencies.cmake | 13 +++---- src/CMakeLists.txt | 3 +- src/engines/vulkan/gepard-vulkan.cpp | 18 ++++++++-- src/engines/vulkan/gepard-vulkan.h | 1 - .../vulkan/shaders/VulkanShaders.cmake | 35 +++++++++++++++++++ 5 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 src/engines/vulkan/shaders/VulkanShaders.cmake diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index 7de60269..7b742f72 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -27,15 +27,10 @@ elseif (BACKEND STREQUAL "VULKAN") set(VULKAN_INCLUDE_DIR ${PROJECT_BINARY_DIR}/thirdparty/include) endif() - add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/gepard-vulkan-spirv-binaries.h - ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/gepard-vulkan-spirv-binaries.inc.h - COMMAND python ${PROJECT_SOURCE_DIR}/tools/build-vulkan-shaders.py - DEPENDS ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/*.vert - ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/*.frag) - - add_custom_target(vulkan_shaders - DEPENDS ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/gepard-vulkan-spirv-binaries.h - ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders/gepard-vulkan-spirv-binaries.inc.h) + + find_program(GLSLANG_VALIDATOR + NAMES glslangValidator + HINTS ${PROJECT_SOURCE_DIR}/thirdparty/bin) # TODO(kkristof) remove this once XSync has been removed from GepardVulkan::createSwapChain find_package(X11) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 09e8a8a2..9a00b717 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,7 +45,7 @@ set(GLES2_INCLUDE_DIRS set(VULKAN_INCLUDE_DIRS engines/vulkan - engines/vulkan/shaders + ${PROJECT_BINARY_DIR}/spirv ) set(SOFTWARE_INCLUDE_DIRS @@ -73,6 +73,7 @@ if (BACKEND STREQUAL "VULKAN" AND NOT VULKAN_FOUND) endif() if (BACKEND STREQUAL "VULKAN") + include(engines/vulkan/shaders/VulkanShaders.cmake) add_dependencies(gepard vulkan_shaders) endif() diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index 9e9a8a28..92ec3804 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -42,11 +42,25 @@ #include #endif // VK_USE_PLATFORM_XCB_KHR -#include "gepard-vulkan-spirv-binaries.inc.h" - namespace gepard { namespace vulkan { +static const uint32_t fillRectVert[] = { +#include "fill-rect.vert.inc" +}; + +static const uint32_t fillRectFrag[] = { +#include "fill-rect.frag.inc" +}; + +static const uint32_t imageVert[] = { +#include "image.vert.inc" +}; + +static const uint32_t imageFrag[] = { +#include "image.frag.inc" +}; + static const uint64_t oneMiliSec = 1000000; static const uint64_t timeout = (uint64_t)32 * oneMiliSec; // 32 ms #ifdef VK_USE_PLATFORM_XCB_KHR diff --git a/src/engines/vulkan/gepard-vulkan.h b/src/engines/vulkan/gepard-vulkan.h index 9d9beeb7..af5cd847 100644 --- a/src/engines/vulkan/gepard-vulkan.h +++ b/src/engines/vulkan/gepard-vulkan.h @@ -34,7 +34,6 @@ #include "gepard-float.h" #include "gepard-image.h" #include "gepard-vulkan-interface.h" -#include "gepard-vulkan-spirv-binaries.h" #include "gepard.h" #include diff --git a/src/engines/vulkan/shaders/VulkanShaders.cmake b/src/engines/vulkan/shaders/VulkanShaders.cmake new file mode 100644 index 00000000..713b65c9 --- /dev/null +++ b/src/engines/vulkan/shaders/VulkanShaders.cmake @@ -0,0 +1,35 @@ +set(VK_SHADER_DIRECTORY ${PROJECT_SOURCE_DIR}/src/engines/vulkan/shaders) +set(SPIRV_DIRECTORY ${PROJECT_BINARY_DIR}/spirv) +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/spirv) + +add_custom_target( + vulkan_shaders + DEPENDS ${SPIRV_DIRECTORY}/fill-rect.vert.inc + ${SPIRV_DIRECTORY}/fill-rect.frag.inc + ${SPIRV_DIRECTORY}/image.vert.inc + ${SPIRV_DIRECTORY}/image.frag.inc +) + +add_custom_command( + OUTPUT ${SPIRV_DIRECTORY}/fill-rect.vert.inc + COMMAND ${GLSLANG_VALIDATOR} -V -x -o ${SPIRV_DIRECTORY}/fill-rect.vert.inc ${VK_SHADER_DIRECTORY}/fill-rect.vert + DEPENDS ${VK_SHADER_DIRECTORY}/fill-rect.vert ${GLSLANG_VALIDATOR} +) + +add_custom_command( + OUTPUT ${SPIRV_DIRECTORY}/fill-rect.frag.inc + COMMAND ${GLSLANG_VALIDATOR} -V -x -o ${SPIRV_DIRECTORY}/fill-rect.frag.inc ${VK_SHADER_DIRECTORY}/fill-rect.frag + DEPENDS ${VK_SHADER_DIRECTORY}/fill-rect.frag ${GLSLANG_VALIDATOR} +) + +add_custom_command( + OUTPUT ${SPIRV_DIRECTORY}/image.vert.inc + COMMAND ${GLSLANG_VALIDATOR} -V -x -o ${SPIRV_DIRECTORY}/image.vert.inc ${VK_SHADER_DIRECTORY}/image.vert + DEPENDS ${VK_SHADER_DIRECTORY}/image.vert ${GLSLANG_VALIDATOR} +) + +add_custom_command( + OUTPUT ${SPIRV_DIRECTORY}/image.frag.inc + COMMAND ${GLSLANG_VALIDATOR} -V -x -o ${SPIRV_DIRECTORY}/image.frag.inc ${VK_SHADER_DIRECTORY}/image.frag + DEPENDS ${VK_SHADER_DIRECTORY}/image.frag ${GLSLANG_VALIDATOR} +) From 9ff8d42a5111189c6272dd1785359863bf290da3 Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Wed, 3 Oct 2018 23:50:13 +0200 Subject: [PATCH 19/20] Review fixes Signed-off-by: Kristof Kosztyo --- apps/examples/image/image.cpp | 1 - src/engines/vulkan/gepard-vulkan.cpp | 48 +++++++++++++--------------- src/engines/vulkan/gepard-vulkan.h | 9 ++++-- src/gepard-image.cpp | 2 -- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/apps/examples/image/image.cpp b/apps/examples/image/image.cpp index 86fc5d67..a92f3343 100644 --- a/apps/examples/image/image.cpp +++ b/apps/examples/image/image.cpp @@ -60,7 +60,6 @@ int main() gepard::PNGSurface surface(SURFACE_SIZE, SURFACE_SIZE); gepard::Gepard gepard(&surface); - generateCheckerBoard(gepard); gepard::Image image = gepard.createImageData(200.0, 200.0); diff --git a/src/engines/vulkan/gepard-vulkan.cpp b/src/engines/vulkan/gepard-vulkan.cpp index 92ec3804..d48a380a 100644 --- a/src/engines/vulkan/gepard-vulkan.cpp +++ b/src/engines/vulkan/gepard-vulkan.cpp @@ -63,13 +63,10 @@ static const uint32_t imageFrag[] = { static const uint64_t oneMiliSec = 1000000; static const uint64_t timeout = (uint64_t)32 * oneMiliSec; // 32 ms -#ifdef VK_USE_PLATFORM_XCB_KHR -static xcb_connection_t* xcbConnection; -#endif GepardVulkan::GepardVulkan(GepardContext& context) : _context(context) - , _vk("libvulkan.so.1") + , _vk("libvulkan.so") , _allocator(nullptr) , _instance(0) , _imageFormat(VK_FORMAT_R8G8B8A8_UNORM) @@ -292,15 +289,12 @@ void GepardVulkan::fillRect(const Float x, const Float y, const Float w, const F _vk.vkCreateFence(_device, &fenceInfo, _allocator, &fence); _vk.vkQueueSubmit(queue, 1, &submitInfo, fence); vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); - if (vkResult == VK_TIMEOUT) + if (vkResult == VK_TIMEOUT) { GD_LOG1("TIMEOUT!"); - - if(_context.surface->getDisplay()) { - presentImage(); - } else if(_context.surface->getBuffer()) { - presentToMemoryBuffer(); } + updateSurface(); + // Clean up _vk.vkDestroyFence(_device, fence, _allocator); @@ -762,7 +756,7 @@ void GepardVulkan::putImage(Image& imagedata, Float dx, Float dy, Float dirtyX, dirtyY, 0, }; - const VkOffset3D dstOffset{ + const VkOffset3D dstOffset = { dx, dy, 0, @@ -816,15 +810,12 @@ void GepardVulkan::putImage(Image& imagedata, Float dx, Float dy, Float dirtyX, GD_ASSERT(vkResult == VK_SUCCESS && "Queue submit failed!"); vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); - if (vkResult == VK_TIMEOUT) + if (vkResult == VK_TIMEOUT) { GD_LOG1("TIMEOUT!"); - - if(_context.surface->getDisplay()) { - presentImage(); - } else if(_context.surface->getBuffer()) { - presentToMemoryBuffer(); } + updateSurface(); + // Clean up _vk.vkFreeMemory(_device, imageMemory, _allocator); _vk.vkFreeMemory(_device, bufferAlloc, _allocator); @@ -1149,8 +1140,10 @@ void GepardVulkan::createSurfaceImage() _vk.vkCreateFence(_device, &fenceInfo, _allocator, &fence); _vk.vkQueueSubmit(queue, 1, &submitInfo, fence); vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); - if (vkResult == VK_TIMEOUT) + if (vkResult == VK_TIMEOUT) { GD_LOG1("TIMEOUT!"); + } + _vk.vkDestroyFence(_device, fence, _allocator); } @@ -1210,13 +1203,13 @@ void GepardVulkan::createSwapChain() #elif defined(VK_USE_PLATFORM_XCB_KHR) XSync((Display*)_context.surface->getDisplay(), false); - xcbConnection = XGetXCBConnection((Display*)_context.surface->getDisplay()); + _xcbConnection = XGetXCBConnection((Display*)_context.surface->getDisplay()); const VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = { VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType; nullptr, // const void* pNext; 0, // VkXlibSurfaceCreateFlagsKHR flags; - xcbConnection, // xcb_connection_t* connection; + _xcbConnection, // xcb_connection_t* connection; (xcb_window_t)_context.surface->getWindow(), // xcb_window_t window; }; @@ -1442,8 +1435,9 @@ void GepardVulkan::presentImage() VkResult vkResult; _vk.vkQueueSubmit(queue, 1, &submitInfo, fence); vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); - if (vkResult == VK_TIMEOUT) + if (vkResult == VK_TIMEOUT) { GD_LOG1("TIMEOUT!"); + } const VkPresentInfoKHR presentInfo = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType; @@ -1584,8 +1578,9 @@ void GepardVulkan::readImage(uint32_t* memoryBuffer, int32_t x, int32_t y, uint3 _vk.vkCreateFence(_device, &fenceInfo, _allocator, &fence); _vk.vkQueueSubmit(queque, 1, &submitInfo, fence); vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); - if (vkResult == VK_TIMEOUT) + if (vkResult == VK_TIMEOUT) { GD_LOG1("TIMEOUT!"); + } void* data; _vk.vkMapMemory(_device, bufferAlloc, 0, dataSize, 0, &data); @@ -1612,12 +1607,11 @@ void GepardVulkan::readImage(uint32_t* memoryBuffer, int32_t x, int32_t y, uint3 void GepardVulkan::createBuffer(VkBuffer &buffer, VkDeviceMemory &bufferAlloc, VkMemoryRequirements &bufferRequirements, VkDeviceSize size, VkBufferUsageFlags usageFlag) { VkResult vkResult; - const VkDeviceSize dataSize = size; const VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; nullptr, // const void* pNext; 0u, // VkBufferCreateFlags flags; - dataSize, // VkDeviceSize size; + size, // VkDeviceSize size; usageFlag, // VkBufferUsageFlags usage; VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1u, // uint32_t queueFamilyIndexCount; @@ -1873,7 +1867,7 @@ VkRect2D GepardVulkan::getDefaultRenderArea() VkViewport GepardVulkan::getDefaultViewPort() { - VkViewport viewPort = { + VkViewport viewPort = { 0.0f, // float x; 0.0f, // float y; (float)_context.surface->width(), // float width; @@ -1913,8 +1907,10 @@ void GepardVulkan::submitAndWait(const VkCommandBuffer commandBuffer) _vk.vkCreateFence(_device, &fenceInfo, _allocator, &fence); _vk.vkQueueSubmit(queue, 1, &submitInfo, fence); vkResult = _vk.vkWaitForFences(_device, 1, &fence, VK_TRUE, timeout); - if (vkResult == VK_TIMEOUT) + if (vkResult == VK_TIMEOUT) { GD_LOG1("TIMEOUT!"); + } + _vk.vkDestroyFence(_device, fence, _allocator); } diff --git a/src/engines/vulkan/gepard-vulkan.h b/src/engines/vulkan/gepard-vulkan.h index af5cd847..a19b0cfd 100644 --- a/src/engines/vulkan/gepard-vulkan.h +++ b/src/engines/vulkan/gepard-vulkan.h @@ -79,6 +79,9 @@ class GepardVulkan { VkSurfaceKHR _wsiSurface; VkSwapchainKHR _wsiSwapChain; std::vector _wsiSwapChainImages; +#ifdef VK_USE_PLATFORM_XCB_KHR + xcb_connection_t* _xcbConnection; +#endif void createDefaultInstance(); void chooseDefaultPhysicalDevice(); @@ -101,8 +104,10 @@ class GepardVulkan { void createShaderModule(VkShaderModule& shader, const uint32_t* code, const size_t codeSize); void uploadToDeviceMemory(VkDeviceMemory buffer, const void* data, VkDeviceSize size, VkDeviceSize offset = 0); - void createSimplePipeline(VkPipeline& pipeline, VkPipelineLayout& layout, - const VkShaderModule vertex, const VkShaderModule fragment, + void createSimplePipeline(VkPipeline& pipeline, + VkPipelineLayout& layout, + const VkShaderModule vertex, + const VkShaderModule fragment, const VkPipelineVertexInputStateCreateInfo vertexInputState, const VkPipelineColorBlendAttachmentState blendState, const VkPipelineLayoutCreateInfo layoutInfo); diff --git a/src/gepard-image.cpp b/src/gepard-image.cpp index f41f6875..360260df 100644 --- a/src/gepard-image.cpp +++ b/src/gepard-image.cpp @@ -25,8 +25,6 @@ #include "gepard-image.h" -#include - namespace gepard { Image::Image() From f0f5bf90483a314e865cb6aa01e943d71fa3bf6f Mon Sep 17 00:00:00 2001 From: Kristof Kosztyo Date: Thu, 4 Oct 2018 00:03:56 +0200 Subject: [PATCH 20/20] Review fixes for the build system --- {src/engines/vulkan/shaders => cmake}/VulkanShaders.cmake | 0 src/CMakeLists.txt | 2 +- thirdparty/CMakeLists.txt | 6 +++--- 3 files changed, 4 insertions(+), 4 deletions(-) rename {src/engines/vulkan/shaders => cmake}/VulkanShaders.cmake (100%) diff --git a/src/engines/vulkan/shaders/VulkanShaders.cmake b/cmake/VulkanShaders.cmake similarity index 100% rename from src/engines/vulkan/shaders/VulkanShaders.cmake rename to cmake/VulkanShaders.cmake diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9a00b717..f805d974 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -73,7 +73,7 @@ if (BACKEND STREQUAL "VULKAN" AND NOT VULKAN_FOUND) endif() if (BACKEND STREQUAL "VULKAN") - include(engines/vulkan/shaders/VulkanShaders.cmake) + include(VulkanShaders) add_dependencies(gepard vulkan_shaders) endif() diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 458f6fb1..21902196 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -22,14 +22,14 @@ set(INCLUDE_OUTPUT_DIR ${PROJECT_SOURCE_DIR}/include) # - A subdirectory in PROJECT_BINARY_DIR can be used as a build directory. add_custom_target(common ALL - DEPENDS gtest - glslang) + DEPENDS gtest) add_custom_target(gles2 ALL DEPENDS common) add_custom_target(vulkan ALL - DEPENDS common) + DEPENDS common + glslang) add_custom_target(software ALL DEPENDS common)