Browse Source

VK: Initial commit.

Branimir Karadžić 9 years ago
parent
commit
e0b901a98a
5 changed files with 5853 additions and 17 deletions
  1. 0 5
      scripts/bgfx.lua
  2. 75 9
      scripts/shaderc.lua
  3. 4621 0
      src/renderer_vk.cpp
  4. 449 0
      src/renderer_vk.h
  5. 708 3
      tools/shaderc/shaderc_spirv.cpp

+ 0 - 5
scripts/bgfx.lua

@@ -161,11 +161,6 @@ function bgfxProject(_name, _kind, _defines)
 			path.join(BGFX_DIR, "src/**.bin.h"),
 		}
 
-		overridefiles(BGFX_DIR, path.join(BGFX_DIR, "../bgfx-ext"), {
-			path.join(BGFX_DIR, "src/renderer_vk.cpp"),
-			path.join(BGFX_DIR, "src/renderer_vk.h"),
-		})
-
 		overridefiles(BGFX_DIR, path.join(BGFX_DIR, "../bgfx-ext"), {
 			path.join(BGFX_DIR, "src/renderer_gnm.cpp"),
 			path.join(BGFX_DIR, "src/renderer_gnm.h"),

+ 75 - 9
scripts/shaderc.lua

@@ -3,8 +3,65 @@
 -- License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 --
 
+project "glslang"
+	kind "StaticLib"
+
+	buildoptions {
+		"-Wno-ignored-qualifiers",
+		"-Wno-inconsistent-missing-override",
+		"-Wno-missing-field-initializers",
+		"-Wno-reorder",
+		"-Wno-shadow",
+		"-Wno-sign-compare",
+		"-Wno-undef",
+		"-Wno-unknown-pragmas",
+		"-Wno-unused-parameter",
+		"-Wno-unused-variable",
+		"-std=c++11",
+	}
+
+	configuration { "osx" }
+		buildoptions {
+			"-Wno-c++11-extensions",
+			"-Wno-unused-const-variable",
+		}
+
+	configuration { "not osx" }
+		buildoptions {
+			"-Wno-unused-but-set-variable",
+		}
+
+	configuration {}
+
+	includedirs {
+		"../3rdparty/glslang",
+	}
+
+	files {
+		"../3rdparty/glslang/glslang/**.cpp",
+		"../3rdparty/glslang/glslang/**.h",
+
+		"../3rdparty/glslang/hlsl/**.cpp",
+		"../3rdparty/glslang/hlsl/**.h",
+
+		"../3rdparty/glslang/SPIRV/**.cpp",
+		"../3rdparty/glslang/SPIRV/**.h",
+
+		"../3rdparty/glslang/OGLCompilersDLL/**.cpp",
+		"../3rdparty/glslang/OGLCompilersDLL/**.h",
+
+		"../3rdparty/glsl-parser/**.cpp",
+		"../3rdparty/glsl-parser/**.h",
+	}
+
+	removefiles {
+		"../3rdparty/glslang/glslang/OSDependent/Windows/**.cpp",
+		"../3rdparty/glslang/glslang/OSDependent/Windows/**.h",
+
+		"../3rdparty/glsl-parser/main.cpp",
+	}
+
 project "shaderc"
-	uuid "f3cd2e90-52a4-11e1-b86c-0800200c9a66"
 	kind "ConsoleApp"
 
 	local GLSL_OPTIMIZER = path.join(BGFX_DIR, "3rdparty/glsl-optimizer")
@@ -74,6 +131,11 @@ project "shaderc"
 		path.join(BGFX_DIR, "3rdparty/dxsdk/include"),
 		FCPP_DIR,
 
+		path.join(BGFX_DIR, "3rdparty/glslang/glslang/Public"),
+		path.join(BGFX_DIR, "3rdparty/glslang/glslang/Include"),
+		path.join(BGFX_DIR, "3rdparty/glslang"),
+--		path.join(BGFX_DIR, "3rdparty/spirv-tools/include"),
+
 		path.join(GLSL_OPTIMIZER, "include"),
 		path.join(GLSL_OPTIMIZER, "src/mesa"),
 		path.join(GLSL_OPTIMIZER, "src/mapi"),
@@ -84,6 +146,7 @@ project "shaderc"
 		path.join(BGFX_DIR, "tools/shaderc/**.cpp"),
 		path.join(BGFX_DIR, "tools/shaderc/**.h"),
 		path.join(BGFX_DIR, "src/vertexdecl.**"),
+		path.join(BGFX_DIR, "src/shader_spirv.**"),
 
 		path.join(FCPP_DIR, "**.h"),
 		path.join(FCPP_DIR, "cpp1.c"),
@@ -114,6 +177,10 @@ project "shaderc"
 		path.join(GLSL_OPTIMIZER, "src/glsl/builtin_stubs.cpp"),
 	}
 
+	links {
+		"glslang",
+	}
+
 	if filesexist(BGFX_DIR, path.join(BGFX_DIR, "../bgfx-ext"), {
 		path.join(BGFX_DIR, "scripts/shaderc.lua"), }) then
 
@@ -125,15 +192,14 @@ project "shaderc"
 			}
 		end
 
-		if filesexist(BGFX_DIR, path.join(BGFX_DIR, "../bgfx-ext"), {
-			path.join(BGFX_DIR, "tools/shaderc/shaderc_spirv.cpp"), }) then
-
-			removefiles {
-				path.join(BGFX_DIR, "tools/shaderc/shaderc_spirv.cpp"),
-			}
-		end
-
 		dofile(path.join(BGFX_DIR, "../bgfx-ext/scripts/shaderc.lua") )
 	end
 
+	configuration { "osx or linux-*" }
+		links {
+			"pthread",
+		}
+
+	configuration {}
+
 	strip()

File diff suppressed because it is too large
+ 4621 - 0
src/renderer_vk.cpp


+ 449 - 0
src/renderer_vk.h

