BearishSun 9 лет назад
Родитель
Сommit
9d9a222d00

+ 6 - 13
Source/BansheeCore/Include/BsRenderAPI.h

@@ -506,25 +506,18 @@ namespace BansheeEngine
 		/**
 		/**
 		 * Initializes the render API system and creates a primary render window.
 		 * Initializes the render API system and creates a primary render window.
 		 *
 		 *
-		 * @note	
-		 * Although I'd like otherwise, due to the nature of some render API implementations, you cannot initialize the 
-		 * render system without a window.
-		 * @note
-		 * Sim thread.
+		 * @note Sim thread only.
 		 */
 		 */
 		SPtr<RenderWindow> initialize(const RENDER_WINDOW_DESC& primaryWindowDesc);
 		SPtr<RenderWindow> initialize(const RENDER_WINDOW_DESC& primaryWindowDesc);
 
 
-		/**
-		 * Prepares the initialization of the render API system on the core thread. After the system is prepared a render 
-		 * window can be created and initialization finalized.
-		 */
-		virtual void initializePrepare();
+		/** Initializes the render API system. Called before the primary render window is created. */
+		virtual void initialize();
 
 
 		/**
 		/**
-		 * Finalizes the initialization of the render API system on the core thread. Should be called after the primary 
-		 * render window is created.
+		 * Performs (optional) secondary initialization of the render API system. Called after the render window is 
+		 * created.
 		 */
 		 */
-		virtual void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow);
+		virtual void initializeWithWindow(const SPtr<RenderWindowCore>& primaryWindow);
 
 
 		/**
 		/**
 		 * Shuts down the render API system and cleans up all resources.
 		 * Shuts down the render API system and cleans up all resources.

+ 1 - 1
Source/BansheeCore/Include/BsRenderStateManager.h

@@ -155,7 +155,7 @@ namespace BansheeEngine
 		SPtr<BlendStateCore> _createBlendState(const BLEND_STATE_DESC& desc) const;
 		SPtr<BlendStateCore> _createBlendState(const BLEND_STATE_DESC& desc) const;
 
 
 		/**	Creates an uninitialized GpuPipelineState. Requires manual initialization after creation. */
 		/**	Creates an uninitialized GpuPipelineState. Requires manual initialization after creation. */
-		SPtr<GpuPipelineStateCore> _createPipelineState(const PIPELINE_STATE_CORE_DESC& desc, 
+		virtual SPtr<GpuPipelineStateCore> _createPipelineState(const PIPELINE_STATE_CORE_DESC& desc, 
 			GpuDeviceFlags deviceMask = GDF_DEFAULT) const;
 			GpuDeviceFlags deviceMask = GDF_DEFAULT) const;
 
 
 		/** Gets a sampler state initialized with default options. */
 		/** Gets a sampler state initialized with default options. */

+ 4 - 4
Source/BansheeCore/Source/BsRenderAPI.cpp

@@ -169,22 +169,22 @@ namespace BansheeEngine
 
 
 	SPtr<RenderWindow> RenderAPICore::initialize(const RENDER_WINDOW_DESC& primaryWindowDesc)
 	SPtr<RenderWindow> RenderAPICore::initialize(const RENDER_WINDOW_DESC& primaryWindowDesc)
 	{
 	{
-		gCoreThread().queueCommand(std::bind(&RenderAPICore::initializePrepare, this), true);
+		gCoreThread().queueCommand(std::bind((void(RenderAPICore::*)())&RenderAPICore::initialize, this), true);
 
 
 		RENDER_WINDOW_DESC windowDesc = primaryWindowDesc;
 		RENDER_WINDOW_DESC windowDesc = primaryWindowDesc;
 		SPtr<RenderWindow> renderWindow = RenderWindow::create(windowDesc, nullptr);
 		SPtr<RenderWindow> renderWindow = RenderWindow::create(windowDesc, nullptr);
 
 
-		gCoreThread().queueCommand(std::bind(&RenderAPICore::initializeFinalize, this, renderWindow->getCore()), true);
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::initializeWithWindow, this, renderWindow->getCore()), true);
 
 
 		return renderWindow;
 		return renderWindow;
 	}
 	}
 
 
-	void RenderAPICore::initializePrepare()
+	void RenderAPICore::initialize()
 	{
 	{
 		// Do nothing
 		// Do nothing
 	}
 	}
 
 
-	void RenderAPICore::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
+	void RenderAPICore::initializeWithWindow(const SPtr<RenderWindowCore>& primaryWindow)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 	}
 	}

+ 2 - 2
Source/BansheeCore/Source/BsTexture.cpp

