VK: Initial commit.
This commit is contained in:
parent
f46d6a5803
commit
e0b901a98a
@ -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"),
|
||||
|
@ -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()
|
||||
|
4623
src/renderer_vk.cpp
4623
src/renderer_vk.cpp
File diff suppressed because it is too large
Load Diff
449
src/renderer_vk.h
Normal file
449
src/renderer_vk.h
Normal file
@ -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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user