@@ -0,0 +1,449 @@
+/*
+ * Copyright 2011-2016 Branimir Karadzic. All rights reserved.
+ * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
+ */
+
+#ifndef BGFX_RENDERER_VK_H_HEADER_GUARD
+#define BGFX_RENDERER_VK_H_HEADER_GUARD
+
+#if BX_PLATFORM_ANDROID
+#	define VK_USE_PLATFORM_ANDROID_KHR
+#	define KHR_SURFACE_EXTENSION_NAME VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
+#	define VK_IMPORT_INSTANCE_PLATFORM VK_IMPORT_INSTANCE_ANDROID
+#elif BX_PLATFORM_LINUX
+//#	define VK_USE_PLATFORM_MIR_KHR
+#	define VK_USE_PLATFORM_XLIB_KHR
+#	define VK_USE_PLATFORM_XCB_KHR
+//#	define VK_USE_PLATFORM_WAYLAND_KHR
+#	define KHR_SURFACE_EXTENSION_NAME VK_KHR_XCB_SURFACE_EXTENSION_NAME
+#	define VK_IMPORT_INSTANCE_PLATFORM VK_IMPORT_INSTANCE_LINUX
+#elif BX_PLATFORM_WINDOWS
+#	define VK_USE_PLATFORM_WIN32_KHR
+#	define KHR_SURFACE_EXTENSION_NAME  VK_KHR_WIN32_SURFACE_EXTENSION_NAME
+#	define VK_IMPORT_INSTANCE_PLATFORM VK_IMPORT_INSTANCE_WINDOWS
+#else
+#	define KHR_SURFACE_EXTENSION_NAME ""
+#	define VK_IMPORT_INSTANCE_PLATFORM
+#endif // BX_PLATFORM_*
+
+#define VK_NO_STDINT_H
+#define VK_NO_PROTOTYPES
+#include <vulkan/vulkan.h>
+#include "renderer.h"
+#include "debug_renderdoc.h"
+
+#define VK_IMPORT \
+			VK_IMPORT_FUNC(false, vkCreateInstance); \
+			VK_IMPORT_FUNC(false, vkGetInstanceProcAddr); \
+			VK_IMPORT_FUNC(false, vkGetDeviceProcAddr); \
+			VK_IMPORT_FUNC(false, vkEnumerateInstanceExtensionProperties); \
+			VK_IMPORT_FUNC(false, vkEnumerateInstanceLayerProperties); \
+
+#define VK_IMPORT_INSTANCE_ANDROID \
+			VK_IMPORT_INSTANCE_FUNC(true,  vkCreateAndroidSurfaceKHR);
+
+#define VK_IMPORT_INSTANCE_LINUX \
+			VK_IMPORT_INSTANCE_FUNC(true,  vkCreateXlibSurfaceKHR); \
+			VK_IMPORT_INSTANCE_FUNC(true,  vkGetPhysicalDeviceXlibPresentationSupportKHR); \
+			VK_IMPORT_INSTANCE_FUNC(true,  vkCreateXcbSurfaceKHR); \
+			VK_IMPORT_INSTANCE_FUNC(true,  vkGetPhysicalDeviceXcbPresentationSupportKHR); \
+
+//			VK_IMPORT_INSTANCE_FUNC(true,  vkCreateWaylandSurfaceKHR);
+//			VK_IMPORT_INSTANCE_FUNC(true,  vkGetPhysicalDeviceWaylandPresentationSupportKHR);
+//			VK_IMPORT_INSTANCE_FUNC(true,  vkCreateMirSurfaceKHR);
+//			VK_IMPORT_INSTANCE_FUNC(true,  vkGetPhysicalDeviceMirPresentationSupportKHR);
+
+#define VK_IMPORT_INSTANCE_WINDOWS \
+			VK_IMPORT_INSTANCE_FUNC(true,  vkCreateWin32SurfaceKHR); \
+			VK_IMPORT_INSTANCE_FUNC(true,  vkGetPhysicalDeviceWin32PresentationSupportKHR);
+
+#define VK_IMPORT_INSTANCE \
+			VK_IMPORT_INSTANCE_FUNC(false, vkDestroyInstance); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkEnumeratePhysicalDevices); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkEnumerateDeviceExtensionProperties); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkEnumerateDeviceLayerProperties); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkGetPhysicalDeviceProperties); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkGetPhysicalDeviceFormatProperties); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkGetPhysicalDeviceImageFormatProperties); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkGetPhysicalDeviceMemoryProperties); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkGetPhysicalDeviceQueueFamilyProperties); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkGetPhysicalDeviceSurfaceCapabilitiesKHR); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkGetPhysicalDeviceSurfaceFormatsKHR); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkGetPhysicalDeviceSurfacePresentModesKHR); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkGetPhysicalDeviceSurfaceSupportKHR); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkCreateDevice); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkDestroyDevice); \
+			VK_IMPORT_INSTANCE_FUNC(false, vkDestroySurfaceKHR); \
+			/* VK_EXT_debug_report */ \
+			VK_IMPORT_INSTANCE_FUNC(true,  vkCreateDebugReportCallbackEXT); \
+			VK_IMPORT_INSTANCE_FUNC(true,  vkDestroyDebugReportCallbackEXT); \
+			VK_IMPORT_INSTANCE_FUNC(true,  vkDebugReportMessageEXT); \
+			VK_IMPORT_INSTANCE_PLATFORM
+
+#define VK_IMPORT_DEVICE \
+			VK_IMPORT_DEVICE_FUNC(false, vkGetDeviceQueue); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateSwapchainKHR); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroySwapchainKHR); \
+			VK_IMPORT_DEVICE_FUNC(false, vkGetSwapchainImagesKHR); \
+			VK_IMPORT_DEVICE_FUNC(false, vkAcquireNextImageKHR); \
+			VK_IMPORT_DEVICE_FUNC(false, vkQueuePresentKHR); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateFence); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyFence); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateSemaphore); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroySemaphore); \
+			VK_IMPORT_DEVICE_FUNC(false, vkResetFences); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateCommandPool); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyCommandPool); \
+			VK_IMPORT_DEVICE_FUNC(false, vkResetCommandPool); \
+			VK_IMPORT_DEVICE_FUNC(false, vkAllocateCommandBuffers); \
+			VK_IMPORT_DEVICE_FUNC(false, vkFreeCommandBuffers); \
+			VK_IMPORT_DEVICE_FUNC(false, vkGetBufferMemoryRequirements); \
+			VK_IMPORT_DEVICE_FUNC(false, vkGetImageMemoryRequirements); \
+			VK_IMPORT_DEVICE_FUNC(false, vkAllocateMemory); \
+			VK_IMPORT_DEVICE_FUNC(false, vkFreeMemory); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateImage); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyImage); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateImageView); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyImageView); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateBuffer); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyBuffer); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateFramebuffer); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyFramebuffer); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateRenderPass); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyRenderPass); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateShaderModule); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyShaderModule); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreatePipelineCache); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyPipelineCache); \
+			VK_IMPORT_DEVICE_FUNC(false, vkGetPipelineCacheData); \
+			VK_IMPORT_DEVICE_FUNC(false, vkMergePipelineCaches); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateGraphicsPipelines); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateComputePipelines); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyPipeline); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreatePipelineLayout); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyPipelineLayout); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateSampler); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroySampler); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateDescriptorSetLayout); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyDescriptorSetLayout); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCreateDescriptorPool); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDestroyDescriptorPool); \
+			VK_IMPORT_DEVICE_FUNC(false, vkResetDescriptorPool); \
+			VK_IMPORT_DEVICE_FUNC(false, vkAllocateDescriptorSets); \
+			VK_IMPORT_DEVICE_FUNC(false, vkFreeDescriptorSets); \
+			VK_IMPORT_DEVICE_FUNC(false, vkUpdateDescriptorSets); \
+			VK_IMPORT_DEVICE_FUNC(false, vkQueueSubmit); \
+			VK_IMPORT_DEVICE_FUNC(false, vkQueueWaitIdle); \
+			VK_IMPORT_DEVICE_FUNC(false, vkDeviceWaitIdle); \
+			VK_IMPORT_DEVICE_FUNC(false, vkWaitForFences); \
+			VK_IMPORT_DEVICE_FUNC(false, vkBeginCommandBuffer); \
+			VK_IMPORT_DEVICE_FUNC(false, vkEndCommandBuffer); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdPipelineBarrier); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdBeginRenderPass); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdEndRenderPass); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdSetViewport); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdDraw); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdDrawIndexed); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdDrawIndirect); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdDrawIndexedIndirect); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdDispatch); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdDispatchIndirect); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdBindPipeline); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdSetStencilReference); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdSetBlendConstants); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdSetScissor); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdBindDescriptorSets); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdBindIndexBuffer); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdBindVertexBuffers); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdUpdateBuffer); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdClearColorImage); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdClearDepthStencilImage); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdClearAttachments); \
+			VK_IMPORT_DEVICE_FUNC(false, vkCmdResolveImage); \
+			VK_IMPORT_DEVICE_FUNC(false, vkMapMemory); \
+			VK_IMPORT_DEVICE_FUNC(false, vkUnmapMemory); \
+			VK_IMPORT_DEVICE_FUNC(false, vkFlushMappedMemoryRanges); \
+			VK_IMPORT_DEVICE_FUNC(false, vkInvalidateMappedMemoryRanges); \
+			VK_IMPORT_DEVICE_FUNC(false, vkBindBufferMemory); \
+			VK_IMPORT_DEVICE_FUNC(false, vkBindImageMemory); \
+			/* VK_EXT_debug_marker */ \
+			VK_IMPORT_DEVICE_FUNC(true,  vkDebugMarkerSetObjectTagEXT); \
+			VK_IMPORT_DEVICE_FUNC(true,  vkDebugMarkerSetObjectNameEXT); \
+			VK_IMPORT_DEVICE_FUNC(true,  vkCmdDebugMarkerBeginEXT); \
+			VK_IMPORT_DEVICE_FUNC(true,  vkCmdDebugMarkerEndEXT); \
+			VK_IMPORT_DEVICE_FUNC(true,  vkCmdDebugMarkerInsertEXT); \
+
+#define VK_DESTROY \
+			VK_DESTROY_FUNC(Buffer); \
+			VK_DESTROY_FUNC(CommandPool); \
+			VK_DESTROY_FUNC(DescriptorPool); \
+			VK_DESTROY_FUNC(DescriptorSetLayout); \
+			VK_DESTROY_FUNC(Fence); \
+			VK_DESTROY_FUNC(Framebuffer); \
+			VK_DESTROY_FUNC(Image); \
+			VK_DESTROY_FUNC(ImageView); \
+			VK_DESTROY_FUNC(Pipeline); \
+			VK_DESTROY_FUNC(PipelineCache); \
+			VK_DESTROY_FUNC(PipelineLayout); \
+			VK_DESTROY_FUNC(RenderPass); \
+			VK_DESTROY_FUNC(Semaphore); \
+			VK_DESTROY_FUNC(ShaderModule); \
+			VK_DESTROY_FUNC(SwapchainKHR); \
+
+#define _VK_CHECK(_check, _call) \
+				BX_MACRO_BLOCK_BEGIN \
+					/*BX_TRACE(#_call);*/ \
+					VkResult vkresult = _call; \
+					_check(VK_SUCCESS == vkresult, #_call "; VK error 0x%x: %s", vkresult, getName(vkresult) ); \
+				BX_MACRO_BLOCK_END
+
+#if BGFX_CONFIG_DEBUG
+#	define VK_CHECK(_call) _VK_CHECK(BX_CHECK, _call)
+#else
+#	define VK_CHECK(_call) _call
+#endif // BGFX_CONFIG_DEBUG
+
+namespace bgfx { namespace vk
+{
+#define VK_DESTROY_FUNC(_name) \
+			struct Vk##_name \
+			{ \
+				::Vk##_name vk; \
+				Vk##_name() {} \
+				Vk##_name(::Vk##_name _vk) : vk(_vk) {} \
+				operator ::Vk##_name() { return vk; } \
+				operator ::Vk##_name() const { return vk; } \
+				::Vk##_name* operator &() { return &vk; } \
+				const ::Vk##_name* operator &() const { return &vk; } \
+			}; \
+			BX_STATIC_ASSERT(sizeof(::Vk##_name) == sizeof(Vk##_name) ); \
+			void vkDestroy(Vk##_name&)
+VK_DESTROY
+#undef VK_DESTROY_FUNC
+
+	struct DslBinding
+	{
+		enum Enum
+		{
+//			CombinedImageSampler,
+			UniformBuffer,
+//			StorageBuffer,
+
+			Count
+		};
+	};
+
+	template<typename Ty>
+	class StateCacheT
+	{
+	public:
+		void add(uint64_t _key, Ty _value)
+		{
+			invalidate(_key);
+			m_hashMap.insert(stl::make_pair(_key, _value) );
+		}
+
+		Ty find(uint64_t _key)
+		{
+			typename HashMap::iterator it = m_hashMap.find(_key);
+			if (it != m_hashMap.end() )
+			{
+				return it->second;
+			}
+
+			return 0;
+		}
+
+		void invalidate(uint64_t _key)
+		{
+			typename HashMap::iterator it = m_hashMap.find(_key);
+			if (it != m_hashMap.end() )
+			{
+				vkDestroy(it->second);
+				m_hashMap.erase(it);
+			}
+		}
+
+		void invalidate()
+		{
+			for (typename HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it)
+			{
+				vkDestroy(it->second);
+			}
+
+			m_hashMap.clear();
+		}
+
+		uint32_t getCount() const
+		{
+			return uint32_t(m_hashMap.size() );
+		}
+
+	private:
+		typedef stl::unordered_map<uint64_t, Ty> HashMap;
+		HashMap m_hashMap;
+	};
+
+	class ScratchBufferVK
+	{
+	public:
+		ScratchBufferVK()
+		{
+		}
+
+		~ScratchBufferVK()
+		{
+		}
+
+		void create(uint32_t _size, uint32_t _maxDescriptors);
+		void destroy();
+		void reset(VkDescriptorBufferInfo& _gpuAddress);
+		void* allocUbv(VkDescriptorBufferInfo& _gpuAddress, uint32_t _size);
+
+		VkDescriptorSet* m_descriptorSet;
+		VkBuffer m_buffer;
+		VkDeviceMemory m_deviceMem;
+		uint8_t* m_data;
+		uint32_t m_size;
+		uint32_t m_pos;
+		uint32_t m_currentDs;
+		uint32_t m_maxDescriptors;
+	};
+
+	struct ImageVK
+	{
+		ImageVK()
+			: m_memory(VK_NULL_HANDLE)
+			, m_image(VK_NULL_HANDLE)
+			, m_imageView(VK_NULL_HANDLE)
+		{
+		}
+
+		VkResult create(VkFormat _format, const VkExtent3D& _extent);
+		void destroy();
+
+		VkDeviceMemory m_memory;
+		VkImage        m_image;
+		VkImageView    m_imageView;
+	};
+
+	struct BufferVK
+	{
+		BufferVK()
+			: m_buffer(VK_NULL_HANDLE)
+			, m_deviceMem(VK_NULL_HANDLE)
+			, m_size(0)
+			, m_flags(BGFX_BUFFER_NONE)
+			, m_dynamic(false)
+		{
+		}
+
+		void create(uint32_t _size, void* _data, uint16_t _flags, bool _vertex, uint32_t _stride = 0);
+		void update(VkCommandBuffer _commandBuffer, uint32_t _offset, uint32_t _size, void* _data, bool _discard = false);
+		void destroy();
+
+		VkBuffer m_buffer;
+		VkDeviceMemory m_deviceMem;
+		uint32_t m_size;
+		uint16_t m_flags;
+		bool m_dynamic;
+	};
+
+	typedef BufferVK IndexBufferVK;
+
+	struct VertexBufferVK : public BufferVK
+	{
+		void create(uint32_t _size, void* _data, VertexDeclHandle _declHandle, uint16_t _flags);
+
+		VertexDeclHandle m_decl;
+	};
+
+	struct ShaderVK
+	{
+		ShaderVK()
+			: m_code(NULL)
+			, m_module(VK_NULL_HANDLE)
+			, m_constantBuffer(NULL)
+			, m_hash(0)
+			, m_numUniforms(0)
+			, m_numPredefined(0)
+		{
+		}
+
+		void create(const Memory* _mem);
+		void destroy();
+
+		const Memory* m_code;
+		VkShaderModule m_module;
+		UniformBuffer* m_constantBuffer;
+
+		PredefinedUniform m_predefined[PredefinedUniform::Count];
+		uint16_t m_attrMask[Attrib::Count];
+
+		uint32_t m_hash;
+		uint16_t m_numUniforms;
+		uint16_t m_size;
+		uint8_t m_numPredefined;
+	};
+
+	struct ProgramVK
+	{
+		ProgramVK()
+			: m_vsh(NULL)
+			, m_fsh(NULL)
+		{
+		}
+
+		void create(const ShaderVK* _vsh, const ShaderVK* _fsh)
+		{
+			BX_CHECK(NULL != _vsh->m_code, "Vertex shader doesn't exist.");
+			m_vsh = _vsh;
+			memcpy(&m_predefined[0], _vsh->m_predefined, _vsh->m_numPredefined*sizeof(PredefinedUniform));
+			m_numPredefined = _vsh->m_numPredefined;
+
+			if (NULL != _fsh)
+			{
+				BX_CHECK(NULL != _fsh->m_code, "Fragment shader doesn't exist.");
+				m_fsh = _fsh;
+				memcpy(&m_predefined[m_numPredefined], _fsh->m_predefined, _fsh->m_numPredefined*sizeof(PredefinedUniform));
+				m_numPredefined += _fsh->m_numPredefined;
+			}
+		}
+
+		void destroy()
+		{
+			m_numPredefined = 0;
+			m_vsh = NULL;
+			m_fsh = NULL;
+		}
+
+		const ShaderVK* m_vsh;
+		const ShaderVK* m_fsh;
+
+		PredefinedUniform m_predefined[PredefinedUniform::Count * 2];
+		uint8_t m_numPredefined;
+	};
+
+	struct TextureVK
+	{
+		void destroy();
+	};
+
+	struct FrameBufferVK
+	{
+		void destroy();
+
+		TextureHandle m_texture[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
+		TextureHandle m_depth;
+//		IDXGISwapChain* m_swapChain;
+		uint32_t m_width;
+		uint32_t m_height;
+		uint16_t m_denseIdx;
+		uint8_t m_num;
+		uint8_t m_numTh;
+		Attachment m_attachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
+	};
+
+} /* namespace bgfx */ } // namespace vk
+
+#endif // BGFX_RENDERER_VK_H_HEADER_GUARD

+ 708 - 3
tools/shaderc/shaderc_spirv.cpp

@@ -5,13 +5,718 @@
 
 #include "shaderc.h"
 
+#include <ShaderLang.h>
+#include <ResourceLimits.h>
+#include <SPIRV/SPVRemapper.h>
+//#include <spirv-tools/libspirv.hpp>
+//#include <spirv-tools/optimizer.hpp>
+
 namespace bgfx
 {
-	bool compileSPIRVShader(bx::CommandLine& _cmdLine, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
+	static bx::CrtAllocator s_allocator;
+	bx::AllocatorI* g_allocator = &s_allocator;
+
+	struct TinyStlAllocator
+	{
+		static void* static_allocate(size_t _bytes);
+		static void static_deallocate(void* _ptr, size_t /*_bytes*/);
+	};
+
+	void* TinyStlAllocator::static_allocate(size_t _bytes)
+	{
+		return BX_ALLOC(g_allocator, _bytes);
+	}
+
+	void TinyStlAllocator::static_deallocate(void* _ptr, size_t /*_bytes*/)
+	{
+		if (NULL != _ptr)
+		{
+			BX_FREE(g_allocator, _ptr);
+		}
+	}
+} // namespace bgfx
+
+#define TINYSTL_ALLOCATOR bgfx::TinyStlAllocator
+#include <tinystl/allocator.h>
+#include <tinystl/string.h>
+#include <tinystl/unordered_map.h>
+#include <tinystl/vector.h>
+namespace stl = tinystl;
+
+#include "../../src/shader_spirv.h"
+
+namespace glslang
+{
+	void GlslangToSpv(const glslang::TIntermediate& _intermediate, std::vector<uint32_t>& _spirv);
+
+} // namespace glslang
+
+namespace bgfx { namespace spirv
+{
+	const TBuiltInResource resourceLimits =
+	{
+		32,    // MaxLights
+		6,     // MaxClipPlanes
+		32,    // MaxTextureUnits
+		32,    // MaxTextureCoords
+		64,    // MaxVertexAttribs
+		4096,  // MaxVertexUniformComponents
+		64,    // MaxVaryingFloats
+		32,    // MaxVertexTextureImageUnits
+		80,    // MaxCombinedTextureImageUnits
+		32,    // MaxTextureImageUnits
+		4096,  // MaxFragmentUniformComponents
+		32,    // MaxDrawBuffers
+		128,   // MaxVertexUniformVectors
+		8,     // MaxVaryingVectors
+		16,    // MaxFragmentUniformVectors
+		16,    // MaxVertexOutputVectors
+		15,    // MaxFragmentInputVectors
+		-8,    // MinProgramTexelOffset
+		7,     // MaxProgramTexelOffset
+		8,     // MaxClipDistances
+		65535, // MaxComputeWorkGroupCountX
+		65535, // MaxComputeWorkGroupCountY
+		65535, // MaxComputeWorkGroupCountZ
+		1024,  // MaxComputeWorkGroupSizeX
+		1024,  // MaxComputeWorkGroupSizeY
+		64,    // MaxComputeWorkGroupSizeZ
+		1024,  // MaxComputeUniformComponents
+		16,    // MaxComputeTextureImageUnits
+		8,     // MaxComputeImageUniforms
+		8,     // MaxComputeAtomicCounters
+		1,     // MaxComputeAtomicCounterBuffers
+		60,    // MaxVaryingComponents
+		64,    // MaxVertexOutputComponents
+		64,    // MaxGeometryInputComponents
+		128,   // MaxGeometryOutputComponents
+		128,   // MaxFragmentInputComponents
+		8,     // MaxImageUnits
+		8,     // MaxCombinedImageUnitsAndFragmentOutputs
+		8,     // MaxCombinedShaderOutputResources
+		0,     // MaxImageSamples
+		0,     // MaxVertexImageUniforms
+		0,     // MaxTessControlImageUniforms
+		0,     // MaxTessEvaluationImageUniforms
+		0,     // MaxGeometryImageUniforms
+		8,     // MaxFragmentImageUniforms
+		8,     // MaxCombinedImageUniforms
+		16,    // MaxGeometryTextureImageUnits
+		256,   // MaxGeometryOutputVertices
+		1024,  // MaxGeometryTotalOutputComponents
+		1024,  // MaxGeometryUniformComponents
+		64,    // MaxGeometryVaryingComponents
+		128,   // MaxTessControlInputComponents
+		128,   // MaxTessControlOutputComponents
+		16,    // MaxTessControlTextureImageUnits
+		1024,  // MaxTessControlUniformComponents
+		4096,  // MaxTessControlTotalOutputComponents
+		128,   // MaxTessEvaluationInputComponents
+		128,   // MaxTessEvaluationOutputComponents
+		16,    // MaxTessEvaluationTextureImageUnits
+		1024,  // MaxTessEvaluationUniformComponents
+		120,   // MaxTessPatchComponents
+		32,    // MaxPatchVertices
+		64,    // MaxTessGenLevel
+		16,    // MaxViewports
+		0,     // MaxVertexAtomicCounters
+		0,     // MaxTessControlAtomicCounters
+		0,     // MaxTessEvaluationAtomicCounters
+		0,     // MaxGeometryAtomicCounters
+		8,     // MaxFragmentAtomicCounters
+		8,     // MaxCombinedAtomicCounters
+		1,     // MaxAtomicCounterBindings
+		0,     // MaxVertexAtomicCounterBuffers
+		0,     // MaxTessControlAtomicCounterBuffers
+		0,     // MaxTessEvaluationAtomicCounterBuffers
+		0,     // MaxGeometryAtomicCounterBuffers
+		1,     // MaxFragmentAtomicCounterBuffers
+		1,     // MaxCombinedAtomicCounterBuffers
+		16384, // MaxAtomicCounterBufferSize
+		4,     // MaxTransformFeedbackBuffers
+		64,    // MaxTransformFeedbackInterleavedComponents
+		8,     // MaxCullDistances
+		8,     // MaxCombinedClipAndCullDistances
+		4,     // MaxSamples
+		{      // limits
+			1, // nonInductiveForLoops
+			1, // whileLoops
+			1, // doWhileLoops
+			1, // generalUniformIndexing
+			1, // generalAttributeMatrixVectorIndexing
+			1, // generalVaryingIndexing
+			1, // generalSamplerIndexing
+			1, // generalVariableIndexing
+			1, // generalConstantMatrixVectorIndexing
+		},
+	};
+
+	bool printAsm(uint32_t _offset, const SpvInstruction& _instruction, void* _userData)
+	{
+		BX_UNUSED(_userData);
+		char temp[512];
+		toString(temp, sizeof(temp), _instruction);
+		BX_TRACE("%5d: %s", _offset, temp);
+		return true;
+	}
+
+	struct SpvReflection
+	{
+		struct TypeId
+		{
+			enum Enum
+			{
+				Void,
+				Bool,
+				Int32,
+				Int64,
+				Uint32,
+				Uint64,
+				Float,
+				Double,
+
+				Vector,
+				Matrix,
+
+				Count
+			};
+
+			TypeId()
+				: baseType(Enum::Count)
+				, type(Enum::Count)
+			{
+			}
+
+			Enum baseType;
+			Enum type;
+			uint32_t numComponents;
+
+			stl::string toString()
+			{
+				stl::string result;
+
+				switch (type)
+				{
+				case Float:
+					result.append("float");
+					break;
+
+				case Vector:
+					bx::stringPrintf(result, "vec%d"
+						, numComponents
+						);
+					break;
+
+				case Matrix:
+					bx::stringPrintf(result, "mat%d"
+						, numComponents
+						);
+
+				default:
+					break;
+				}
+
+				return result;
+			}
+		};
+
+		struct Id
+		{
+			struct Variable
+			{
+				Variable()
+					: decoration(SpvDecoration::Count)
+					, builtin(SpvBuiltin::Count)
+					, storageClass(SpvStorageClass::Count)
+					, location(UINT32_MAX)
+					, offset(UINT32_MAX)
+					, type(UINT32_MAX)
+				{
+				}
+
+				stl::string name;
+				SpvDecoration::Enum decoration;
+				SpvBuiltin::Enum builtin;
+				SpvStorageClass::Enum storageClass;
+				uint32_t location;
+				uint32_t offset;
+				uint32_t type;
+			};
+
+			typedef stl::vector<Variable> MemberArray;
+
+			Variable var;
+			MemberArray members;
+		};
+
+		typedef stl::unordered_map<uint32_t, TypeId> TypeIdMap;
+		typedef stl::unordered_map<uint32_t, Id> IdMap;
+
+		TypeIdMap typeIdMap;
+		IdMap idMap;
+
+		stl::string getTypeName(uint32_t _typeId)
+		{
+			return getTypeId(_typeId).toString();
+		}
+
+		Id& getId(uint32_t _id)
+		{
+			IdMap::iterator it = idMap.find(_id);
+			if (it == idMap.end() )
+			{
+				Id id;
+				stl::pair<IdMap::iterator, bool> result = idMap.insert(stl::make_pair(_id, id) );
+				it = result.first;
+			}
+
+			return it->second;
+		}
+
+		Id::Variable& get(uint32_t _id, uint32_t _idx)
+		{
+			Id& id = getId(_id);
+			id.members.resize(bx::uint32_max(_idx+1, uint32_t(id.members.size() ) ) );
+			return id.members[_idx];
+		}
+
+		TypeId& getTypeId(uint32_t _id)
+		{
+			TypeIdMap::iterator it = typeIdMap.find(_id);
+			if (it == typeIdMap.end() )
+			{
+				TypeId id;
+				stl::pair<TypeIdMap::iterator, bool> result = typeIdMap.insert(stl::make_pair(_id, id) );
+				it = result.first;
+			}
+
+			return it->second;
+		}
+
+		void update(uint32_t _id, const stl::string& _name)
+		{
+			getId(_id).var.name = _name;
+		}
+
+		BX_NO_INLINE void update(Id::Variable& _variable, SpvDecoration::Enum _decoration, uint32_t _literal)
+		{
+			_variable.decoration = _decoration;
+			switch (_decoration)
+			{
+			case SpvDecoration::Location:
+				_variable.location = _literal;
+				break;
+
+			case SpvDecoration::Offset:
+				_variable.offset = _literal;
+				break;
+
+			case SpvDecoration::BuiltIn:
+				_variable.builtin = SpvBuiltin::Enum(_literal);
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		BX_NO_INLINE void update(Id::Variable& _variable, uint32_t _type, SpvStorageClass::Enum _storageClass)
+		{
+			_variable.type         = _type;
+			_variable.storageClass = _storageClass;
+		}
+
+		void update(uint32_t _id, SpvDecoration::Enum _decoration, uint32_t _literal)
+		{
+			update(getId(_id).var, _decoration, _literal);
+		}
+
+		void update(uint32_t _id, uint32_t _type, SpvStorageClass::Enum _storageClass)
+		{
+			update(getId(_id).var, _type, _storageClass);
+		}
+
+		void update(uint32_t _id, uint32_t _idx, const stl::string& _name)
+		{
+			Id::Variable& var = get(_id, _idx);
+			var.name = _name;
+		}
+
+		BX_NO_INLINE void update(uint32_t _id, uint32_t _idx, SpvDecoration::Enum _decoration, uint32_t _literal)
+		{
+			update(get(_id, _idx), _decoration, _literal);
+		}
+
+		void update(uint32_t _id, TypeId::Enum _type)
+		{
+			TypeId& type = getTypeId(_id);
+			type.type = _type;
+		}
+
+		void update(uint32_t _id, TypeId::Enum _type, uint32_t _baseTypeId, uint32_t _numComonents)
+		{
+			TypeId& type = getTypeId(_id);
+			type.type = _type;
+
+			type.baseType = getTypeId(_baseTypeId).type;
+			type.numComponents = _numComonents;
+		}
+	};
+
+	bool spvParse(uint32_t _offset, const SpvInstruction& _instruction, void* _userData)
+	{
+		BX_UNUSED(_offset);
+		SpvReflection* spv = (SpvReflection*)_userData;
+
+		switch (_instruction.opcode)
+		{
+		case SpvOpcode::Name:
+			spv->update(_instruction.result
+				, _instruction.operand[0].literalString
+				);
+			break;
+
+		case SpvOpcode::Decorate:
+			spv->update(_instruction.operand[0].data
+				, SpvDecoration::Enum(_instruction.operand[1].data)
+				, _instruction.operand[2].data
+				);
+			break;
+
+		case SpvOpcode::MemberName:
+			spv->update(_instruction.result
+				, _instruction.operand[0].data
+				, _instruction.operand[1].literalString
+				);
+			break;
+
+		case SpvOpcode::MemberDecorate:
+			spv->update(_instruction.operand[0].data
+				, _instruction.operand[1].data
+				, SpvDecoration::Enum(_instruction.operand[2].data)
+				, _instruction.operand[3].data
+				);
+			break;
+
+		case SpvOpcode::Variable:
+			spv->update(_instruction.result
+				, _instruction.type
+				, SpvStorageClass::Enum(_instruction.operand[0].data)
+				);
+			break;
+
+		case SpvOpcode::TypeVoid:
+			spv->update(_instruction.result, SpvReflection::TypeId::Void);
+			break;
+
+		case SpvOpcode::TypeBool:
+			spv->update(_instruction.result, SpvReflection::TypeId::Bool);
+			break;
+
+		case SpvOpcode::TypeInt:
+			spv->update(_instruction.result
+				, 32 == _instruction.operand[0].data
+				?	0 == _instruction.operand[1].data
+					? SpvReflection::TypeId::Uint32
+					: SpvReflection::TypeId::Int32
+				:	0 == _instruction.operand[1].data
+					? SpvReflection::TypeId::Uint64
+					: SpvReflection::TypeId::Int64
+				);
+			break;
+
+		case SpvOpcode::TypeFloat:
+			spv->update(_instruction.result
+				, 32 == _instruction.operand[0].data
+				? SpvReflection::TypeId::Float
+				: SpvReflection::TypeId::Double
+				);
+			break;
+
+		case SpvOpcode::TypeVector:
+			spv->update(_instruction.result
+				, SpvReflection::TypeId::Vector
+				, _instruction.operand[0].data
+				, _instruction.operand[1].data
+				);
+			break;
+
+		case SpvOpcode::TypeMatrix:
+			spv->update(_instruction.result
+				, SpvReflection::TypeId::Matrix
+				, _instruction.operand[0].data
+				, _instruction.operand[1].data
+				);
+			break;
+
+		case SpvOpcode::TypeImage:
+		case SpvOpcode::TypeSampler:
+		case SpvOpcode::TypeSampledImage:
+			break;
+
+		case SpvOpcode::TypeStruct:
+			for (uint32_t ii = 0, num = _instruction.numOperands; ii < num; ++ii)
+			{
+				SpvReflection::Id::Variable& var = spv->get(_instruction.result, ii);
+				var.type = _instruction.operand[ii].data;
+			}
+			break;
+
+		default:
+			break;
+		}
+
+		return true;
+	}
+
+	void disassemble(bx::WriterI* _writer, bx::ReaderSeekerI* _reader, bx::Error* _err)
+	{
+		BX_UNUSED(_writer);
+
+		uint32_t magic;
+		bx::peek(_reader, magic);
+
+		SpvReflection spvx;
+
+		if (magic == SPV_CHUNK_HEADER)
+		{
+			SpirV spirv;
+			read(_reader, spirv, _err);
+			parse(spirv.shader, spvParse, &spvx, _err);
+
+			for (SpvReflection::IdMap::const_iterator it = spvx.idMap.begin(), itEnd = spvx.idMap.end(); it != itEnd; ++it)
+			{
+				const SpvReflection::Id& id = it->second;
+				uint32_t num = uint32_t(id.members.size() );
+				if (0 < num
+				&&  0 != strcmp(id.var.name.c_str(), "gl_PerVertex") )
+				{
+					printf("%3d: %s %d %s\n"
+						, it->first
+						, id.var.name.c_str()
+						, id.var.location
+						, getName(id.var.storageClass)
+						);
+					printf("{\n");
+					for (uint32_t ii = 0; ii < num; ++ii)
+					{
+						const SpvReflection::Id::Variable& var = id.members[ii];
+						printf("\t\t%s %s %d %s\n"
+							, spvx.getTypeName(var.type).c_str()
+							, var.name.c_str()
+							, var.offset
+							, getName(var.storageClass)
+							);
+					}
+					printf("}\n");
+				}
+			}
+
+		}
+	}
+
+	struct DebugOutputWriter : public bx::WriterI
+	{
+		virtual int32_t write(const void* _data, int32_t _size, bx::Error*) BX_OVERRIDE
+		{
+			char* out = (char*)alloca(_size + 1);
+			memcpy(out, _data, _size);
+			out[_size] = '\0';
+			printf("%s", out);
+			return _size;
+		}
+	};
+
+	static EShLanguage getLang(char _p)
+	{
+		switch (_p)
+		{
+		case 'c': return EShLangCompute;
+		case 'f': return EShLangFragment;
+		default:  break;
+		}
+
+		return EShLangVertex;
+	}
+
+//	static void printError(spv_message_level_t, const char*, const spv_position_t&, const char* _message)
+//	{
+//		fprintf(stderr, "%s\n", _message);
+//	}
+
+	static bool compile(bx::CommandLine& _cmdLine, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
 	{
 		BX_UNUSED(_cmdLine, _version, _code, _writer);
-		fprintf(stderr, "SPIR-V compiler is not supported.\n");
-		return false;
+
+		const char* profile = _cmdLine.findOption('p', "profile");
+		if (NULL == profile)
+		{
+			fprintf(stderr, "Error: Shader profile must be specified.\n");
+			return false;
+		}
+
+		glslang::InitializeProcess();
+
+		glslang::TProgram* program = new glslang::TProgram;
+
+		EShLanguage stage = getLang(profile[0]);
+		glslang::TShader* shader = new glslang::TShader(stage);
+
+		EShMessages messages = EShMessages(0
+			| EShMsgDefault
+			| EShMsgReadHlsl
+			| EShMsgVulkanRules
+			| EShMsgSpvRules
+			);
+
+		const char* shaderStrings[] = { _code.c_str() };
+		const char* shaderNames[]   = { "" };
+
+		shader->setStringsWithLengthsAndNames(
+			  shaderStrings
+			, NULL
+			, shaderNames
+			, BX_COUNTOF(shaderNames)
+			);
+		bool compiled = shader->parse(&resourceLimits
+			, 110
+			, false
+			, messages
+			);
+		bool linked = false;
+		bool validated = true;
+		bool optimized = true;
+
+		if (!compiled)
+		{
+			const char* log = shader->getInfoLog();
+			if (NULL != log)
+			{
+				int32_t source  = 0;
+				int32_t line    = 0;
+				int32_t column  = 0;
+				int32_t start   = 0;
+				int32_t end     = INT32_MAX;
+
+				const char* err = strstr(log, "ERROR:");
+
+				bool found = false;
+
+				if (NULL != err)
+				{
+					found = 2 == sscanf(err, "ERROR: %u:%u: '", &source, &line);
+					if (found)
+					{
+						++line;
+					}
+				}
+
+				if (found)
+				{
+					start = bx::uint32_imax(1, line-10);
+					end   = start + 20;
+				}
+
+				printCode(_code.c_str(), line, start, end, column);
+
+				fprintf(stderr, "%s\n", log);
+			}
+		}
+		else
+		{
+			program->addShader(shader);
+			linked = true
+				&& program->link(messages)
+				&& program->mapIO()
+				;
+
+			if (!linked)
+			{
+				const char* log = program->getInfoLog();
+				if (NULL != log)
+				{
+					fprintf(stderr, "%s\n", log);
+				}
+			}
+			else
+			{
+//				program->buildReflection();
+//				fprintf(stderr, "attributes %d, uniforms %d\n"
+//					, program->getNumLiveAttributes()
+//					, program->getNumLiveUniformVariables()
+//					);
+//				program->dumpReflection();
+
+				glslang::TIntermediate* intermediate = program->getIntermediate(stage);
+				std::vector<uint32_t> spirv;
+				glslang::GlslangToSpv(*intermediate, spirv);
+				spv::spirvbin_t spvBin;
+				spvBin.remap(
+					  spirv
+					, 0
+					| spv::spirvbin_t::DCE_ALL
+					| spv::spirvbin_t::OPT_ALL
+					| spv::spirvbin_t::MAP_ALL
+//					| spv::spirvbin_t::STRIP
+					);
+
+				bx::Error err;
+				DebugOutputWriter writer;
+				bx::MemoryReader reader(spirv.data(), uint32_t(spirv.size()*4) );
+				disassemble(&writer, &reader, &err);
+
+#if 0
+				spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
+				tools.SetMessageConsumer(printError);
+				validated = tools.Validate(spirv);
+
+				if (!validated)
+				{
+					std::string out;
+					tools.Disassemble(spirv, &out);
+					printf("%s\n", out.c_str());
+				}
+
+				if (validated)
+				{
+					spvtools::Optimizer optm(SPV_ENV_VULKAN_1_0);
+					optm.SetMessageConsumer(printError);
+					optm
+						.RegisterPass(spvtools::CreateStripDebugInfoPass() )
+//						.RegisterPass(spvtools::CreateSetSpecConstantDefaultValuePass({ {1, "42" } }) )
+						.RegisterPass(spvtools::CreateFreezeSpecConstantValuePass() )
+						.RegisterPass(spvtools::CreateFoldSpecConstantOpAndCompositePass() )
+						.RegisterPass(spvtools::CreateEliminateDeadConstantPass() )
+						.RegisterPass(spvtools::CreateUnifyConstantPass() )
+						;
+					optimized = optm.Run(spirv.data(), spirv.size(), &spirv);
+				}
+#endif // 0
+
+				if (optimized)
+				{
+					uint16_t shaderSize = (uint16_t)spirv.size()*sizeof(uint32_t);
+					bx::write(_writer, shaderSize);
+					bx::write(_writer, spirv.data(), shaderSize);
+					uint8_t nul = 0;
+					bx::write(_writer, nul);
+				}
+			}
+		}
+
+		delete program;
+		delete shader;
+
+		glslang::FinalizeProcess();
+
+		return compiled && linked && validated && optimized;
+	}
+
+} // namespace spirv
+
+	bool compileSPIRVShader(bx::CommandLine& _cmdLine, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
+	{
+		return spirv::compile(_cmdLine, _version, _code, _writer);
 	}
 
 } // namespace bgfx

Some files were not shown because too many files changed in this diff