@@ -304,7 +304,7 @@ namespace BansheeEngine
 		desc.type = pixelData->getDepth() > 1 ? TEX_TYPE_3D : TEX_TYPE_2D;
 		desc.type = pixelData->getDepth() > 1 ? TEX_TYPE_3D : TEX_TYPE_2D;
 		desc.width = pixelData->getWidth();
 		desc.width = pixelData->getWidth();
 		desc.height = pixelData->getHeight();
 		desc.height = pixelData->getHeight();
-		desc.depth = pixelData->getHeight();
+		desc.depth = pixelData->getDepth();
 		desc.format = pixelData->getFormat();
 		desc.format = pixelData->getFormat();
 		desc.usage = usage;
 		desc.usage = usage;
 		desc.hwGamma = hwGammaCorrection;
 		desc.hwGamma = hwGammaCorrection;
@@ -550,7 +550,7 @@ namespace BansheeEngine
 		desc.type = pixelData->getDepth() > 1 ? TEX_TYPE_3D : TEX_TYPE_2D;
 		desc.type = pixelData->getDepth() > 1 ? TEX_TYPE_3D : TEX_TYPE_2D;
 		desc.width = pixelData->getWidth();
 		desc.width = pixelData->getWidth();
 		desc.height = pixelData->getHeight();
 		desc.height = pixelData->getHeight();
-		desc.depth = pixelData->getHeight();
+		desc.depth = pixelData->getDepth();
 		desc.format = pixelData->getFormat();
 		desc.format = pixelData->getFormat();
 		desc.usage = usage;
 		desc.usage = usage;
 		desc.hwGamma = hwGammaCorrection;
 		desc.hwGamma = hwGammaCorrection;

+ 2 - 2
Source/BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h

@@ -137,10 +137,10 @@ namespace BansheeEngine
 		friend class D3D11RenderAPIFactory;
 		friend class D3D11RenderAPIFactory;
 
 
 		/** @copydoc RenderAPICore::initializePrepare */
 		/** @copydoc RenderAPICore::initializePrepare */
-		void initializePrepare() override;
+		void initialize() override;
 
 
 		/** @copydoc RenderAPICore::initializeFinalize */
 		/** @copydoc RenderAPICore::initializeFinalize */
-		void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow) override;
+		void initializeWithWindow(const SPtr<RenderWindowCore>& primaryWindow) override;
 
 
 		/** @copydoc RenderAPICore::destroyCore */
 		/** @copydoc RenderAPICore::destroyCore */
 		void destroyCore() override;
 		void destroyCore() override;

+ 4 - 4
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -57,7 +57,7 @@ namespace BansheeEngine
 		return strName;
 		return strName;
 	}
 	}
 
 
-	void D3D11RenderAPI::initializePrepare()
+	void D3D11RenderAPI::initialize()
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
@@ -132,16 +132,16 @@ namespace BansheeEngine
 
 
 		mIAManager = bs_new<D3D11InputLayoutManager>();
 		mIAManager = bs_new<D3D11InputLayoutManager>();
 
 
-		RenderAPICore::initializePrepare();
+		RenderAPICore::initialize();
 	}
 	}
 
 
-	void D3D11RenderAPI::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
+	void D3D11RenderAPI::initializeWithWindow(const SPtr<RenderWindowCore>& primaryWindow)
 	{
 	{
 		D3D11RenderUtility::startUp(mDevice);
 		D3D11RenderUtility::startUp(mDevice);
 
 
 		QueryManager::startUp<D3D11QueryManager>();
 		QueryManager::startUp<D3D11QueryManager>();
 
 
-		RenderAPICore::initializeFinalize(primaryWindow);
+		RenderAPICore::initializeWithWindow(primaryWindow);
 	}
 	}
 
 
     void D3D11RenderAPI::destroyCore()
     void D3D11RenderAPI::destroyCore()

+ 2 - 2
Source/BansheeGLRenderAPI/Include/BsGLRenderAPI.h

@@ -128,10 +128,10 @@ namespace BansheeEngine
 
 
 	protected:
 	protected:
 		/** @copydoc RenderAPICore::initializePrepare */
 		/** @copydoc RenderAPICore::initializePrepare */
-		void initializePrepare() override;
+		void initialize() override;
 
 
 		/** @copydoc RenderAPICore::initializeFinalize */
 		/** @copydoc RenderAPICore::initializeFinalize */
-		void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow) override;
+		void initializeWithWindow(const SPtr<RenderWindowCore>& primaryWindow) override;
 
 
 		/** @copydoc RenderAPICore::destroyCore */
 		/** @copydoc RenderAPICore::destroyCore */
 		void destroyCore() override;
 		void destroyCore() override;

