Browse Source

WIP: Linux port
- Getting Vulkan plugin to build

Marko Pintera 8 years ago
parent
commit
55bf4ddfd9
46 changed files with 1443 additions and 164 deletions
  1. 1 1
      Documentation/GitHub/dependencies.md
  2. 64 0
      Documentation/MonoIntegrationGuide.txt
  3. 10 3
      Source/BansheeVulkanRenderAPI/BsVulkanCommandBuffer.cpp
  4. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanCommandBuffer.h
  5. 97 1
      Source/BansheeVulkanRenderAPI/BsVulkanDevice.cpp
  6. 12 1
      Source/BansheeVulkanRenderAPI/BsVulkanDevice.h
  7. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanEventQuery.h
  8. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanGpuBuffer.h
  9. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanGpuParamBlockBuffer.h
  10. 6 6
      Source/BansheeVulkanRenderAPI/BsVulkanGpuParams.cpp
  11. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanGpuParams.h
  12. 6 6
      Source/BansheeVulkanRenderAPI/BsVulkanGpuPipelineParamInfo.cpp
  13. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanGpuPipelineParamInfo.h
  14. 3 6
      Source/BansheeVulkanRenderAPI/BsVulkanGpuPipelineState.cpp
  15. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanGpuPipelineState.h
  16. 15 7
      Source/BansheeVulkanRenderAPI/BsVulkanGpuProgram.cpp
  17. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanGpuProgram.h
  18. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanHardwareBuffer.h
  19. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanIndexBuffer.h
  20. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanOcclusionQuery.h
  21. 6 1
      Source/BansheeVulkanRenderAPI/BsVulkanPrerequisites.h
  22. 10 4
      Source/BansheeVulkanRenderAPI/BsVulkanRenderAPI.cpp
  23. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanRenderAPI.h
  24. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanRenderTexture.h
  25. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanResource.cpp
  26. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanSamplerState.h
  27. 6 6
      Source/BansheeVulkanRenderAPI/BsVulkanTexture.cpp
  28. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanTimerQuery.h
  29. 2 0
      Source/BansheeVulkanRenderAPI/BsVulkanUtility.cpp
  30. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanUtility.h
  31. 1 1
      Source/BansheeVulkanRenderAPI/BsVulkanVertexBuffer.h
  32. 35 5
      Source/BansheeVulkanRenderAPI/CMakeSources.cmake
  33. 709 0
      Source/BansheeVulkanRenderAPI/Linux/BsLinuxRenderWindow.cpp
  34. 172 0
      Source/BansheeVulkanRenderAPI/Linux/BsLinuxRenderWindow.h
  35. 182 0
      Source/BansheeVulkanRenderAPI/Linux/BsLinuxVideoModeInfo.cpp
  36. 57 0
      Source/BansheeVulkanRenderAPI/Linux/BsLinuxVideoModeInfo.h
  37. 2 2
      Source/BansheeVulkanRenderAPI/Managers/BsVulkanCommandBufferManager.cpp
  38. 2 2
      Source/BansheeVulkanRenderAPI/Managers/BsVulkanDescriptorManager.cpp
  39. 1 1
      Source/BansheeVulkanRenderAPI/Managers/BsVulkanHardwareBufferManager.cpp
  40. 1 1
      Source/BansheeVulkanRenderAPI/Managers/BsVulkanRenderAPIFactory.cpp
  41. 17 2
      Source/BansheeVulkanRenderAPI/Managers/BsVulkanRenderWindowManager.cpp
  42. 2 0
      Source/BansheeVulkanRenderAPI/Managers/BsVulkanTextureManager.cpp
  43. 1 1
      Source/BansheeVulkanRenderAPI/Managers/BsVulkanVertexInputManager.cpp
  44. 4 88
      Source/BansheeVulkanRenderAPI/Win32/BsWin32RenderWindow.cpp
  45. 1 1
      Source/BansheeVulkanRenderAPI/Win32/BsWin32RenderWindow.h
  46. 1 1
      Source/BansheeVulkanRenderAPI/Win32/BsWin32VideoModeInfo.h

+ 1 - 1
Documentation/GitHub/dependencies.md

@@ -111,7 +111,7 @@ Additionally, if the dependency structure still isn't clear, download one of the
   - Requires libogg, as described in its readme file.
    
 **glslang**
-- glslang commit: 19bdf90eba71390f04bb85226337517df65d73e2
+- glslang commit: 258b700f5957fc13b0512b3734a1b0e81a1c271d
 - https://github.com/KhronosGroup/glslang
 - Required by BansheeVulkanRenderAPI
 - Compile as a static library

+ 64 - 0
Documentation/MonoIntegrationGuide.txt