+ 4 - 4
Source/BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -90,7 +90,7 @@ namespace BansheeEngine
 		return strName;
 		return strName;
 	}
 	}
 
 
-	void GLRenderAPI::initializePrepare()
+	void GLRenderAPI::initialize()
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
@@ -105,10 +105,10 @@ namespace BansheeEngine
 
 
 		QueryManager::startUp<GLQueryManager>();
 		QueryManager::startUp<GLQueryManager>();
 
 
-		RenderAPICore::initializePrepare();
+		RenderAPICore::initialize();
 	}
 	}
 
 
-	void GLRenderAPI::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
+	void GLRenderAPI::initializeWithWindow(const SPtr<RenderWindowCore>& primaryWindow)
 	{
 	{
 		// Get the context from the window and finish initialization
 		// Get the context from the window and finish initialization
 		SPtr<GLContext> context;
 		SPtr<GLContext> context;
@@ -147,7 +147,7 @@ namespace BansheeEngine
 
 
 		mGLInitialised = true;
 		mGLInitialised = true;
 
 
-		RenderAPICore::initializeFinalize(primaryWindow);
+		RenderAPICore::initializeWithWindow(primaryWindow);
 	}
 	}
 
 
 	void GLRenderAPI::destroyCore()
 	void GLRenderAPI::destroyCore()

+ 6 - 0
Source/BansheeVulkanRenderAPI/CMakeSources.cmake

@@ -16,6 +16,9 @@ set(BS_BANSHEEVULKANRENDERAPI_INC_NOFILTER
 	"Include/BsVulkanEventQuery.h"
 	"Include/BsVulkanEventQuery.h"
 	"Include/BsVulkanRenderAPI.h"
 	"Include/BsVulkanRenderAPI.h"
 	"Include/BsVulkanCommandBuffer.h"
 	"Include/BsVulkanCommandBuffer.h"
+	"Include/BsVulkanDevice.h"
+	"Include/BsVulkanRenderStateManager.h"
+	"Include/BsVulkanGpuPipelineState.h"
 )
 )
 
 
 set(BS_BANSHEEVULKANRENDERAPI_INC_MANAGERS
 set(BS_BANSHEEVULKANRENDERAPI_INC_MANAGERS
@@ -46,6 +49,9 @@ set(BS_BANSHEEVULKANRENDERAPI_SRC_NOFILTER
 	"Source/BsVulkanEventQuery.cpp"
 	"Source/BsVulkanEventQuery.cpp"
 	"Source/BsVulkanRenderAPI.cpp"
 	"Source/BsVulkanRenderAPI.cpp"
 	"Source/BsVulkanCommandBuffer.cpp"
 	"Source/BsVulkanCommandBuffer.cpp"
+	"Source/BsVulkanDevice.cpp"
+	"Source/BsVulkanRenderStateManager.cpp"
+	"Source/BsVulkanGpuPipelineState.cpp"
 )
 )
 
 
 set(BS_BANSHEEVULKANRENDERAPI_SRC_MANAGERS
 set(BS_BANSHEEVULKANRENDERAPI_SRC_MANAGERS

+ 77 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanDevice.h

@@ -0,0 +1,77 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsVulkanPrerequisites.h"
+#include "BsRenderAPI.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Vulkan
+	 *  @{
+	 */
+
+#define BS_MAX_VULKAN_QUEUES_PER_TYPE 4
+
+	 /** Types of GPU queues. */
+	enum VulkanQueueType
+	{
+		/**
+		 * Queue used for rendering. Allows the use of draw commands, but also all commands supported by compute
+		 * or upload buffers.
+		 */
+		VQT_GRAPHICS,
+		/** Discrete queue used for compute operations. Allows the use of dispatch and upload commands. */
+		VQT_COMPUTE,
+		/** Queue used for memory transfer operations only. No rendering or compute dispatch allowed. */
+		VQT_UPLOAD,
+		VQT_COUNT // Keep at end
+	};
+
+	/** Represents a single GPU device usable by Vulkan. */
+	class VulkanDevice
+	{
+	public:
+		VulkanDevice(VkPhysicalDevice device);
+		~VulkanDevice();
+
+		/** Returns an object describing the physical properties of the device. */
+		VkPhysicalDevice getPhysical() const { return mPhysicalDevice; }
+
+		/** Returns an object describing the logical properties of the device. */
+		VkDevice getLogical() const { return mLogicalDevice; }
+
+		/** Returns a set of properties describing the physical device. */
+		const VkPhysicalDeviceProperties& getDeviceProperties() const { return mDeviceProperties; }
+
+		/** Returns a set of features that the application can use to check if a specific feature is supported. */
+		const VkPhysicalDeviceFeatures& getDeviceFeatures() const { return mDeviceFeatures; }
+
+		/** Returns a set of properties describing the memory of the physical device. */
+		const VkPhysicalDeviceMemoryProperties& getMemoryProperties() const { return mMemoryProperties; }
+
+		/** Returns the number of queue supported on the device, per type. */
+		UINT32 getNumQueues(VulkanQueueType type) const { return (UINT32)mQueueInfos[(int)type].queues.size(); }
+
+		/** Returns queue of the specified type at the specified index. Index must be in range [0, getNumQueues()) */
+		VkQueue getQueue(VulkanQueueType type, UINT32 idx) const { return mQueueInfos[(int)type].queues[idx]; }
+	private:
+		VkPhysicalDevice mPhysicalDevice;
+		VkDevice mLogicalDevice;
+
+		VkPhysicalDeviceProperties mDeviceProperties;
+		VkPhysicalDeviceFeatures mDeviceFeatures;
+		VkPhysicalDeviceMemoryProperties mMemoryProperties;
+
+		/** Contains data about a set of queues of a specific type. */
+		struct QueueInfo
+		{
+			UINT32 familyIdx;
+			Vector<VkQueue> queues;
+		};
+
+		QueueInfo mQueueInfos[VQT_COUNT];
+	};
+
+	/** @} */
+}

+ 27 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanGpuPipelineState.h

@@ -0,0 +1,27 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsVulkanPrerequisites.h"
+#include "BsGpuPipelineState.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Vulkan
+	 *  @{
+	 */
+
+	/**	Vulkan implementation of a GPU pipeline state. */
+	class VulkanGpuPipelineStateCore : public GpuPipelineStateCore
+	{
+	public:
+		~VulkanGpuPipelineStateCore();
+
+	protected:
+		friend class VulkanRenderStateCoreManager;
+
+		VulkanGpuPipelineStateCore(const PIPELINE_STATE_CORE_DESC& desc, GpuDeviceFlags deviceMask);
+	};
+
+	/** @} */
+}

+ 14 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanPrerequisites.h

@@ -9,6 +9,10 @@
 #	define NOMINMAX // Required to stop windows.h messing up std::min
 #	define NOMINMAX // Required to stop windows.h messing up std::min
 #endif
 #endif
 
 
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+	#define VK_USE_PLATFORM_WIN32_KHR
+#endif
+
 #include "vulkan/vulkan.h"
 #include "vulkan/vulkan.h"
 
 
 /** @addtogroup Plugins
 /** @addtogroup Plugins
@@ -30,4 +34,14 @@ namespace BansheeEngine
 	class VulkanIndexBuffer;
 	class VulkanIndexBuffer;
 	class VulkanVertexDeclaration;
 	class VulkanVertexDeclaration;
 	class VulkanHardwareBuffer;
 	class VulkanHardwareBuffer;
+	class VulkanDevice;
+	class VulkanGLSLProgramFactory;
+
+	VkAllocationCallbacks* gVulkanAllocator = nullptr;
+
+	/**	Vulkan specific types to track resource statistics for. */
+	enum VulkanRenderStatResourceType
+	{
+		RenderStatObject_PipelineState = 100,
+	};
 }
 }

+ 29 - 4
Source/BansheeVulkanRenderAPI/Include/BsVulkanRenderAPI.h

@@ -111,19 +111,44 @@ namespace BansheeEngine
 		/** @copydoc RenderAPICore::generateParamBlockDesc() */
 		/** @copydoc RenderAPICore::generateParamBlockDesc() */
 		GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) override;
 		GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) override;
 
 
+		/**
+		 * @name Internal
+		 * @{
+		 */
+
+		/** Returns a Vulkan device at the specified index. Must be in range [0, _getNumDevices()) */
+		SPtr<VulkanDevice> _getDevice(UINT32 idx) const { return mDevices[idx]; }
+
+		/** Gets the total number of Vulkan compatible devices available on this system. */
+		UINT32 _getNumDevices() const { return (UINT32)mDevices.size(); }
+
+		/** 
+		 * Returns one or multiple devices recognized as primary. This will be a single device in most cases, or multiple
+		 * devices if using some kind of a supported multi-GPU setup.
+		 */
+		const Vector<SPtr<VulkanDevice>> _getPrimaryDevices() const { return mPrimaryDevices; }
+
+		/** @}/
 	protected:
 	protected:
 		friend class VulkanRenderAPIFactory;
 		friend class VulkanRenderAPIFactory;
 
 
 		/** @copydoc RenderAPICore::initializePrepare */
 		/** @copydoc RenderAPICore::initializePrepare */