@@ -0,0 +1,64 @@
+---------------------------------Compiling runtime-------------------------------------
+ - Grab Mono 5.4 (or newer) source code
+  - From tarball: https://download.mono-project.com/sources/mono/
+  - Optionally check it out from git repository: https://github.com/mono/mono
+   - If on Windows, make sure your git client has this set: "git config --global core.autocrlf input" as otherwise you'll have problems with line endings during later steps
+
+ - Expose "mono_class_bind_generic_parameters" to the public:
+  - In mono/metadata/object-internals.h change:
+   MonoClass* mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic) MONO_INTERNAL; 
+   to:
+   MONO_API MonoClass* mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, mono_bool is_dynamic);
+   then move it to:
+   mono/metadata/object.h
+  - In mono/metadata/reflection.c modify:
+   MonoClass* mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
+   to:
+   MonoClass* mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, mono_bool is_dynamic)
+  - (Windows only) Add "mono_class_bind_generic_parameters" entry to mono/msvc/mono.def file
+
+ - Build
+  - Install Mono binary release (whichever one is the latest).
+  - (Windows only)Add the "(InstallDir)\Mono\bin" to your PATH environment variable.
+  - If on Windows:
+   - Go to msvc/ folder to find mono.sln (Visual studio solution)
+   - Open in VS2012 as is, or open in later VS and upgrade all projects to latest toolkit (v120 and v140 tested and working)
+   - Generate missing header files:
+    - First compile "genmdesc" project for desired configuration (debug/release, 32/64 bit)
+    - Then run "runmdesc x64\bin\Debug\genmdesc x64" located in /msvc folder
+     - Replace folder path to genmdesc you generated in the previous step
+      - Replace x64 with Win32 for 32-bit builds
+   - Compile mono project with desired configuration (debug/release, 32/64 bit, SGen builds were not tested). You will receive mono-2.0.dll and mono-2.0.lib as output.
+    - Repeat the "genmdesc" step above for each configuration. Doing it once might be enough but be on the safe side.
+  - If on Linux/Mac:
+   - "./autogen.sh --prefix="(OutputDir)" --with-preview=yes"" (Replace (OutputDir) with a folder where you want to output the binaries, e.g. "C:\MonoInstall")
+   - "./configure"
+   - "make"
+   - "make install"
+
+ - Post build
+  - (If using GDB only) Mono uses certain signals internally for normal operation. In order to avoid GDB triggering breakpoints when not required, put this in your .gdbinit file (in your $HOME path):
+   - handle SIGXCPU SIG33 SIG35 SIG36 SIGPWR nostop noprint
+
+-----------------------------Compiling libraries & compiler -------------------------------------
+ - If on Linux/Mac the compiler and libraries should already be compiled using the above steps
+ - If on Windows:
+  - Install Cygwin 32-bit version using these command line parameters:
+ setup-x86.exe -qnNdO -R "C:\cygwin" -s "http://cygwin.mirror.constant.com" 
+   -l "C:\cygwin\var\cache\setup" -P autoconf -P automake -P bison -P gcc-core -P gcc-g++ -P mingw64-i686-runtime 
+   -P mingw64-i686-binutils -P mingw64-i686-gcc-core -P mingw64-i686-gcc-g++ -P mingw64-i686-headers -P mingw64-i686-pthreads
+   -P mingw64-i686-windows-default-manifest -P mingw64-i686-winpthreads -P w32api-headers -P w32api-runtime 
+   -P windows-default-manifest -P libtool -P make -P python -P gettext-devel -P gettext -P intltool -P libiconv 
+   -P pkg-config -P git -P wget -P curl
+  - Go to your mono source directory (the one retrieved when compiling the runtime) in terminal (Cygwin or native) and enter these commands in order:
+   - "./autogen.sh --prefix="(OutputDir)" --with-preview=yes"" (Replace (OutputDir) with a folder where you want to output the binaries, e.g. "C:\MonoInstall")
+   - "./configure --host=i686-w64-mingw32"
+   - "make"
+   - "make install"
+  - Your built mono should now be output to (OutputDir) folder. (If it's not in that folder, check your Cygwin install folder under /usr/local)
+ - Copy contents of (OutputDir)/include/mono/mono-2.0/mono to (BansheeRootDir)/Dependencies/Include/Mono
+  - Make sure to modify "object.h" as you did above when building the binaries
+ - Copy folder (OutputDir)/etc to (BansheeRootDir)/bin/Mono
+ - Copy assembly folders (OutputDir)/lib/mono/4.0 and (OutputDir)/lib/mono/4.5 to (BansheeRootDir)/bin/Mono/lib/mono/4.0 and (BansheeRootDir)/bin/Mono/lib/mono/4.5, respectively
+  - If you wish, you can clean up the assemblies within those folders are many might not be used. The minimum needed are "mscorlib.dll", "System.dll" and "System.Core.dll".
+ - Copy the compiler (mcs executable) from (OutputDir)/lib/mono/4.5 to (BansheeRootDir)/bin/Mono/compiler

+ 10 - 3
Source/BansheeVulkanRenderAPI/BsVulkanCommandBuffer.cpp

@@ -20,6 +20,8 @@
 
 #if BS_PLATFORM == BS_PLATFORM_WIN32
 #include "Win32/BsWin32RenderWindow.h"
+#elif BS_PLATFORM == BS_PLATFORM_LINUX
+#include "Linux/BsLinuxRenderWindow.h"
 #else
 static_assert(false, "Other platforms go here");
 #endif
@@ -452,7 +454,7 @@ namespace bs { namespace ct
 				continue;
 
 			UINT32 currentQueueFamily = resource->getQueueFamily();
-			if (currentQueueFamily != -1 && currentQueueFamily != mQueueFamily)
+			if (currentQueueFamily != (UINT32)-1 && currentQueueFamily != mQueueFamily)
 			{
 				Vector<VkBufferMemoryBarrier>& barriers = mTransitionInfoTemp[currentQueueFamily].bufferBarriers;
 
@@ -478,7 +480,8 @@ namespace bs { namespace ct
 			ImageInfo& imageInfo = mImageInfos[entry.second];
 
 			UINT32 currentQueueFamily = resource->getQueueFamily();
-			bool queueMismatch = resource->isExclusive() && currentQueueFamily != -1 && currentQueueFamily != mQueueFamily;
+			bool queueMismatch = resource->isExclusive() && currentQueueFamily != (UINT32)-1
+				&& currentQueueFamily != mQueueFamily;
 
 			ImageSubresourceInfo* subresourceInfos = &mSubresourceInfoStorage[imageInfo.subresourceInfoIdx];
 			if (queueMismatch)
@@ -567,7 +570,7 @@ namespace bs { namespace ct
 			UINT32 entryQueueFamily = entry.first;
 
 			// No queue transition needed for entries on this queue (this entry is most likely an image layout transition)
-			if (entryQueueFamily == -1 || entryQueueFamily == mQueueFamily)
+			if (entryQueueFamily == (UINT32)-1 || entryQueueFamily == mQueueFamily)
 				continue;
 
 			VulkanCmdBuffer* cmdBuffer = device.getCmdBufferPool().getBuffer(entryQueueFamily, false);
@@ -814,7 +817,11 @@ namespace bs { namespace ct
 		{
 			if (rt->getProperties().isWindow)
 			{
+#if BS_PLATFORM == BS_PLATFORM_WIN32
 				Win32RenderWindow* window = static_cast<Win32RenderWindow*>(rt.get());
+#elif BS_PLATFORM == BS_PLATFORM_LINUX
+				LinuxRenderWindow* window = static_cast<LinuxRenderWindow*>(rt.get());
+#endif
 				window->acquireBackBuffer();
 
 				VulkanSwapChain* swapChain;

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanCommandBuffer.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsCommandBuffer.h"
+#include "RenderAPI/BsCommandBuffer.h"
 #include "BsVulkanRenderAPI.h"
 #include "BsVulkanResource.h"
 #include "BsVulkanGpuPipelineState.h"

+ 97 - 1
Source/BansheeVulkanRenderAPI/BsVulkanDevice.cpp

@@ -166,6 +166,102 @@ namespace bs { namespace ct
 		return idMask;
 	}
 
+	SurfaceFormat VulkanDevice::getSurfaceFormat(const VkSurfaceKHR& surface, bool gamma) const
+	{
+		uint32_t numFormats;
+		VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(mPhysicalDevice, surface, &numFormats, nullptr);
+		assert(result == VK_SUCCESS);
+		assert(numFormats > 0);
+
+		VkSurfaceFormatKHR* surfaceFormats = bs_stack_alloc<VkSurfaceFormatKHR>(numFormats);
+		result = vkGetPhysicalDeviceSurfaceFormatsKHR(mPhysicalDevice, surface, &numFormats, surfaceFormats);
+		assert(result == VK_SUCCESS);
+
+		SurfaceFormat output;
+		output.colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
+		output.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
+		output.depthFormat = VK_FORMAT_D24_UNORM_S8_UINT;
+
+		// If there is no preferred format, use standard RGBA
+		if ((numFormats == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED))
+		{
+			if (gamma)
+				output.colorFormat = VK_FORMAT_R8G8B8A8_SRGB;
+			else
+				output.colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
+
+			output.colorSpace = surfaceFormats[0].colorSpace;
+		}
+		else
+		{
+			bool foundFormat = false;
+
+			VkFormat wantedFormatsUNORM[] =
+			{
+				VK_FORMAT_R8G8B8A8_UNORM,
+				VK_FORMAT_B8G8R8A8_UNORM,
+				VK_FORMAT_A8B8G8R8_UNORM_PACK32,
+				VK_FORMAT_A8B8G8R8_UNORM_PACK32,
+				VK_FORMAT_R8G8B8_UNORM,
+				VK_FORMAT_B8G8R8_UNORM
+			};
+
+			VkFormat wantedFormatsSRGB[] =
+			{
+				VK_FORMAT_R8G8B8A8_SRGB,
+				VK_FORMAT_B8G8R8A8_SRGB,
+				VK_FORMAT_A8B8G8R8_SRGB_PACK32,
+				VK_FORMAT_A8B8G8R8_SRGB_PACK32,
+				VK_FORMAT_R8G8B8_SRGB,
+				VK_FORMAT_B8G8R8_SRGB
+			};
+
+			UINT32 numWantedFormats;
+			VkFormat* wantedFormats;
+			if (gamma)
+			{
+				numWantedFormats = sizeof(wantedFormatsSRGB) / sizeof(wantedFormatsSRGB[0]);
+				wantedFormats = wantedFormatsSRGB;
+			}
+			else
+			{
+				numWantedFormats = sizeof(wantedFormatsUNORM) / sizeof(wantedFormatsUNORM[0]);
+				wantedFormats = wantedFormatsUNORM;
+			}
+
+			for(UINT32 i = 0; i < numWantedFormats; i++)
+			{
+				for(UINT32 j = 0; j < numFormats; j++)
+				{
+					if(surfaceFormats[j].format == wantedFormats[i])
+					{
+						output.colorFormat = surfaceFormats[j].format;
+						output.colorSpace = surfaceFormats[j].colorSpace;
+
+						foundFormat = true;
+						break;
+					}
+				}
+
+				if (foundFormat)
+					break;
+			}
+
+			// If we haven't found anything, fall back to first available
+			if(!foundFormat)
+			{
+				output.colorFormat = surfaceFormats[0].format;
+				output.colorSpace = surfaceFormats[0].colorSpace;
+
+				if (gamma)
+					LOGERR("Cannot find a valid sRGB format for a render window surface, falling back to a default format.");
+			}
+		}
+
+		bs_stack_free(surfaceFormats);
+		return output;
+	}
+
 	VkDeviceMemory VulkanDevice::allocateMemory(VkImage image, VkMemoryPropertyFlags flags)
 	{
 		VkMemoryRequirements memReq;
@@ -200,7 +296,7 @@ namespace bs { namespace ct
 		allocateInfo.memoryTypeIndex = findMemoryType(reqs.memoryTypeBits, flags);
 		allocateInfo.allocationSize = reqs.size;
 
-		if (allocateInfo.memoryTypeIndex == -1)
+		if (allocateInfo.memoryTypeIndex == (UINT32)-1)
 			return VK_NULL_HANDLE;
 
 		VkDeviceMemory memory;

+ 12 - 1
Source/BansheeVulkanRenderAPI/BsVulkanDevice.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsRenderAPI.h"
+#include "RenderAPI/BsRenderAPI.h"
 #include "Managers/BsVulkanDescriptorManager.h"
 
 namespace bs { namespace ct
@@ -12,6 +12,14 @@ namespace bs { namespace ct
 	 *  @{
 	 */
 
+	/** Contains format describing a Vulkan surface. */
+	struct SurfaceFormat
+	{
+		VkFormat colorFormat;
+		VkFormat depthFormat;
+		VkColorSpaceKHR colorSpace;
+	};
+
 	/** Represents a single GPU device usable by Vulkan. */
 	class VulkanDevice
 	{
@@ -61,6 +69,9 @@ namespace bs { namespace ct
 		 */
 		UINT32 getQueueMask(GpuQueueType type, UINT32 queueIdx) const;
 
+		/** Returns the best matching surface format according to the provided parameters. */
+		SurfaceFormat getSurfaceFormat(const VkSurfaceKHR& surface, bool gamma) const;
+
 		/** Returns a pool that can be used for allocating command buffers for all queues on this device. */
 		VulkanCmdBufferPool& getCmdBufferPool() const { return *mCommandBufferPool; }
 

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanEventQuery.h

@@ -4,7 +4,7 @@
 
 #include "BsVulkanPrerequisites.h"
 #include "BsVulkanResource.h"
-#include "Renderapi/BsEventQuery.h"
+#include "RenderAPI/BsEventQuery.h"
 
 namespace bs { namespace ct
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanGpuBuffer.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsGpuBuffer.h"
+#include "RenderAPI/BsGpuBuffer.h"
 
 namespace bs { namespace ct
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanGpuParamBlockBuffer.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsGpuParamBlockBuffer.h"
+#include "RenderAPI/BsGpuParamBlockBuffer.h"
 
 namespace bs { namespace ct
 {

+ 6 - 6
Source/BansheeVulkanRenderAPI/BsVulkanGpuParams.cpp

@@ -15,7 +15,7 @@
 #include "BsVulkanCommandBuffer.h"
 #include "Managers/BsVulkanTextureManager.h"
 #include "Managers/BsVulkanHardwareBufferManager.h"
-#include "Renderapi/BsGpuParamDesc.h"
+#include "RenderAPI/BsGpuParamDesc.h"
 
 namespace bs { namespace ct
 {
@@ -226,7 +226,7 @@ namespace bs { namespace ct
 
 		VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
 		UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
-		if(bindingIdx == -1)
+		if(bindingIdx == (UINT32)-1)
 		{
 			LOGERR("Provided set/slot combination is not used by the GPU program: " + toString(set) + "," + 
 				toString(slot) + ".");
@@ -277,7 +277,7 @@ namespace bs { namespace ct
 
 		VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
 		UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
-		if (bindingIdx == -1)
+		if (bindingIdx == (UINT32)-1)
 		{
 			LOGERR("Provided set/slot combination is not used by the GPU program: " + toString(set) + "," +
 				   toString(slot) + ".");
@@ -338,7 +338,7 @@ namespace bs { namespace ct
 
 		VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
 		UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
-		if (bindingIdx == -1)
+		if (bindingIdx == (UINT32)-1)
 		{
 			LOGERR("Provided set/slot combination is not used by the GPU program: " + toString(set) + "," +
 				   toString(slot) + ".");
@@ -389,7 +389,7 @@ namespace bs { namespace ct
 
 		VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
 		UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
-		if (bindingIdx == -1)
+		if (bindingIdx == (UINT32)-1)
 		{
 			LOGERR("Provided set/slot combination is not used by the GPU program: " + toString(set) + "," +
 				   toString(slot) + ".");
@@ -473,7 +473,7 @@ namespace bs { namespace ct
 
 		VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
 		UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
-		if (bindingIdx == -1)
+		if (bindingIdx == (UINT32)-1)
 		{
 			LOGERR("Provided set/slot combination is not used by the GPU program: " + toString(set) + "," +
 				   toString(slot) + ".");

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanGpuParams.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsGpuParams.h"
+#include "RenderAPI/BsGpuParams.h"
 #include "Allocators/BsGroupAlloc.h"
 
 namespace bs { namespace ct

+ 6 - 6
Source/BansheeVulkanRenderAPI/BsVulkanGpuPipelineParamInfo.cpp

@@ -4,7 +4,7 @@
 #include "BsVulkanUtility.h"
 #include "BsVulkanRenderAPI.h"
 #include "BsVulkanDevice.h"
-#include "Renderapi/BsGpuParamDesc.h"
+#include "RenderAPI/BsGpuParamDesc.h"
 
 namespace bs { namespace ct
 {
@@ -78,9 +78,9 @@ namespace bs { namespace ct
 
 			for (UINT32 j = 0; j < mSetInfos[i].numSlots; j++)
 			{
-				if (mSetInfos[i].slotIndices[j] == -1)
+				if (mSetInfos[i].slotIndices[j] == (UINT32)-1)
 				{
-					mSetExtraInfos[i].slotIndices[j] = -1;
+					mSetExtraInfos[i].slotIndices[j] = (UINT32)-1;
 					continue;
 				}
 
@@ -121,7 +121,7 @@ namespace bs { namespace ct
 				for (auto& entry : params)
 				{
 					UINT32 bindingIdx = getBindingIdx(entry.second.set, entry.second.slot);
-					assert(bindingIdx != -1);
+					assert(bindingIdx != (UINT32)-1);
 
 					LayoutInfo& layoutInfo = mLayoutInfos[entry.second.set];
 					VkDescriptorSetLayoutBinding& binding = layoutInfo.bindings[bindingIdx];
@@ -136,7 +136,7 @@ namespace bs { namespace ct
 				for (auto& entry : params)
 				{
 					UINT32 bindingIdx = getBindingIdx(entry.second.set, entry.second.slot);
-					assert(bindingIdx != -1);
+					assert(bindingIdx != (UINT32)-1);
 
 					LayoutInfo& layoutInfo = mLayoutInfos[entry.second.set];
 					VkDescriptorSetLayoutBinding& binding = layoutInfo.bindings[bindingIdx];
@@ -158,7 +158,7 @@ namespace bs { namespace ct
 			for (auto& entry : paramDesc->buffers)
 			{
 				UINT32 bindingIdx = getBindingIdx(entry.second.set, entry.second.slot);
-				assert(bindingIdx != -1);
+				assert(bindingIdx != (UINT32)-1);
 
 				LayoutInfo& layoutInfo = mLayoutInfos[entry.second.set];
 				VkDescriptorSetLayoutBinding& binding = layoutInfo.bindings[bindingIdx];

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanGpuPipelineParamInfo.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsGpuPipelineParamInfo.h"
+#include "RenderAPI/BsGpuPipelineParamInfo.h"
 #include "Allocators/BsGroupAlloc.h"
 
 namespace bs { namespace ct

+ 3 - 6
Source/BansheeVulkanRenderAPI/BsVulkanGpuPipelineState.cpp

@@ -9,9 +9,9 @@
 #include "BsVulkanGpuPipelineParamInfo.h"
 #include "Managers/BsVulkanVertexInputManager.h"
 #include "BsVulkanCommandBuffer.h"
-#include "Renderapi/BsRasterizerState.h"
-#include "Renderapi/BsDepthStencilState.h"
-#include "Renderapi/BsBlendState.h"
+#include "RenderAPI/BsRasterizerState.h"
+#include "RenderAPI/BsDepthStencilState.h"
+#include "RenderAPI/BsBlendState.h"
 #include "Profiling/BsRenderStats.h"
 
 namespace bs { namespace ct
@@ -442,10 +442,7 @@ namespace bs { namespace ct
 			mPipelineInfo.pColorBlendState = nullptr;
 
 			for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
-			{
-				VkPipelineColorBlendAttachmentState& blendState = mAttachmentBlendStates[i];
 				colorReadOnly[i] = true;
-			}
 		}
 
 		std::pair<VkShaderStageFlagBits, GpuProgram*> stages[] =

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanGpuPipelineState.h

@@ -4,7 +4,7 @@
 
 #include "BsVulkanPrerequisites.h"
 #include "BsVulkanResource.h"
-#include "Renderapi/BsGpuPipelineState.h"
+#include "RenderAPI/BsGpuPipelineState.h"
 
 namespace bs { namespace ct
 {

+ 15 - 7
Source/BansheeVulkanRenderAPI/BsVulkanGpuProgram.cpp

@@ -4,10 +4,10 @@
 #include "BsVulkanRenderAPI.h"
 #include "BsVulkanDevice.h"
 #include "BsVulkanUtility.h"
-#include "Renderapi/BsGpuParams.h"
-#include "Renderapi/BsGpuParamDesc.h"
+#include "RenderAPI/BsGpuParams.h"
+#include "RenderAPI/BsGpuParamDesc.h"
 #include "Managers/BsGpuProgramManager.h"
-#include "Renderapi/BsVertexDeclaration.h"
+#include "RenderAPI/BsVertexDeclaration.h"
 #include "Managers/BsHardwareBufferManager.h"
 #include "Profiling/BsRenderStats.h"
 #include "FileSystem/BsFileSystem.h"
@@ -336,7 +336,7 @@ namespace bs { namespace ct
 			const glslang::TType* ttype = program->getAttributeTType(i);
 			UINT32 location = ttype->getQualifier().layoutLocation;
 
-			if (location == -1)
+			if (location == (UINT32)-1)
 			{
 				log = "Vertex attribute parsing error: Found a vertex attribute without a location "
 					"qualifier. Each attribute must have an explicitly defined location number.";
@@ -462,6 +462,8 @@ namespace bs { namespace ct
 						break;
 					case glslang::Esd3D:		param.type = GPOT_RWTEXTURE3D; break;
 					case glslang::EsdBuffer:	param.type = GPOT_RWBYTE_BUFFER; break;
+					default:
+						break;
 					}
 
 					if(sampler.dim != glslang::EsdBuffer)
@@ -477,6 +479,8 @@ namespace bs { namespace ct
 					case glslang::Esd2D:		param.type = sampler.isMultiSample() ? GPOT_SAMPLER2DMS : GPOT_SAMPLER2D; break;
 					case glslang::Esd3D:		param.type = GPOT_SAMPLER3D; break;
 					case glslang::EsdCube:		param.type = GPOT_SAMPLERCUBE; break;
+					default:
+						break;
 					}
 
 					desc.samplers[name] = param;
@@ -495,6 +499,8 @@ namespace bs { namespace ct
 						case glslang::Esd3D:		param.type = GPOT_TEXTURE3D; break;
 						case glslang::EsdCube:		param.type = sampler.isArrayed() ? GPOT_TEXTURECUBEARRAY : GPOT_TEXTURECUBE; break;
 						case glslang::EsdBuffer:	param.type = GPOT_BYTE_BUFFER; break;
+						default:
+							break;
 						}
 
 						if (sampler.dim != glslang::EsdBuffer)
@@ -616,8 +622,13 @@ namespace bs { namespace ct
 		case GPT_COMPUTE_PROGRAM:
 			glslType = EShLangCompute;
 			break;
+		default:
+			break;
 		}
 
+		VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPI::instance());
+		VulkanDevice* devices[BS_MAX_DEVICES];
+
 		std::vector<UINT32> spirv;
 		spv::SpvBuildLogger logger;
 		std::string compileLog;
@@ -683,9 +694,6 @@ namespace bs { namespace ct
 		moduleCI.codeSize = spirv.size() * sizeof(UINT32);
 		moduleCI.pCode = spirv.data();
 
-		VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPI::instance());
-
-		VulkanDevice* devices[BS_MAX_DEVICES];
 		VulkanUtility::getDevices(rapi, mDeviceMask, devices);
 
 		for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanGpuProgram.h

@@ -4,7 +4,7 @@
 
 #include "BsVulkanPrerequisites.h"
 #include "BsVulkanResource.h"
-#include "Renderapi/BsGpuProgram.h"
+#include "RenderAPI/BsGpuProgram.h"
 
 namespace bs { namespace ct
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanHardwareBuffer.h

@@ -4,7 +4,7 @@
 
 #include "BsVulkanPrerequisites.h"
 #include "BsVulkanResource.h"
-#include "Renderapi/BsHardwareBuffer.h"
+#include "RenderAPI/BsHardwareBuffer.h"
 
 namespace bs { namespace ct
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanIndexBuffer.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsIndexBuffer.h"
+#include "RenderAPI/BsIndexBuffer.h"
 
 namespace bs { namespace ct
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanOcclusionQuery.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsOcclusionQuery.h"
+#include "RenderAPI/BsOcclusionQuery.h"
 
 namespace bs { namespace ct
 {

+ 6 - 1
Source/BansheeVulkanRenderAPI/BsVulkanPrerequisites.h

@@ -11,12 +11,17 @@
 
 #if BS_PLATFORM == BS_PLATFORM_WIN32
 	#define VK_USE_PLATFORM_WIN32_KHR
+#elif BS_PLATFORM == BS_PLATFORM_LINUX
+	#define VK_USE_PLATFORM_XLIB_KHR
+#elif BS_PLATFORM == BS_PLATFORM_ANDROID
+	#define VK_USE_PLATFORM_ANDROID_KHR
 #endif
 
 /** Maximum number of GPU queues that may exist at once. */
 #define BS_MAX_UNIQUE_QUEUES BS_MAX_QUEUES_PER_TYPE * bs::GQT_COUNT // Must fit within 4 bytes
 
 #include "vulkan/vulkan.h"
+#undef None // Conflicting define from Xlib
 
 /** @addtogroup Plugins
  *  @{
@@ -102,4 +107,4 @@ namespace bs { namespace ct
 
 /** Macro to get a procedure address based on a Vulkan device. */
 #define GET_DEVICE_PROC_ADDR(device, name) \
-	vk##name = reinterpret_cast<PFN_vk##name>(vkGetDeviceProcAddr(device, "vk"#name));
+	vk##name = reinterpret_cast<PFN_vk##name>(vkGetDeviceProcAddr(device, "vk"#name));

+ 10 - 4
Source/BansheeVulkanRenderAPI/BsVulkanRenderAPI.cpp

@@ -1,9 +1,9 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsVulkanRenderAPI.h"
-#include "Corethread/BsCoreThread.h"
+#include "CoreThread/BsCoreThread.h"
 #include "Profiling/BsRenderStats.h"
-#include "Renderapi/BsGpuParamDesc.h"
+#include "RenderAPI/BsGpuParamDesc.h"
 #include "BsVulkanDevice.h"
 #include "Managers/BsVulkanTextureManager.h"
 #include "Managers/BsVulkanRenderWindowManager.h"
@@ -18,8 +18,12 @@
 #include "Managers/BsVulkanVertexInputManager.h"
 #include "BsVulkanGpuParamBlockBuffer.h"
 
+#include <vulkan/vulkan.h>
+
 #if BS_PLATFORM == BS_PLATFORM_WIN32
 	#include "Win32/BsWin32VideoModeInfo.h"
+#elif BS_PLATFORM == BS_PLATFORM_LINUX
+	#include "Linux/BsLinuxVideoModeInfo.h"
 #else
 	static_assert(false, "Other platform includes go here.");
 #endif
@@ -148,7 +152,7 @@ namespace bs { namespace ct
 #elif BS_PLATFORM == BS_PLATFORM_ANDROID
 		extensions[1] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
 #else
-		extensions[1] = VK_KHR_XCB_SURFACE_EXTENSION_NAME;
+		extensions[1] = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
 #endif
 
 		uint32_t numExtensions = sizeof(extensions) / sizeof(extensions[0]);
@@ -216,8 +220,10 @@ namespace bs { namespace ct
 
 #if BS_PLATFORM == BS_PLATFORM_WIN32
 		mVideoModeInfo = bs_shared_ptr_new<Win32VideoModeInfo>();
+#elif BS_PLATFORM == BS_PLATFORM_LINUX
+		mVideoModeInfo = bs_shared_ptr_new<LinuxVideoModeInfo>();
 #else
-		static_assert(false, "mVideoModeInfo needs to be created.")
+		static_assert(false, "mVideoModeInfo needs to be created.");
 #endif
 
 		GPUInfo gpuInfo;

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanRenderAPI.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsRenderAPI.h"
+#include "RenderAPI/BsRenderAPI.h"
 
 namespace bs { namespace ct
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanRenderTexture.h

@@ -4,7 +4,7 @@
 
 #include "BsVulkanPrerequisites.h"
 #include "Image/BsTexture.h"
-#include "Renderapi/BsRenderTexture.h"
+#include "RenderAPI/BsRenderTexture.h"
 
 namespace bs
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanResource.cpp

@@ -2,7 +2,7 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsVulkanResource.h"
 #include "BsVulkanCommandBuffer.h"
-#include "Corethread/BsCoreThread.h"
+#include "CoreThread/BsCoreThread.h"
 
 namespace bs { namespace ct
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanSamplerState.h

@@ -4,7 +4,7 @@
 
 #include "BsVulkanPrerequisites.h"
 #include "BsVulkanResource.h"
-#include "Renderapi/BsSamplerState.h"
+#include "RenderAPI/BsSamplerState.h"
 
 namespace bs { namespace ct
 {

+ 6 - 6
Source/BansheeVulkanRenderAPI/BsVulkanTexture.cpp

@@ -6,7 +6,7 @@
 #include "BsVulkanUtility.h"
 #include "Managers/BsVulkanCommandBufferManager.h"
 #include "BsVulkanHardwareBuffer.h"
-#include "Corethread/BsCoreThread.h"
+#include "CoreThread/BsCoreThread.h"
 #include "Profiling/BsRenderStats.h"
 #include "Math/BsMath.h"
 
@@ -34,7 +34,7 @@ namespace bs { namespace ct
 
 	VulkanImage::VulkanImage(VulkanResourceManager* owner, const VULKAN_IMAGE_DESC& desc, bool ownsImage)
 		: VulkanResource(owner, false), mImage(desc.image), mMemory(desc.memory), mFramebufferMainView(VK_NULL_HANDLE)
-		, mOwnsImage(ownsImage), mNumFaces(desc.numFaces), mNumMipLevels(desc.numMipLevels), mUsage(desc.usage)
+		, mUsage(desc.usage), mOwnsImage(ownsImage), mNumFaces(desc.numFaces), mNumMipLevels(desc.numMipLevels)
 	{
 		mImageViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
 		mImageViewCI.pNext = nullptr;
@@ -563,10 +563,10 @@ namespace bs { namespace ct
 
 	VulkanTexture::VulkanTexture(const TEXTURE_DESC& desc, const SPtr<PixelData>& initialData,
 										 GpuDeviceFlags deviceMask)
-		: Texture(desc, initialData, deviceMask), mImages(), mDeviceMask(deviceMask), mStagingBuffer(nullptr)
-		, mMappedDeviceIdx(-1), mMappedGlobalQueueIdx(-1), mMappedMip(0), mMappedFace(0), mMappedRowPitch(false)
-		, mMappedSlicePitch(false), mMappedLockOptions(GBL_WRITE_ONLY), mInternalFormats()
-		, mDirectlyMappable(false), mSupportsGPUWrites(false), mIsMapped(false)
+		: Texture(desc, initialData, deviceMask), mImages(), mInternalFormats(), mDeviceMask(deviceMask)
+		, mStagingBuffer(nullptr), mMappedDeviceIdx((UINT32)-1), mMappedGlobalQueueIdx((UINT32)-1)
+		, mMappedMip(0), mMappedFace(0), mMappedRowPitch(0), mMappedSlicePitch(0)
+		, mMappedLockOptions(GBL_WRITE_ONLY), mDirectlyMappable(false), mSupportsGPUWrites(false), mIsMapped(false)
 	{
 		
 	}

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanTimerQuery.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsTimerQuery.h"
+#include "RenderAPI/BsTimerQuery.h"
 
 namespace bs { namespace ct
 {

+ 2 - 0
Source/BansheeVulkanRenderAPI/BsVulkanUtility.cpp

@@ -351,6 +351,8 @@ namespace bs { namespace ct
 			return VK_SHADER_STAGE_VERTEX_BIT;
 		case GPT_COMPUTE_PROGRAM:
 			return VK_SHADER_STAGE_COMPUTE_BIT;
+		default:
+			break;
 		}
 
 		// Unsupported type

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanUtility.h

@@ -4,7 +4,7 @@
 
 #include "BsVulkanPrerequisites.h"
 #include "Image/BsPixelUtil.h"
-#include "Renderapi/BsVertexDeclaration.h"
+#include "RenderAPI/BsVertexDeclaration.h"
 
 namespace bs { namespace ct
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/BsVulkanVertexBuffer.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsVertexBuffer.h"
+#include "RenderAPI/BsVertexBuffer.h"
 
 namespace bs { namespace ct
 {

+ 35 - 5
Source/BansheeVulkanRenderAPI/CMakeSources.cmake

@@ -1,6 +1,4 @@
 set(BS_BANSHEEVULKANRENDERAPI_INC_NOFILTER
-	"Win32/BsWin32VideoModeInfo.h"
-	"Win32/BsWin32RenderWindow.h"	
 	"BsVulkanVertexBuffer.h"
 	"BsVulkanTimerQuery.h"
 	"BsVulkanTexture.h"
@@ -44,8 +42,6 @@ set(BS_BANSHEEVULKANRENDERAPI_INC_MANAGERS
 )
 
 set(BS_BANSHEEVULKANRENDERAPI_SRC_NOFILTER
-	"Win32/BsWin32VideoModeInfo.cpp"
-	"Win32/BsWin32RenderWindow.cpp"	
 	"BsVulkanVertexBuffer.cpp"
 	"BsVulkanTimerQuery.cpp"
 	"BsVulkanTexture.cpp"
@@ -88,14 +84,48 @@ set(BS_BANSHEEVULKANRENDERAPI_SRC_MANAGERS
 	"Managers/BsVulkanDescriptorManager.cpp"
 )
 
+set(BS_BANSHEEVULKANRENDERAPI_INC_WIN32
+	"Win32/BsWin32VideoModeInfo.h"
+	"Win32/BsWin32RenderWindow.h"
+)
+
+set(BS_BANSHEEVULKANRENDERAPI_SRC_WIN32
+	"Win32/BsWin32VideoModeInfo.cpp"
+	"Win32/BsWin32RenderWindow.cpp"
+)
+
+set(BS_BANSHEEVULKANRENDERAPI_INC_LINUX
+	"Linux/BsLinuxVideoModeInfo.h"
+	"Linux/BsLinuxRenderWindow.h"
+)
+
+set(BS_BANSHEEVULKANRENDERAPI_SRC_LINUX
+	"Linux/BsLinuxVideoModeInfo.cpp"
+	"Linux/BsLinuxRenderWindow.cpp"
+)
+
 source_group("Header Files" FILES ${BS_BANSHEEVULKANRENDERAPI_INC_NOFILTER})
 source_group("Header Files\\Managers" FILES ${BS_BANSHEEVULKANRENDERAPI_INC_MANAGERS})
+source_group("Header Files\\Win32" FILES ${BS_BANSHEEVULKANRENDERAPI_INC_WIN32})
 source_group("Source Files" FILES ${BS_BANSHEEVULKANRENDERAPI_SRC_NOFILTER})
 source_group("Source Files\\Managers" FILES ${BS_BANSHEEVULKANRENDERAPI_SRC_MANAGERS})
+source_group("Source Files\\Win32" FILES ${BS_BANSHEEVULKANRENDERAPI_SRC_WIN32})
 
 set(BS_BANSHEEVULKANRENDERAPI_SRC
 	${BS_BANSHEEVULKANRENDERAPI_INC_NOFILTER}
 	${BS_BANSHEEVULKANRENDERAPI_SRC_NOFILTER}
 	${BS_BANSHEEVULKANRENDERAPI_INC_MANAGERS}
 	${BS_BANSHEEVULKANRENDERAPI_SRC_MANAGERS}
-)
+)
+
+if(WIN32)
+	list(APPEND BS_BANSHEEVULKANRENDERAPI_SRC
+		${BS_BANSHEEVULKANRENDERAPI_INC_WIN32}
+		${BS_BANSHEEVULKANRENDERAPI_SRC_WIN32}
+	)
+elseif(LINUX)
+	list(APPEND BS_BANSHEEVULKANRENDERAPI_SRC
+		${BS_BANSHEEVULKANRENDERAPI_INC_LINUX}
+		${BS_BANSHEEVULKANRENDERAPI_SRC_LINUX}
+	)
+endif()

+ 709 - 0
Source/BansheeVulkanRenderAPI/Linux/BsLinuxRenderWindow.cpp

@@ -0,0 +1,709 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "CoreThread/BsCoreThread.h"
+#include "Linux/BsLinuxPlatform.h"
+#include "Linux/BsLinuxRenderWindow.h"
+#include "Linux/BsLinuxWindow.h"
+#include "Linux/BsLinuxVideoModeInfo.h"
+#include "Math/BsMath.h"
+#include "Managers/BsRenderWindowManager.h"
+#include "Managers/BsVulkanCommandBufferManager.h"
+#include "BsVulkanRenderAPI.h"
+#include "BsVulkanDevice.h"
+#include "BsVulkanSwapChain.h"
+#include "BsVulkanQueue.h"
+#include <X11/Xutil.h>
+
+#define XRANDR_ROTATION_LEFT    (1 << 1)
+#define XRANDR_ROTATION_RIGHT   (1 << 3)
+
+namespace bs
+{
+	LinuxRenderWindow::LinuxRenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId)
+		:RenderWindow(desc, windowId), mProperties(desc)
+	{ }
+
+	void LinuxRenderWindow::getCustomAttribute(const String& name, void* data) const
+	{
+		if (name == "WINDOW" || name == "LINUX_WINDOW")
+		{
+			blockUntilCoreInitialized();
+			getCore()->getCustomAttribute(name, data);
+			return;
+		}
+	}
+
+	Vector2I LinuxRenderWindow::screenToWindowPos(const Vector2I& screenPos) const
+	{
+		blockUntilCoreInitialized();
+
+		LinuxPlatform::lockX();
+		Vector2I pos = getCore()->_getInternal()->screenToWindowPos(screenPos);
+		LinuxPlatform::unlockX();
+
+		return pos;
+	}
+
+	Vector2I LinuxRenderWindow::windowToScreenPos(const Vector2I& windowPos) const
+	{
+		blockUntilCoreInitialized();
+
+		LinuxPlatform::lockX();
+		Vector2I pos = getCore()->_getInternal()->windowToScreenPos(windowPos);
+		LinuxPlatform::unlockX();
+
+		return pos;
+	}
+
+	SPtr<ct::LinuxRenderWindow> LinuxRenderWindow::getCore() const
+	{
+		return std::static_pointer_cast<ct::LinuxRenderWindow>(mCoreSpecific);
+	}
+
+	void LinuxRenderWindow::syncProperties()
+	{
+		ScopedSpinLock lock(getCore()->_getPropertiesLock());
+		mProperties = getCore()->mSyncedProperties;
+	}
+
+	namespace ct
+	{
+	LinuxRenderWindow::LinuxRenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId, VulkanRenderAPI& renderAPI)
+		: RenderWindow(desc, windowId), mRenderAPI(renderAPI), mRequiresNewBackBuffer(true), mWindow(nullptr)
+		, mProperties(desc), mSyncedProperties(desc), mIsChild(false), mShowOnSwap(false)
+	{ }
+
+	LinuxRenderWindow::~LinuxRenderWindow()
+	{
+		// Make sure to set the original desktop video mode before we exit
+		if(mProperties.isFullScreen)
+			setWindowed(50, 50);
+
+		SPtr<VulkanDevice> presentDevice = mRenderAPI._getPresentDevice();
+		presentDevice->waitIdle();
+
+		if (mWindow != nullptr)
+		{
+			Platform::resetNonClientAreas(*this);
+
+			LinuxPlatform::lockX();
+
+			bs_delete(mWindow);
+			mWindow = nullptr;
+
+			LinuxPlatform::unlockX();
+		}
+
+		mSwapChain = nullptr;
+		vkDestroySurfaceKHR(mRenderAPI._getInstance(), mSurface, gVulkanAllocator);
+	}
+
+	void LinuxRenderWindow::initialize()
+	{
+		LinuxPlatform::lockX();
+
+		RenderWindowProperties& props = mProperties;
+
+		props.isFullScreen = mDesc.fullscreen;
+		mIsChild = false;
+
+		XVisualInfo visualInfoTempl = {};
+		visualInfoTempl.screen = XDefaultScreen(LinuxPlatform::getXDisplay());
+		visualInfoTempl.depth = 32;
+		visualInfoTempl.c_class = TrueColor;
+
+		int32_t numVisuals;
+		XVisualInfo* visualInfo = XGetVisualInfo(LinuxPlatform::getXDisplay(),
+				VisualScreenMask | VisualDepthMask | VisualClassMask, &visualInfoTempl, &numVisuals);
+
+		WINDOW_DESC windowDesc;
+		windowDesc.x = mDesc.left;
+		windowDesc.y = mDesc.top;
+		windowDesc.width = mDesc.videoMode.getWidth();
+		windowDesc.height = mDesc.videoMode.getHeight();
+		windowDesc.title = mDesc.title;
+		windowDesc.showDecorations = mDesc.showTitleBar;
+		windowDesc.allowResize = mDesc.allowResize;
+		windowDesc.showOnTaskBar = !mDesc.toolWindow;
+		windowDesc.modal = mDesc.modal;
+		windowDesc.visualInfo = *visualInfo;
+		windowDesc.screen = mDesc.videoMode.getOutputIdx();
+		windowDesc.hidden = mDesc.hideUntilSwap || mDesc.hidden;
+
+		NameValuePairList::const_iterator opt;
+		opt = mDesc.platformSpecific.find("parentWindowHandle");
+		if (opt != mDesc.platformSpecific.end())
+			windowDesc.parent = (::Window)parseUINT64(opt->second);
+		else
+			windowDesc.parent = 0;
+
+		mIsChild = windowDesc.parent != 0;
+		props.isFullScreen = mDesc.fullscreen && !mIsChild;
+
+		mShowOnSwap = mDesc.hideUntilSwap;
+		props.isHidden = mDesc.hideUntilSwap || mDesc.hidden;
+
+		mWindow = bs_new<LinuxWindow>(windowDesc);
+		mWindow->_setUserData(this);
+
+		props.width = mWindow->getWidth();
+		props.height = mWindow->getHeight();
+		props.top = mWindow->getTop();
+		props.left = mWindow->getLeft();
+
+		props.hwGamma = mDesc.gamma;
+		props.multisampleCount = mDesc.multisampleCount;
+
+		XWindowAttributes windowAttributes;
+		XGetWindowAttributes(LinuxPlatform::getXDisplay(), mWindow->_getXWindow(), &windowAttributes);
+
+		// Create Vulkan surface
+		VkXlibSurfaceCreateInfoKHR surfaceCreateInfo;
+		surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+		surfaceCreateInfo.pNext = nullptr;
+		surfaceCreateInfo.flags = 0;
+		surfaceCreateInfo.window = mWindow->_getXWindow();
+		surfaceCreateInfo.dpy = LinuxPlatform::getXDisplay();
+
+		// Note: I manually lock Xlib, while Vulkan spec says XInitThreads should be called, since Vulkan
+		// surely calls Xlib under the hood as well. I've tried to guess which calls use Xlib and lock them
+		// externally, but XInitThreads might be required if problems occur.
+		VkInstance instance = mRenderAPI._getInstance();
+		VkResult result = vkCreateXlibSurfaceKHR(instance, &surfaceCreateInfo, gVulkanAllocator, &mSurface);
+		assert(result == VK_SUCCESS);
+
+		SPtr<VulkanDevice> presentDevice = mRenderAPI._getPresentDevice();
+		VkPhysicalDevice physicalDevice = presentDevice->getPhysical();
+
+		mPresentQueueFamily = presentDevice->getQueueFamily(GQT_GRAPHICS);
+
+		VkBool32 supportsPresent;
+		vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, mPresentQueueFamily, mSurface, &supportsPresent);
+
+		if(!supportsPresent)
+		{
+			// Note: Not supporting present only queues at the moment
+			// Note: Also present device can only return one family of graphics queue, while there could be more (some of
+			// which support present)
+			BS_EXCEPT(RenderingAPIException, "Cannot find a graphics queue that also supports present operations.");
+		}
+
+		SurfaceFormat format = presentDevice->getSurfaceFormat(mSurface, mDesc.gamma);
+		mColorFormat = format.colorFormat;
+		mColorSpace = format.colorSpace;
+		mDepthFormat = format.depthFormat;
+
+		// Create swap chain
+		mSwapChain = bs_shared_ptr_new<VulkanSwapChain>();
+		mSwapChain->rebuild(presentDevice, mSurface, props.width, props.height, props.vsync, mColorFormat, mColorSpace,
+				mDesc.depthBuffer, mDepthFormat);
+
+		LinuxPlatform::unlockX(); // Calls below have their own locking mechanisms
+
+		if(mDesc.fullscreen && !mIsChild)
+			setFullscreen(mDesc.videoMode);
+
+		if(mDesc.vsync && mDesc.vsyncInterval > 0)
+			setVSync(true, mDesc.vsyncInterval);
+
+		{
+			ScopedSpinLock lock(mLock);
+			mSyncedProperties = props;
+		}
+
+		bs::RenderWindowManager::instance().notifySyncDataDirty(this);
+		RenderWindow::initialize();
+	}
+
+	void LinuxRenderWindow::acquireBackBuffer()
+	{
+		// We haven't presented the current back buffer yet, so just use that one
+		if (!mRequiresNewBackBuffer)
+			return;
+
+		mSwapChain->acquireBackBuffer();
+		mRequiresNewBackBuffer = false;
+	}
+
+	void LinuxRenderWindow::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		VideoMode videoMode(width, height, refreshRate, monitorIdx);
+		setFullscreen(videoMode);
+	}
+
+	void LinuxRenderWindow::setVideoMode(INT32 screen, RROutput output, RRMode mode)
+	{
+		::Display* display = LinuxPlatform::getXDisplay();
+		::Window rootWindow = RootWindow(display, screen);
+
+		XRRScreenResources* screenRes = XRRGetScreenResources (display, rootWindow);
+		if(screenRes == nullptr)
+		{
+			LOGERR("XRR: Failed to retrieve screen resources. ");
+			return;
+		}
+
+		XRROutputInfo* outputInfo = XRRGetOutputInfo(display, screenRes, output);
+		if(outputInfo == nullptr)
+		{
+			XRRFreeScreenResources(screenRes);
+
+			LOGERR("XRR: Failed to retrieve output info for output: " + toString((UINT32)output));
+			return;
+		}
+
+		XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(display, screenRes, outputInfo->crtc);
+		if(crtcInfo == nullptr)
+		{
+			XRRFreeScreenResources(screenRes);
+			XRRFreeOutputInfo(outputInfo);
+
+			LOGERR("XRR: Failed to retrieve CRTC info for output: " + toString((UINT32)output));
+			return;
+		}
+
+		// Note: This changes the user's desktop resolution permanently, even when the app exists, make sure to revert
+		// (Sadly there doesn't appear to be a better way)
+		Status status = XRRSetCrtcConfig (display, screenRes, outputInfo->crtc, CurrentTime,
+			crtcInfo->x, crtcInfo->y, mode, crtcInfo->rotation, &output, 1);
+
+		if(status != Success)
+			LOGERR("XRR: XRRSetCrtcConfig failed.");
+
+		XRRFreeCrtcInfo(crtcInfo);
+		XRRFreeOutputInfo(outputInfo);
+		XRRFreeScreenResources(screenRes);
+	}
+
+	void LinuxRenderWindow::setFullscreen(const VideoMode& mode)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mIsChild)
+			return;
+
+		const LinuxVideoModeInfo& videoModeInfo =
+				static_cast<const LinuxVideoModeInfo&>(RenderAPI::instance().getVideoModeInfo());
+
+		UINT32 outputIdx = mode.getOutputIdx();
+		if(outputIdx >= videoModeInfo.getNumOutputs())
+		{
+			LOGERR("Invalid output device index.")
+			return;
+		}
+
+		const LinuxVideoOutputInfo& outputInfo =
+				static_cast<const LinuxVideoOutputInfo&>(videoModeInfo.getOutputInfo (outputIdx));
+
+		INT32 screen = outputInfo._getScreen();
+		RROutput outputID = outputInfo._getOutputID();
+
+		RRMode modeID = 0;
+		if(!mode.isCustom())
+		{
+			const LinuxVideoMode& videoMode = static_cast<const LinuxVideoMode&>(mode);
+			modeID = videoMode._getModeID();
+		}
+		else
+		{
+			LinuxPlatform::lockX();
+
+			// Look for mode matching the requested resolution
+			::Display* display = LinuxPlatform::getXDisplay();
+			::Window rootWindow = RootWindow(display, screen);
+
+			XRRScreenResources* screenRes = XRRGetScreenResources(display, rootWindow);
+			if (screenRes == nullptr)
+			{
+				LOGERR("XRR: Failed to retrieve screen resources. ");
+				return;
+			}
+
+			XRROutputInfo* outputInfo = XRRGetOutputInfo(display, screenRes, outputID);
+			if (outputInfo == nullptr)
+			{
+				XRRFreeScreenResources(screenRes);
+
+				LOGERR("XRR: Failed to retrieve output info for output: " + toString((UINT32)outputID));
+				return;
+			}
+
+			XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(display, screenRes, outputInfo->crtc);
+			if (crtcInfo == nullptr)
+			{
+				XRRFreeScreenResources(screenRes);
+				XRRFreeOutputInfo(outputInfo);
+
+				LOGERR("XRR: Failed to retrieve CRTC info for output: " + toString((UINT32)outputID));
+				return;
+			}
+
+			bool foundMode = false;
+			for (INT32 i = 0; i < screenRes->nmode; i++)
+			{
+				const XRRModeInfo& modeInfo = screenRes->modes[i];
+
+				UINT32 width, height;
+
+				if (crtcInfo->rotation & (XRANDR_ROTATION_LEFT | XRANDR_ROTATION_RIGHT))
+				{
+					width = modeInfo.height;
+					height = modeInfo.width;
+				}
+				else
+				{
+					width = modeInfo.width;
+					height = modeInfo.height;
+				}
+
+				float refreshRate;
+				if (modeInfo.hTotal != 0 && modeInfo.vTotal != 0)
+					refreshRate = (float) (modeInfo.dotClock / (double) (modeInfo.hTotal * modeInfo.vTotal));
+				else
+					refreshRate = 0.0f;
+
+				if (width == mode.getWidth() && height == mode.getHeight())
+				{
+					modeID = modeInfo.id;
+					foundMode = true;
+
+					if (Math::approxEquals(refreshRate, mode.getRefreshRate()))
+						break;
+				}
+			}
+
+			if (!foundMode)
+			{
+				LinuxPlatform::unlockX();
+
+				LOGERR("Unable to enter fullscreen, unsupported video mode requested.");
+				return;
+			}
+
+			LinuxPlatform::unlockX();
+		}
+
+		LinuxPlatform::lockX();
+
+		setVideoMode(screen, outputID, modeID);
+		mWindow->_setFullscreen(true);
+
+		LinuxPlatform::unlockX();
+
+		RenderWindowProperties& props = mProperties;
+		props.isFullScreen = true;
+
+		props.top = 0;
+		props.left = 0;
+		props.width = mode.getWidth();
+		props.height = mode.getHeight();
+
+		_windowMovedOrResized();
+	}
+
+	void LinuxRenderWindow::setWindowed(UINT32 width, UINT32 height)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		RenderWindowProperties& props = mProperties;
+
+		if (!props.isFullScreen)
+			return;
+
+		// Restore old screen config
+		const LinuxVideoModeInfo& videoModeInfo =
+				static_cast<const LinuxVideoModeInfo&>(RenderAPI::instance().getVideoModeInfo());
+
+		UINT32 outputIdx = 0; // 0 is always primary
+		if(outputIdx >= videoModeInfo.getNumOutputs())
+		{
+			LOGERR("Invalid output device index.")
+			return;
+		}
+
+		const LinuxVideoOutputInfo& outputInfo =
+				static_cast<const LinuxVideoOutputInfo&>(videoModeInfo.getOutputInfo (outputIdx));
+
+		const LinuxVideoMode& desktopVideoMode = static_cast<const LinuxVideoMode&>(outputInfo.getDesktopVideoMode());
+
+		LinuxPlatform::lockX();
+
+		setVideoMode(outputInfo._getScreen(), outputInfo._getOutputID(), desktopVideoMode._getModeID());
+		mWindow->_setFullscreen(false);
+
+		LinuxPlatform::unlockX();
+
+		props.isFullScreen = false;
+		props.width = width;
+		props.height = height;
+
+		{
+			ScopedSpinLock lock(mLock);
+			mSyncedProperties.width = props.width;
+			mSyncedProperties.height = props.height;
+		}
+
+		bs::RenderWindowManager::instance().notifySyncDataDirty(this);
+		_windowMovedOrResized();
+	}
+
+	void LinuxRenderWindow::move(INT32 left, INT32 top)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		RenderWindowProperties& props = mProperties;
+		if (!props.isFullScreen)
+		{
+			LinuxPlatform::lockX();
+			mWindow->move(left, top);
+			LinuxPlatform::unlockX();
+
+			props.top = mWindow->getTop();
+			props.left = mWindow->getLeft();
+
+			{
+				ScopedSpinLock lock(mLock);
+				mSyncedProperties.top = props.top;
+				mSyncedProperties.left = props.left;
+			}
+
+			bs::RenderWindowManager::instance().notifySyncDataDirty(this);
+		}
+	}
+
+	void LinuxRenderWindow::resize(UINT32 width, UINT32 height)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		RenderWindowProperties& props = mProperties;
+		if (!props.isFullScreen)
+		{
+			LinuxPlatform::lockX();
+			mWindow->resize(width, height);
+			LinuxPlatform::unlockX();
+
+			props.width = mWindow->getWidth();
+			props.height = mWindow->getHeight();
+
+			{
+				ScopedSpinLock lock(mLock);
+				mSyncedProperties.width = props.width;
+				mSyncedProperties.height = props.height;
+			}
+
+			bs::RenderWindowManager::instance().notifySyncDataDirty(this);
+		}
+	}
+
+	void LinuxRenderWindow::minimize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		LinuxPlatform::lockX();
+		mWindow->minimize();
+		LinuxPlatform::unlockX();
+	}
+
+	void LinuxRenderWindow::maximize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		LinuxPlatform::lockX();
+		mWindow->maximize();
+		LinuxPlatform::unlockX();
+	}
+
+	void LinuxRenderWindow::restore()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		LinuxPlatform::lockX();
+		mWindow->restore();
+		LinuxPlatform::unlockX();
+	}
+
+	void LinuxRenderWindow::setVSync(bool enabled, UINT32 interval)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if(!enabled)
+			interval = 0;
+
+		SPtr<VulkanDevice> presentDevice = mRenderAPI._getPresentDevice();
+		presentDevice->waitIdle();
+
+		LinuxPlatform::lockX();
+
+		mSwapChain->rebuild(presentDevice, mSurface, mProperties.width, mProperties.height, enabled, mColorFormat,
+				mColorSpace, mDesc.depthBuffer, mDepthFormat);
+
+		LinuxPlatform::unlockX();
+		
+		mProperties.vsync = enabled;
+		mProperties.vsyncInterval = interval;
+
+		{
+			ScopedSpinLock lock(mLock);
+			mSyncedProperties.vsync = enabled;
+			mSyncedProperties.vsyncInterval = interval;
+		}
+
+		bs::RenderWindowManager::instance().notifySyncDataDirty(this);		
+	}
+
+	void LinuxRenderWindow::swapBuffers(UINT32 syncMask)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (mShowOnSwap)
+			setHidden(false);
+
+		LinuxPlatform::lockX();
+
+		// Get a command buffer on which we'll submit
+		SPtr<VulkanDevice> presentDevice = mRenderAPI._getPresentDevice();
+
+		// Assuming present queue is always graphics
+		assert(presentDevice->getQueueFamily(GQT_GRAPHICS) == mPresentQueueFamily);
+
+		// Find an appropriate queue to execute on
+		VulkanQueue* queue = presentDevice->getQueue(GQT_GRAPHICS, 0);
+		UINT32 queueMask = presentDevice->getQueueMask(GQT_GRAPHICS, 0);
+
+		// Ignore myself
+		syncMask &= ~queueMask;
+
+		UINT32 deviceIdx = presentDevice->getIndex();
+		VulkanCommandBufferManager& cbm = static_cast<VulkanCommandBufferManager&>(CommandBufferManager::instance());
+
+		UINT32 numSemaphores;
+		cbm.getSyncSemaphores(deviceIdx, syncMask, mSemaphoresTemp, numSemaphores);
+
+		// Wait on present (i.e. until the back buffer becomes available), if we haven't already done so
+		const SwapChainSurface& surface = mSwapChain->getBackBuffer();
+		if(surface.needsWait)
+		{
+			mSemaphoresTemp[numSemaphores] = mSwapChain->getBackBuffer().sync;
+			numSemaphores++;
+
+			mSwapChain->notifyBackBufferWaitIssued();
+		}
+
+		queue->present(mSwapChain.get(), mSemaphoresTemp, numSemaphores);
+		mRequiresNewBackBuffer = true;
+
+		LinuxPlatform::unlockX();
+	}
+
+	void LinuxRenderWindow::copyToMemory(PixelData &dst, FrameBuffer buffer)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		assert(false && "Not implemented");
+	}
+
+	void LinuxRenderWindow::getCustomAttribute(const String& name, void* data) const
+	{
+		if (name == "FB")
+		{
+			VulkanFramebuffer** fb = (VulkanFramebuffer**)data;
+			*fb = mSwapChain->getBackBuffer().framebuffer;
+			return;
+		}
+
+		if(name == "SC")
+		{
+			VulkanSwapChain** sc = (VulkanSwapChain**)data;
+			*sc = mSwapChain.get();
+			return;
+		}
+
+		if(name == "LINUX_WINDOW")
+		{
+			LinuxWindow** window = (LinuxWindow**)data;
+			*window = mWindow;
+			return;
+		}
+
+		if(name == "WINDOW")
+		{
+			::Window* window = (::Window*)data;
+			*window = mWindow->_getXWindow();
+			return;
+		}
+	}
+
+	void LinuxRenderWindow::setActive(bool state)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		LinuxPlatform::lockX();
+
+		if(state)
+			mWindow->restore();
+		else
+			mWindow->minimize();
+
+		LinuxPlatform::unlockX();
+
+		RenderWindow::setActive(state);
+	}
+
+	void LinuxRenderWindow::setHidden(bool hidden)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if(!hidden)
+			mShowOnSwap = false;
+
+		LinuxPlatform::lockX();
+
+		if(hidden)
+			mWindow->hide();
+		else
+			mWindow->show();
+
+		LinuxPlatform::unlockX();
+
+		RenderWindow::setHidden(hidden);
+	}
+
+	void LinuxRenderWindow::_windowMovedOrResized()
+	{
+		if (!mWindow)
+			return;
+
+		RenderWindowProperties& props = mProperties;
+		if (!props.isFullScreen) // Fullscreen is handled directly by this object
+		{
+			props.top = mWindow->getTop();
+			props.left = mWindow->getLeft();
+			props.width = mWindow->getWidth();
+			props.height = mWindow->getHeight();
+		}
+
+		// Resize swap chain
+
+		//// Need to make sure nothing is using the swap buffer before we re-create it
+		// Note: Optionally I can detect exactly on which queues (if any) are the swap chain images used on, and only wait
+		// on those
+		SPtr<VulkanDevice> presentDevice = mRenderAPI._getPresentDevice();
+		presentDevice->waitIdle();
+
+		LinuxPlatform::lockX();
+		mSwapChain->rebuild(presentDevice, mSurface, props.width, props.height, props.vsync, mColorFormat, mColorSpace,
+				mDesc.depthBuffer, mDepthFormat);
+		LinuxPlatform::unlockX();
+
+		RenderWindow::_windowMovedOrResized();
+	}
+
+	void LinuxRenderWindow::syncProperties()
+	{
+		ScopedSpinLock lock(mLock);
+		mProperties = mSyncedProperties;
+	}
+}}
+

+ 172 - 0
Source/BansheeVulkanRenderAPI/Linux/BsLinuxRenderWindow.h

@@ -0,0 +1,172 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsVulkanPrerequisites.h"
+#include "RenderAPI/BsRenderWindow.h"
+#include <X11/extensions/Xrandr.h>
+
+namespace bs
+{
+	class LinuxWindow;
+	class LinuxRenderWindow;
+
+	namespace ct
+	{
+		class LinuxRenderWindow;
+	}
+
+	/** @addtogroup Vulkan
+	 *  @{
+	 */
+
+	/**
+	 * Render window implementation for Linux.
+	 *
+	 * @note	Sim thread only.
+	 */
+	class LinuxRenderWindow : public RenderWindow
+	{
+	public:
+		~LinuxRenderWindow() { }
+
+		/** @copydoc RenderWindow::getCustomAttribute */
+		void getCustomAttribute(const String& name, void* pData) const override;
+
+		/** @copydoc RenderWindow::screenToWindowPos */
+		Vector2I screenToWindowPos(const Vector2I& screenPos) const override;
+
+		/** @copydoc RenderWindow::windowToScreenPos */
+		Vector2I windowToScreenPos(const Vector2I& windowPos) const override;
+
+		/** @copydoc RenderWindow::getCore */
+		SPtr<ct::LinuxRenderWindow> getCore() const;
+
+	protected:
+		friend class VulkanRenderWindowManager;
+		friend class ct::LinuxRenderWindow;
+
+		LinuxRenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId);
+
+		/** @copydoc RenderWindow::getProperties */
+		const RenderTargetProperties& getPropertiesInternal() const override { return mProperties; }
+
+		/** @copydoc RenderWindow::syncProperties */
+		void syncProperties() override;
+
+	private:
+		RenderWindowProperties mProperties;
+	};
+
+	namespace ct
+	{
+		/**
+		 * Render window implementation for Linux.
+		 *
+		 * @note	Core thread only.
+		 */
+		class LinuxRenderWindow : public RenderWindow
+		{
+		public:
+			LinuxRenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId, VulkanRenderAPI& renderAPI);
+			~LinuxRenderWindow();
+
+			/** @copydoc RenderWindow::setFullscreen(UINT32, UINT32, float, UINT32) */
+			void setFullscreen(UINT32 width, UINT32 height, float refreshRate = 60.0f, UINT32 monitorIdx = 0) override;
+
+			/** @copydoc RenderWindow::setFullscreen(const VideoMode&) */
+			void setFullscreen(const VideoMode& videoMode) override;
+
+			/** @copydoc RenderWindow::setWindowed */
+			void setWindowed(UINT32 width, UINT32 height) override;
+
+			/** @copydoc RenderWindow::setHidden */
+			void setHidden(bool hidden) override;
+
+			/** @copydoc RenderWindow::minimize */
+			void minimize() override;
+
+			/** @copydoc RenderWindow::maximize */
+			void maximize() override;
+
+			/** @copydoc RenderWindow::restore */
+			void restore() override;
+
+			/** @copydoc RenderWindow::move */
+			void move(INT32 left, INT32 top) override;
+
+			/** @copydoc RenderWindow::resize */
+			void resize(UINT32 width, UINT32 height) override;
+
+			/** @copydoc RenderWindow::setVSync */
+			void setVSync(bool enabled, UINT32 interval = 1) override;
+
+			/**
+			 * Copies the contents of a frame buffer into the pre-allocated buffer.
+			 *
+			 * @param[out]	dst		Previously allocated buffer to read the contents into. Must be of valid size.
+			 * @param[in]	buffer	Frame buffer to read the contents from.
+			 */
+			void copyToMemory(PixelData& dst, FrameBuffer buffer);
+
+			/** Prepares the back buffer for rendering. Should be called before it is bound to the GPU. */
+			void acquireBackBuffer();
+
+			/** @copydoc RenderWindow::swapBuffers */
+			void swapBuffers(UINT32 syncMask) override;
+
+			/** @copydoc RenderWindow::getCustomAttribute */
+			void getCustomAttribute(const String& name, void* pData) const override;
+
+			/** @copydoc RenderWindow::setActive */
+			void setActive(bool state) override;
+
+			/** @copydoc RenderWindow::_windowMovedOrResized */
+			void _windowMovedOrResized() override;
+
+			/** Returns a lock that can be used for accessing synced properties. */
+			SpinLock& _getPropertiesLock() { return mLock;}
+
+			/** Returns the internal X11 window that this object wraps. */
+			LinuxWindow* _getInternal() const { return mWindow; }
+
+		protected:
+			/** Changes the video mode to the specified RandR mode on the specified output device. */
+			void setVideoMode(INT32 screen, RROutput output, RRMode mode);
+
+			/** @copydoc CoreObject::initialize */
+			void initialize() override;
+
+			/** @copydoc RenderWindow::getProperties */
+			const RenderTargetProperties& getPropertiesInternal() const override { return mProperties; }
+
+			/** @copydoc RenderWindow::getSyncedProperties */
+			RenderWindowProperties& getSyncedProperties() override { return mSyncedProperties; }
+
+			/** @copydoc RenderWindow::syncProperties */
+			void syncProperties() override;
+
+		protected:
+			friend class bs::LinuxRenderWindow;
+
+			VulkanRenderAPI& mRenderAPI;
+			VkSurfaceKHR mSurface;
+			VkColorSpaceKHR mColorSpace;
+			VkFormat mColorFormat;
+			VkFormat mDepthFormat;
+			UINT32 mPresentQueueFamily;
+			SPtr<VulkanSwapChain> mSwapChain;
+			VulkanSemaphore* mSemaphoresTemp[BS_MAX_UNIQUE_QUEUES + 1]; // +1 for present semaphore
+			bool mRequiresNewBackBuffer;
+
+			LinuxWindow* mWindow;
+			RenderWindowProperties mProperties;
+			RenderWindowProperties mSyncedProperties;
+			bool mIsChild;
+			bool mShowOnSwap;
+		};
+	}
+
+	/** @} */
+}
+

+ 182 - 0
Source/BansheeVulkanRenderAPI/Linux/BsLinuxVideoModeInfo.cpp

@@ -0,0 +1,182 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "Linux/BsLinuxVideoModeInfo.h"
+#include "Linux/BsLinuxPlatform.h"
+#include <X11/extensions/Xrandr.h>
+
+#define XRANDR_ROTATION_LEFT    (1 << 1)
+#define XRANDR_ROTATION_RIGHT   (1 << 3)
+
+namespace bs { namespace ct
+{
+	LinuxVideoModeInfo::LinuxVideoModeInfo()
+	{
+		LinuxPlatform::lockX();
+
+		::Display* display = LinuxPlatform::getXDisplay();
+
+		INT32 minor, major;
+		XRRQueryVersion(display, &minor, &major);
+
+		INT32 defaultScreen = XDefaultScreen(display);
+		RROutput primaryOutput = XRRGetOutputPrimary(display, RootWindow(display, defaultScreen));
+
+		INT32 screenCount = XScreenCount(display);
+		for(INT32 i = 0; i < screenCount; i++)
+		{
+			XRRScreenResources* screenRes = XRRGetScreenResources(display, RootWindow(display, i));
+
+			for(INT32 j = 0; j < screenRes->noutput; j++)
+			{
+				XRROutputInfo* outputInfo = XRRGetOutputInfo(display, screenRes, screenRes->outputs[j]);
+
+				if(outputInfo == nullptr || outputInfo->crtc == 0 || outputInfo->connection == RR_Disconnected)
+				{
+					XRRFreeOutputInfo(outputInfo);
+					continue;
+				}
+
+				XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(display, screenRes, outputInfo->crtc);
+				if(crtcInfo == nullptr)
+				{
+					XRRFreeCrtcInfo(crtcInfo);
+					XRRFreeOutputInfo(outputInfo);
+					continue;
+				}
+
+				VideoOutputInfo* output = bs_new<LinuxVideoOutputInfo>(display, i, outputInfo, crtcInfo, screenRes,
+						screenRes->outputs[j], (UINT32)mOutputs.size());
+
+				// Make sure the primary output is the first in the output list
+				if(i == defaultScreen && screenRes->outputs[j] == primaryOutput)
+					mOutputs.insert(mOutputs.begin(), output);
+				else
+					mOutputs.push_back(output);
+
+				XRRFreeCrtcInfo(crtcInfo);
+				XRRFreeOutputInfo(outputInfo);
+			}
+
+			XRRFreeScreenResources(screenRes);
+		}
+
+		LinuxPlatform::unlockX();
+	}
+
+	LinuxVideoOutputInfo::LinuxVideoOutputInfo(::Display* x11Display, INT32 screen, XRROutputInfo* outputInfo,
+		XRRCrtcInfo* crtcInfo, XRRScreenResources* screenRes, RROutput outputID, UINT32 outputIdx)
+			: mOutputID(outputID), mScreen(screen)
+	{
+		RRMode currentMode = crtcInfo->mode;
+
+		// Parse output name
+		Atom EDID = XInternAtom(x11Display, "EDID", False);
+
+		INT32 numOutputProps;
+		Atom* outputProps = XRRListOutputProperties(x11Display, mOutputID, &numOutputProps);
+
+		for(INT32 k = 0; k < numOutputProps; k++)
+		{
+			if(outputProps[k] != EDID)
+				continue;
+
+			Atom actualType;
+			unsigned long numItems, bytesAfter;
+			INT32 actualFormat;
+			UINT8* data;
+
+			Status status = XRRGetOutputProperty(x11Display, mOutputID, outputProps[k], 0, 100, False,
+					False, AnyPropertyType, &actualType, &actualFormat, &numItems, &bytesAfter, &data);
+			if(status == Success)
+			{
+				// Decode EDID to get the name
+				for(UINT32 l = 0; l < 4; l++)
+				{
+					INT32 idx = 0x36 + l * 18;
+					if(data[idx] == 0 && data[idx + 1] == 0 && data[idx + 3] == 0xFC)
+					{
+						UINT8* nameSrc = &data[idx + 5];
+
+						char name[13];
+						for(UINT32 m = 0; m < 13; m++)
+						{
+							if(nameSrc[m] == 0x0a)
+							{
+								name[m] = '\0';
+								break;
+							}
+							else if(nameSrc[m] == 0x00)
+								name[m] = ' ';
+							else
+								name[m] = nameSrc[m];
+						}
+
+						mName = String(name);
+					}
+				}
+
+				continue;
+			}
+
+			XFree(data);
+			break;
+		}
+
+		XFree(outputProps);
+
+		// Use the output name if display name cannot be found
+		if(mName.empty())
+			mName = outputInfo->name;
+
+		// Enumerate all valid resolutions
+		for(INT32 k = 0; k < screenRes->nmode; k++)
+		{
+			const XRRModeInfo& modeInfo = screenRes->modes[k];
+
+			UINT32 width, height;
+
+			if(crtcInfo->rotation & (XRANDR_ROTATION_LEFT | XRANDR_ROTATION_RIGHT))
+			{
+				width = modeInfo.height;
+				height = modeInfo.width;
+			}
+			else
+			{
+				width = modeInfo.width;
+				height = modeInfo.height;
+			}
+
+			float refreshRate;
+			if(modeInfo.hTotal != 0 && modeInfo.vTotal != 0)
+				refreshRate = (float)(modeInfo.dotClock / (double)(modeInfo.hTotal * modeInfo.vTotal));
+			else
+				refreshRate = 0.0f;
+
+			LinuxVideoMode* videoMode = new (bs_alloc<LinuxVideoMode>())
+					LinuxVideoMode(width, height, refreshRate, outputIdx, modeInfo.id);
+			mVideoModes.push_back(videoMode);
+		}
+
+		// Save current desktop mode
+		for(INT32 k = 0; k < screenRes->nmode; k++)
+		{
+			if(screenRes->modes[k].id == currentMode)
+			{
+				mDesktopVideoMode = new (bs_alloc<LinuxVideoMode>())
+						LinuxVideoMode(mVideoModes[k]->getWidth(), mVideoModes[k]->getHeight(),
+						mVideoModes[k]->getRefreshRate(), mVideoModes[k]->getOutputIdx(), currentMode);
+				break;
+			}
+		}
+	}
+
+	LinuxVideoMode::LinuxVideoMode(UINT32 width, UINT32 height, float refreshRate, UINT32 outputIdx)
+		:VideoMode(width, height, refreshRate, outputIdx), mModeID((RRMode)-1)
+	{ }
+
+	LinuxVideoMode::LinuxVideoMode(UINT32 width, UINT32 height, float refreshRate, UINT32 outputIdx, RRMode modeID)
+		:VideoMode(width, height, refreshRate, outputIdx), mModeID(modeID)
+	{
+		mIsCustom = false;
+	}
+}}

+ 57 - 0
Source/BansheeVulkanRenderAPI/Linux/BsLinuxVideoModeInfo.h

@@ -0,0 +1,57 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsVulkanPrerequisites.h"
+#include "RenderAPI/BsVideoModeInfo.h"
+#include <X11/extensions/Xrandr.h>
+
+namespace bs::ct
+{
+	/** @addtogroup Vulkan
+	 *  @{
+	 */
+
+	/** @copydoc VideoMode */
+	class LinuxVideoMode : public VideoMode
+	{
+	public:
+		LinuxVideoMode(UINT32 width, UINT32 height, float refreshRate, UINT32 outputIdx);
+
+		/** Returns internal RandR video mode id. */
+		RRMode _getModeID() const { return mModeID; }
+
+	private:
+		LinuxVideoMode(UINT32 width, UINT32 height, float refreshRate, UINT32 outputIdx, RRMode modeID);
+		friend class LinuxVideoOutputInfo;
+
+		RRMode mModeID;
+	};
+
+	/** @copydoc VideoOutputInfo */
+	class LinuxVideoOutputInfo : public VideoOutputInfo
+	{
+	public:
+		LinuxVideoOutputInfo(::Display* x11Display, INT32 screen, XRROutputInfo* outputInfo, XRRCrtcInfo* crtcInfo,
+			 XRRScreenResources* screenRes, RROutput outputID, UINT32 outputIdx);
+
+		/** Returns internal RandR output device id. */
+		RROutput _getOutputID() const { return mOutputID; }
+
+		/** Returns X11 screen this output renders to. One screen can contain multiple output devices. */
+		INT32 _getScreen() const { return mScreen;}
+	private:
+		RROutput mOutputID;
+		INT32 mScreen;
+	};
+
+	/** @copydoc VideoModeInfo */
+	class LinuxVideoModeInfo : public VideoModeInfo
+	{
+	public:
+		LinuxVideoModeInfo();
+	};
+
+	/** @} */
+}
+

+ 2 - 2
Source/BansheeVulkanRenderAPI/Managers/BsVulkanCommandBufferManager.cpp

@@ -10,11 +10,11 @@
 namespace bs { namespace ct
 {
 	VulkanTransferBuffer::VulkanTransferBuffer()
-		:mDevice(nullptr), mType(GQT_GRAPHICS), mQueueIdx(0), mQueue(nullptr), mCB(nullptr), mSyncMask(0), mQueueMask(0)
+		:mDevice(nullptr), mType(GQT_GRAPHICS), mQueueIdx(0), mQueue(nullptr), mQueueMask(0), mCB(nullptr), mSyncMask(0)
 	{ }
 
 	VulkanTransferBuffer::VulkanTransferBuffer(VulkanDevice* device, GpuQueueType type, UINT32 queueIdx)
-		:mDevice(device), mType(type), mQueueIdx(queueIdx), mQueue(nullptr), mCB(nullptr), mSyncMask(0), mQueueMask(0)
+		:mDevice(device), mType(type), mQueueIdx(queueIdx), mQueue(nullptr), mQueueMask(0), mCB(nullptr), mSyncMask(0)
 	{
 		UINT32 numQueues = device->getNumQueues(mType);
 		if (numQueues == 0)

+ 2 - 2
Source/BansheeVulkanRenderAPI/Managers/BsVulkanDescriptorManager.cpp

@@ -10,7 +10,7 @@
 namespace bs { namespace ct
 {
 	VulkanLayoutKey::VulkanLayoutKey(VkDescriptorSetLayoutBinding* bindings, UINT32 numBindings)
-		:bindings(bindings), numBindings(numBindings), layout(nullptr)
+		:numBindings(numBindings), bindings(bindings), layout(nullptr)
 	{ }
 
 	bool VulkanLayoutKey::operator==(const VulkanLayoutKey& rhs) const
@@ -41,7 +41,7 @@ namespace bs { namespace ct
 	}
 
 	VulkanPipelineLayoutKey::VulkanPipelineLayoutKey(VulkanDescriptorLayout** layouts, UINT32 numLayouts)
-		:layouts(layouts), numLayouts(numLayouts)
+		:numLayouts(numLayouts), layouts(layouts)
 	{
 		
 	}

+ 1 - 1
Source/BansheeVulkanRenderAPI/Managers/BsVulkanHardwareBufferManager.cpp

@@ -7,7 +7,7 @@
 #include "BsVulkanGpuParamBlockBuffer.h"
 #include "BsVulkanGpuParams.h"
 #include "BsVulkanHardwareBuffer.h"
-#include "Renderapi/BsGpuParamDesc.h"
+#include "RenderAPI/BsGpuParamDesc.h"
 
 namespace bs { namespace ct
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/Managers/BsVulkanRenderAPIFactory.cpp

@@ -1,7 +1,7 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "Managers/BsVulkanRenderAPIFactory.h"
-#include "Renderapi/BsRenderAPI.h"
+#include "RenderAPI/BsRenderAPI.h"
 
 namespace bs { namespace ct
 {

+ 17 - 2
Source/BansheeVulkanRenderAPI/Managers/BsVulkanRenderWindowManager.cpp

@@ -1,7 +1,12 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "Managers/BsVulkanRenderWindowManager.h"
+
+#if BS_PLATFORM == BS_PLATFORM_WIN32
 #include "Win32/BsWin32RenderWindow.h"
+#elif BS_PLATFORM == BS_PLATFORM_LINUX
+#include "Linux/BsLinuxRenderWindow.h"
+#endif
 
 namespace bs 
 {
@@ -18,8 +23,13 @@ namespace bs
 		}
 
 		// Create the window
+#if BS_PLATFORM == BS_PLATFORM_WIN32
 		Win32RenderWindow* renderWindow = new (bs_alloc<Win32RenderWindow>()) Win32RenderWindow(desc, windowId);
 		return bs_core_ptr<Win32RenderWindow>(renderWindow);
+#elif BS_PLATFORM == BS_PLATFORM_LINUX
+		LinuxRenderWindow* renderWindow = new (bs_alloc<LinuxRenderWindow>()) LinuxRenderWindow(desc, windowId);
+		return bs_core_ptr<LinuxRenderWindow>(renderWindow);
+#endif
 	}
 
 	namespace ct
@@ -31,12 +41,17 @@ namespace bs
 	SPtr<RenderWindow> VulkanRenderWindowManager::createInternal(RENDER_WINDOW_DESC& desc, UINT32 windowId)
 	{
 		// Create the window
+#if BS_PLATFORM == BS_PLATFORM_WIN32
 		Win32RenderWindow* renderWindow =
 			new (bs_alloc<Win32RenderWindow>()) Win32RenderWindow(desc, windowId, mRenderAPI);
-
 		SPtr<Win32RenderWindow> renderWindowPtr = bs_shared_ptr<Win32RenderWindow>(renderWindow);
-		renderWindowPtr->_setThisPtr(renderWindowPtr);
+#elif BS_PLATFORM == BS_PLATFORM_LINUX
+		LinuxRenderWindow* renderWindow =
+				new (bs_alloc<LinuxRenderWindow>()) LinuxRenderWindow(desc, windowId, mRenderAPI);
+		SPtr<LinuxRenderWindow> renderWindowPtr = bs_shared_ptr<LinuxRenderWindow>(renderWindow);
+#endif
 
+		renderWindowPtr->_setThisPtr(renderWindowPtr);
 		windowCreated(renderWindow);
 
 		return renderWindowPtr;

+ 2 - 0
Source/BansheeVulkanRenderAPI/Managers/BsVulkanTextureManager.cpp

@@ -125,6 +125,8 @@ namespace bs
 		case GPOT_RWTEXTURE1DARRAY:
 			texture = mDummyStorageTextures[1];
 			break;
+		default:
+			break;
 		}
 
 		return texture->getResource(deviceIdx)->getView(false);

+ 1 - 1
Source/BansheeVulkanRenderAPI/Managers/BsVulkanVertexInputManager.cpp

@@ -2,7 +2,7 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "Managers/BsVulkanVertexInputManager.h"
 #include "BsVulkanUtility.h"
-#include "Renderapi/BsVertexDeclaration.h"
+#include "RenderAPI/BsVertexDeclaration.h"
 #include "Profiling/BsRenderStats.h"
 
 namespace bs { namespace ct

+ 4 - 88
Source/BansheeVulkanRenderAPI/Win32/BsWin32RenderWindow.cpp

@@ -188,95 +188,11 @@ namespace bs
 			// which support present)
 			BS_EXCEPT(RenderingAPIException, "Cannot find a graphics queue that also supports present operations.");
 		}
-		
-		uint32_t numFormats;
-		result = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, mSurface, &numFormats, nullptr);
-		assert(result == VK_SUCCESS);
-		assert(numFormats > 0);
-
-		VkSurfaceFormatKHR* surfaceFormats = bs_stack_alloc<VkSurfaceFormatKHR>(numFormats);
-		result = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, mSurface, &numFormats, surfaceFormats);
-		assert(result == VK_SUCCESS);
-
-		// If there is no preferred format, use standard RGBA
-		if ((numFormats == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED))
-		{
-			if (mDesc.gamma)
-				mColorFormat = VK_FORMAT_R8G8B8A8_SRGB;
-			else
-				mColorFormat = VK_FORMAT_B8G8R8A8_UNORM;
-
-			mColorSpace = surfaceFormats[0].colorSpace;
-		}
-		else
-		{
-			bool foundFormat = false;
-
-			VkFormat wantedFormatsUNORM[] =
-			{
-				VK_FORMAT_R8G8B8A8_UNORM,
-				VK_FORMAT_B8G8R8A8_UNORM,
-				VK_FORMAT_A8B8G8R8_UNORM_PACK32,
-				VK_FORMAT_A8B8G8R8_UNORM_PACK32,
-				VK_FORMAT_R8G8B8_UNORM,
-				VK_FORMAT_B8G8R8_UNORM
-			};
-
-			VkFormat wantedFormatsSRGB[] = 
-			{
-				VK_FORMAT_R8G8B8A8_SRGB,
-				VK_FORMAT_B8G8R8A8_SRGB,
-				VK_FORMAT_A8B8G8R8_SRGB_PACK32,
-				VK_FORMAT_A8B8G8R8_SRGB_PACK32,
-				VK_FORMAT_R8G8B8_SRGB,
-				VK_FORMAT_B8G8R8_SRGB
-			};
-
-			UINT32 numWantedFormats;
-			VkFormat* wantedFormats;
-			if (mDesc.gamma)
-			{
-				numWantedFormats = sizeof(wantedFormatsSRGB) / sizeof(wantedFormatsSRGB[0]);
-				wantedFormats = wantedFormatsSRGB;
-			}
-			else
-			{
-				numWantedFormats = sizeof(wantedFormatsUNORM) / sizeof(wantedFormatsUNORM[0]);
-				wantedFormats = wantedFormatsUNORM;
-			}
 
-			for(UINT32 i = 0; i < numWantedFormats; i++)
-			{
-				for(UINT32 j = 0; j < numFormats; j++)
-				{
-					if(surfaceFormats[j].format == wantedFormats[i])
-					{
-						mColorFormat = surfaceFormats[j].format;
-						mColorSpace = surfaceFormats[j].colorSpace;
-
-						foundFormat = true;
-						break;
-					}
-				}
-
-				if (foundFormat)
-					break;
-			}
-
-			// If we haven't found anything, fall back to first available
-			if(!foundFormat)
-			{
-				mColorFormat = surfaceFormats[0].format;
-				mColorSpace = surfaceFormats[0].colorSpace;
-
-				if (mDesc.gamma)
-					LOGERR("Cannot find a valid sRGB format for a render window surface, falling back to a default format.");
-			}
-		}
-
-		mDepthFormat = VK_FORMAT_D24_UNORM_S8_UINT;
-		
-		bs_stack_free(surfaceFormats);
+		SurfaceFormat format = presentDevice->getSurfaceFormat(mSurface, mDesc.gamma);
+		mColorFormat = format.colorFormat;
+		mColorSpace = format.colorSpace;
+		mDepthFormat = format.depthFormat;
 
 		// Create swap chain
 		mSwapChain = bs_shared_ptr_new<VulkanSwapChain>();

+ 1 - 1
Source/BansheeVulkanRenderAPI/Win32/BsWin32RenderWindow.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsRenderWindow.h"
+#include "RenderAPI/BsRenderWindow.h"
 
 namespace bs
 {

+ 1 - 1
Source/BansheeVulkanRenderAPI/Win32/BsWin32VideoModeInfo.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
-#include "Renderapi/BsVideoModeInfo.h"
+#include "RenderAPI/BsVideoModeInfo.h"
 
 namespace bs { namespace ct
 {