-		void initializePrepare() override;
-
-		/** @copydoc RenderAPICore::initializeFinalize */
-		void initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow) override;
+		void initialize() override;
 
 
 		/** @copydoc RenderAPICore::destroyCore */
 		/** @copydoc RenderAPICore::destroyCore */
 		void destroyCore() override;
 		void destroyCore() override;
 
 
 	private:
 	private:
+		VkInstance mInstance;
+
+		Vector<SPtr<VulkanDevice>> mDevices;
+		Vector<SPtr<VulkanDevice>> mPrimaryDevices;
+
+		VulkanGLSLProgramFactory* mGLSLFactory;
+
+#if BS_DEBUG_MODE
+		VkDebugReportCallbackEXT mDebugCallback;
+#endif
 	};
 	};
 
 
 	/** @} */
 	/** @} */

+ 24 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanRenderStateManager.h

@@ -0,0 +1,24 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsVulkanPrerequisites.h"
+#include "BsRenderStateManager.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Vulkan
+	 *  @{
+	 */
+
+	/**	Handles creation of Vulkan pipeline states. */
+	class VulkanRenderStateCoreManager : public RenderStateCoreManager
+	{
+	protected:
+		/** @copydoc RenderStateCoreManager::_createPipelineState */
+		SPtr<GpuPipelineStateCore> _createPipelineState(const PIPELINE_STATE_CORE_DESC& desc,
+			GpuDeviceFlags deviceMask = GDF_DEFAULT) const override;
+	};
+
+	/** @} */
+}

+ 105 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanDevice.cpp

@@ -0,0 +1,105 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsVulkanDevice.h"
+
+namespace BansheeEngine
+{
+	VulkanDevice::VulkanDevice(VkPhysicalDevice device)
+		:mPhysicalDevice(device), mLogicalDevice(nullptr), mQueueInfos{}
+	{
+		vkGetPhysicalDeviceProperties(device, &mDeviceProperties);
+		vkGetPhysicalDeviceFeatures(device, &mDeviceFeatures);
+		vkGetPhysicalDeviceMemoryProperties(device, &mMemoryProperties);
+
+		uint32_t numQueueFamilies;
+		vkGetPhysicalDeviceQueueFamilyProperties(device, &numQueueFamilies, nullptr);
+
+		Vector<VkQueueFamilyProperties> queueFamilyProperties(numQueueFamilies);
+		vkGetPhysicalDeviceQueueFamilyProperties(device, &numQueueFamilies, queueFamilyProperties.data());
+
+		// Create queues
+		const float defaultQueuePriorities[BS_MAX_VULKAN_QUEUES_PER_TYPE] = { 0.0f };
+		Vector<VkDeviceQueueCreateInfo> queueCreateInfos;
+
+		auto populateQueueInfo = [&](VulkanQueueType type, uint32_t familyIdx)
+		{
+			queueCreateInfos.push_back(VkDeviceQueueCreateInfo());
+
+			VkDeviceQueueCreateInfo& createInfo = queueCreateInfos.back();
+			createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+			createInfo.pNext = nullptr;
+			createInfo.flags = 0;
+			createInfo.queueFamilyIndex = familyIdx;
+			createInfo.queueCount = std::min(queueFamilyProperties[familyIdx].queueCount, (uint32_t)BS_MAX_VULKAN_QUEUES_PER_TYPE);
+			createInfo.pQueuePriorities = defaultQueuePriorities;
+
+			mQueueInfos[type].familyIdx = familyIdx;
+			mQueueInfos[type].queues.resize(createInfo.queueCount);
+		};
+
+		// Look for dedicated compute queues
+		for (UINT32 i = 0; i < (UINT32)queueFamilyProperties.size(); i++)
+		{
+			if ((queueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) && (queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)
+			{
+				populateQueueInfo(VQT_COMPUTE, i);
+				break;
+			}
+		}
+
+		// Look for dedicated upload queues
+		for (UINT32 i = 0; i < (UINT32)queueFamilyProperties.size(); i++)
+		{
+			if ((queueFamilyProperties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) &&
+				((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0) &&
+				((queueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0))
+			{
+				populateQueueInfo(VQT_UPLOAD, i);
+				break;
+			}
+		}
+
+		// Looks for graphics queues
+		for (UINT32 i = 0; i < (UINT32)queueFamilyProperties.size(); i++)
+		{
+			if (queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
+			{
+				populateQueueInfo(VQT_GRAPHICS, i);
+				break;
+			}
+		}
+
+		// Create logical device
+		const char* extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
+		uint32_t numExtensions = sizeof(extensions) / sizeof(extensions[0]);
+
+		VkDeviceCreateInfo deviceInfo;
+		deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+		deviceInfo.pNext = nullptr;
+		deviceInfo.flags = 0;
+		deviceInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size();
+		deviceInfo.pQueueCreateInfos = queueCreateInfos.data();
+		deviceInfo.pEnabledFeatures = &mDeviceFeatures;
+		deviceInfo.enabledExtensionCount = numExtensions;
+		deviceInfo.ppEnabledExtensionNames = extensions;
+		deviceInfo.enabledLayerCount = 0;
+		deviceInfo.ppEnabledLayerNames = nullptr;
+
+		VkResult result = vkCreateDevice(device, &deviceInfo, gVulkanAllocator, &mLogicalDevice);
+		assert(result == VK_SUCCESS);
+
+		// Retrieve queues
+		for(UINT32 i = 0; i < VQT_COUNT; i++)
+		{
+			UINT32 numQueues = (UINT32)mQueueInfos[i].queues.size();
+			for(UINT32 j = 0; j < numQueues; j++)
+				vkGetDeviceQueue(mLogicalDevice, mQueueInfos[i].familyIdx, j, &mQueueInfos[i].queues[j]);
+		}
+	}
+
+	VulkanDevice::~VulkanDevice()
+	{
+		vkDeviceWaitIdle(mLogicalDevice);
+		vkDestroyDevice(mLogicalDevice, gVulkanAllocator);
+	}
+}

+ 18 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuPipelineState.cpp

@@ -0,0 +1,18 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsVulkanGpuPipelineState.h"
+#include "BsRenderStats.h"
+
+namespace BansheeEngine
+{
+	VulkanGpuPipelineStateCore::VulkanGpuPipelineStateCore(const PIPELINE_STATE_CORE_DESC& desc, GpuDeviceFlags deviceMask)
+		:GpuPipelineStateCore(desc, deviceMask)
+	{
+		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_PipelineState);
+	}
+
+	VulkanGpuPipelineStateCore::~VulkanGpuPipelineStateCore()
+	{
+		BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_PipelineState);
+	}
+}

+ 205 - 7
Source/BansheeVulkanRenderAPI/Source/BsVulkanRenderAPI.cpp

@@ -4,10 +4,56 @@
 #include "BsCoreThread.h"
 #include "BsCoreThread.h"
 #include "BsRenderStats.h"
 #include "BsRenderStats.h"
 #include "BsGpuParamDesc.h"
 #include "BsGpuParamDesc.h"
+#include "BsVulkanDevice.h"
+#include "BsVulkanTextureManager.h"
+#include "BsVulkanRenderWindowManager.h"
+#include "BsVulkanHardwareBufferManager.h"
+#include "BsVulkanRenderStateManager.h"
+#include "BsGpuProgramManager.h"
+#include "BsVulkanQueryManager.h"
+#include "BsVulkanGLSLProgramFactory.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = nullptr;
+	PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr;
+
+	VkBool32 debugMsgCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
+		size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData)
+	{
+		StringStream message;
+
+		// Determine prefix
+		if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
+			message << "ERROR";
+
+		if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT)
+			message << "WARNING";
+
+		if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
+			message << "PERFORMANCE";
+
+		if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)
+			message << "INFO";
+
+		if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT)
+			message << "DEBUG";
+
+		message << ": [" << pLayerPrefix << "] Code " << msgCode << ": " << pMsg << std::endl;
+
+		if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
+			BS_EXCEPT(RenderingAPIException, message.str())
+		else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT || flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
+			LOGWRN(message.str())
+		else
+			LOGDBG(message.str())
+
+		// Don't abort calls that caused a validation message
+		return VK_FALSE;
+	}
+
 	VulkanRenderAPI::VulkanRenderAPI()
 	VulkanRenderAPI::VulkanRenderAPI()
+		:mInstance(nullptr), mDebugCallback(nullptr)
 	{ }
 	{ }
 
 
 	VulkanRenderAPI::~VulkanRenderAPI()
 	VulkanRenderAPI::~VulkanRenderAPI()
@@ -27,22 +73,174 @@ namespace BansheeEngine
 		return strName;
 		return strName;
 	}
 	}
 
 
-	void VulkanRenderAPI::initializePrepare()
+	void VulkanRenderAPI::initialize()
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
-		RenderAPICore::initializePrepare();
-	}
-
-	void VulkanRenderAPI::initializeFinalize(const SPtr<RenderWindowCore>& primaryWindow)
-	{
-		RenderAPICore::initializeFinalize(primaryWindow);
+		// Create instance
+		VkApplicationInfo appInfo;
+		appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+		appInfo.pNext = nullptr;
+		appInfo.pApplicationName = "Banshee3D App";
+		appInfo.applicationVersion = 1;
+		appInfo.pEngineName = "Banshee3D";
+		appInfo.engineVersion = (0 << 24) | (4 << 16) | 0;
+		appInfo.apiVersion = VK_API_VERSION_1_0;
+
+#if BS_DEBUG_MODE
+		const char* layers[] =
+		{
+			"VK_LAYER_LUNARG_standard_validation"
+		};
+
+		const char* extensions[] =
+		{
+			nullptr, /** Surface extension */
+			nullptr, /** OS specific surface extension */
+			VK_EXT_DEBUG_REPORT_EXTENSION_NAME
+		};
+#else
+		const char** layers = nullptr;
+		const char* extensions[] =
+		{
+			nullptr, /** Surface extension */
+			nullptr, /** OS specific surface extension */
+		};
+#endif
+
+		extensions[0] = VK_KHR_SURFACE_EXTENSION_NAME;
+
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+		extensions[1] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
+#elif BS_PLATFORM == BS_PLATFORM_ANDROID
+		extensions[1] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
+#else
+		extensions[1] = VK_KHR_XCB_SURFACE_EXTENSION_NAME;
+#endif
+
+		uint32_t numLayers = sizeof(layers) / sizeof(layers[0]);
+		uint32_t numExtensions = sizeof(extensions) / sizeof(extensions[0]);
+
+		VkInstanceCreateInfo instanceInfo;
+		instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+		instanceInfo.pNext = nullptr;
+		instanceInfo.flags = 0;
+		instanceInfo.pApplicationInfo = &appInfo;
+		instanceInfo.enabledLayerCount = numLayers;
+		instanceInfo.ppEnabledLayerNames = layers;
+		instanceInfo.enabledExtensionCount = numExtensions;
+		instanceInfo.ppEnabledExtensionNames = extensions;
+
+		VkResult result = vkCreateInstance(&instanceInfo, gVulkanAllocator, &mInstance);
+		assert(result == VK_SUCCESS);
+
+		// Set up debugging
+#if BS_DEBUG_MODE
+		VkDebugReportFlagsEXT debugFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | 
+			VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+
+		vkCreateDebugReportCallbackEXT = 
+			(PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(mInstance, "vkCreateDebugReportCallbackEXT");
+		vkDestroyDebugReportCallbackEXT = 
+			(PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(mInstance, "vkDestroyDebugReportCallbackEXT");
+
+		VkDebugReportCallbackCreateInfoEXT debugInfo;
+		debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+		debugInfo.pNext = nullptr;
+		debugInfo.flags = 0;
+		debugInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)debugMsgCallback;
+		debugInfo.flags = debugFlags;
+
+		result = vkCreateDebugReportCallbackEXT(mInstance, &debugInfo, nullptr, &mDebugCallback);
+		assert(result == VK_SUCCESS);
+#endif
+
+		// Enumerate all devices
+		uint32_t numDevices;
+
+		result = vkEnumeratePhysicalDevices(mInstance, &numDevices, nullptr);
+		assert(result == VK_SUCCESS);
+
+		Vector<VkPhysicalDevice> physicalDevices(numDevices);
+		result = vkEnumeratePhysicalDevices(mInstance, &numDevices, physicalDevices.data());
+		assert(result == VK_SUCCESS);
+
+		mDevices.resize(numDevices);
+		for(uint32_t i = 0; i < numDevices; i++)
+			mDevices[i] = bs_shared_ptr_new<VulkanDevice>(physicalDevices[i]);
+
+		// Find primary device
+		// TODO MULTIGPU - Detect multiple similar devices here if supporting multi-GPU
+		for (uint32_t i = 0; i < numDevices; i++)
+		{
+			if (mDevices[i]->getDeviceProperties().deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
+			{
+				mPrimaryDevices.push_back(mDevices[i]);
+				break;
+			}
+		}
+
+		if (mPrimaryDevices.size() == 0)
+			mPrimaryDevices.push_back(mDevices[0]);
+
+		// Create the texture manager for use by others		
+		TextureManager::startUp<VulkanTextureManager>();
+		TextureCoreManager::startUp<VulkanTextureCoreManager>();
+
+		// Create hardware buffer manager		
+		HardwareBufferManager::startUp();
+		HardwareBufferCoreManager::startUp<VulkanHardwareBufferCoreManager>();
+
+		// Create render window manager
+		RenderWindowManager::startUp<VulkanRenderWindowManager>();
+		RenderWindowCoreManager::startUp<VulkanRenderWindowCoreManager>();
+
+		// Create query manager 
+		QueryManager::startUp<VulkanQueryManager>();
+
+		// Create & register HLSL factory		
+		mGLSLFactory = bs_new<VulkanGLSLProgramFactory>();
+
+		// Create render state manager
+		RenderStateCoreManager::startUp<VulkanRenderStateCoreManager>();
+		GpuProgramCoreManager::instance().addFactory(mGLSLFactory);
+
+		// TODO - Create and populate VideoModeInfo
+		// TODO - Create and populate capabilities, per device
+		mCurrentCapabilities->addShaderProfile("glsl");
+
+		RenderAPICore::initialize();
 	}
 	}
 
 
     void VulkanRenderAPI::destroyCore()
     void VulkanRenderAPI::destroyCore()
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
+		if (mGLSLFactory != nullptr)
+		{
+			bs_delete(mGLSLFactory);
+			mGLSLFactory = nullptr;
+		}
+
+		QueryManager::shutDown();
+		RenderStateCoreManager::shutDown();
+		RenderWindowCoreManager::shutDown();
+		RenderWindowManager::shutDown();
+		HardwareBufferCoreManager::shutDown();
+		HardwareBufferManager::shutDown();
+		TextureCoreManager::shutDown();
+		TextureManager::shutDown();
+
+		mPrimaryDevices.clear();
+		mDevices.clear();
+
+#if BS_DEBUG_MODE
+		if (mDebugCallback != nullptr)
+			vkDestroyDebugReportCallbackEXT(mInstance, mDebugCallback, gVulkanAllocator);
+#endif
+
+		vkDestroyInstance(mInstance, gVulkanAllocator);
+
 		RenderAPICore::destroyCore();
 		RenderAPICore::destroyCore();
 	}
 	}
 
 

+ 17 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanRenderStateManager.cpp

@@ -0,0 +1,17 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsVulkanRenderStateManager.h"
+#include "BsVulkanGpuPipelineState.h"
+
+namespace BansheeEngine
+{
+	SPtr<GpuPipelineStateCore> VulkanRenderStateCoreManager::_createPipelineState(const PIPELINE_STATE_CORE_DESC& desc,
+		GpuDeviceFlags deviceMask) const
+	{
+		SPtr<VulkanGpuPipelineStateCore> pipelineState =
+			bs_shared_ptr<VulkanGpuPipelineStateCore>(new (bs_alloc<VulkanGpuPipelineStateCore>()) VulkanGpuPipelineStateCore(desc, deviceMask));
+		pipelineState->_setThisPtr(pipelineState);
+
+		return pipelineState;
+	}
+}

+ 2 - 0
Source/CMakeLists.txt

@@ -101,12 +101,14 @@ if(MSVC)
 	
 	
 elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
 elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
 	# Note: Optionally add -ffunction-sections, -fdata-sections, but with linker option --gc-sections
 	# Note: Optionally add -ffunction-sections, -fdata-sections, but with linker option --gc-sections
+	# TODO: Use link-time optimization -flto. Might require non-default linker.
 	set(BS_COMPILER_FLAGS_COMMON "-fpic -fno-exceptions -fno-strict-aliasing -fno-rtti -fno-ms-compatibility -fms-extensions")
 	set(BS_COMPILER_FLAGS_COMMON "-fpic -fno-exceptions -fno-strict-aliasing -fno-rtti -fno-ms-compatibility -fms-extensions")
 	
 	
 	set(CMAKE_CXX_FLAGS_DEBUG "${BS_COMPILER_FLAGS_COMMON} -g -O0")
 	set(CMAKE_CXX_FLAGS_DEBUG "${BS_COMPILER_FLAGS_COMMON} -g -O0")
 	set(CMAKE_CXX_FLAGS_OPTIMIZEDDEBUG "${BS_COMPILER_FLAGS_COMMON} -gline-tables-only -O2")
 	set(CMAKE_CXX_FLAGS_OPTIMIZEDDEBUG "${BS_COMPILER_FLAGS_COMMON} -gline-tables-only -O2")
 	set(CMAKE_CXX_FLAGS_RELEASE "${BS_COMPILER_FLAGS_COMMON} -g0 -O2")
 	set(CMAKE_CXX_FLAGS_RELEASE "${BS_COMPILER_FLAGS_COMMON} -g0 -O2")
 elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
 elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+	# TODO: Use link-time optimization -flto. Might require non-default linker.
 	set(BS_COMPILER_FLAGS_COMMON "-fpic -fno-exceptions -fno-strict-aliasing -fno-rtti")
 	set(BS_COMPILER_FLAGS_COMMON "-fpic -fno-exceptions -fno-strict-aliasing -fno-rtti")
 	
 	
 	set(CMAKE_CXX_FLAGS_DEBUG "${BS_COMPILER_FLAGS_COMMON} -g -O0")
 	set(CMAKE_CXX_FLAGS_DEBUG "${BS_COMPILER_FLAGS_COMMON} -g -O0")