From 367f3a78a40731da45ee12b9a18c94707f1d1429 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Thu, 3 May 2018 14:25:13 -0400 Subject: Feature/vulkan first render (#545) * First pass at InputLayout for Vulkan Add support for RGBA_Float32 * Use VulkanModule and VulkanApi to handle accessing Vulkan types. * First pass at Vulkan swap chain/Device queue. * Added VulkanUtil for generic function functions. * Move more functionality to VulkanApi and VulkanUtil. Make Buffer able to initialize itself. * More tidy up around VulkanDeviceQueue * First pass use of VulkanDeviceQueue in VkRenderer * First pass use of VulkanSwapChain on VkRenderer * Added depth formats. Binding for constant and vertex buffers for Vulkan. * Setting up VkImageView on backbuffers. * First pass support for setting up vkRenderPass. * Fixes to work around Vulkan swap chain/verification issues. * Added support for Pipeline and a pipeline cache. * Working without waiting - because use of pipeline cache. * Added support for VkFramebuffer in Vulkan. * First pass at creating Vulkan graphics pipeline. * More efforts to get Vulkan to render. * Small improvement for checking of Binding flags. * Removed setConstantBuffers from the Renderer interface - so that all resource binding takes place through the BindingState. To make this work required a 'hack' in render-test main.cpp - so that the constant buffer binding that is needed in some tests is only added when it doesn't clash. * RendererID -> unified into RendererType. Added getRendererType to Renderer interface. Added ProjectionStyle, and function to get from RendererType. Added getIdentityProjection to RendererUtil - to get projection that is the 'identity' - but hits the same pixels for all projection styles. * Fix build problem on Win32 on Vulkan where should use VK_NULL_HANDLE. * Improve naming, comments. Remove dead code. * Remove unwanted comment. --- tools/render-test/vk-api.cpp | 136 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 tools/render-test/vk-api.cpp (limited to 'tools/render-test/vk-api.cpp') diff --git a/tools/render-test/vk-api.cpp b/tools/render-test/vk-api.cpp new file mode 100644 index 000000000..9d721f18f --- /dev/null +++ b/tools/render-test/vk-api.cpp @@ -0,0 +1,136 @@ +// vk-api.cpp +#include "vk-api.h" + +#include "../../source/core/list.h" + +namespace renderer_test { +using namespace Slang; + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VulkanApi !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +#define VK_API_CHECK_FUNCTION(x) && (x != nullptr) +#define VK_API_CHECK_FUNCTIONS(FUNCTION_LIST) true FUNCTION_LIST(VK_API_CHECK_FUNCTION) + +bool VulkanApi::areDefined(ProcType type) const +{ + switch (type) + { + case ProcType::Global: return VK_API_CHECK_FUNCTIONS(VK_API_ALL_GLOBAL_PROCS); + case ProcType::Instance: return VK_API_CHECK_FUNCTIONS(VK_API_ALL_INSTANCE_PROCS); + case ProcType::Device: return VK_API_CHECK_FUNCTIONS(VK_API_ALL_DEVICE_PROCS); + default: + { + assert(!"Unhandled type"); + return false; + } + } +} + +Slang::Result VulkanApi::initGlobalProcs(const VulkanModule& module) +{ +#define VK_API_GET_GLOBAL_PROC(x) x = (PFN_##x)module.getFunction(#x); + + // Initialize all the global functions + VK_API_ALL_GLOBAL_PROCS(VK_API_GET_GLOBAL_PROC) + + if (!areDefined(ProcType::Global)) + { + return SLANG_FAIL; + } + m_module = &module; + return SLANG_OK; +} + +Slang::Result VulkanApi::initInstanceProcs(VkInstance instance) +{ + assert(instance && vkGetInstanceProcAddr != nullptr); + +#define VK_API_GET_INSTANCE_PROC(x) x = (PFN_##x)vkGetInstanceProcAddr(instance, #x); + + VK_API_ALL_INSTANCE_PROCS(VK_API_GET_INSTANCE_PROC) + + if (!areDefined(ProcType::Instance)) + { + return SLANG_FAIL; + } + + m_instance = instance; + return SLANG_OK; +} + +Slang::Result VulkanApi::initPhysicalDevice(VkPhysicalDevice physicalDevice) +{ + assert(m_physicalDevice == VK_NULL_HANDLE); + m_physicalDevice = physicalDevice; + + vkGetPhysicalDeviceProperties(m_physicalDevice, &m_deviceProperties); + vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_deviceFeatures); + vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &m_deviceMemoryProperties); + + return SLANG_OK; +} + +Slang::Result VulkanApi::initDeviceProcs(VkDevice device) +{ + assert(m_instance && device && vkGetDeviceProcAddr != nullptr); + +#define VK_API_GET_DEVICE_PROC(x) x = (PFN_##x)vkGetDeviceProcAddr(device, #x); + + VK_API_ALL_DEVICE_PROCS(VK_API_GET_DEVICE_PROC) + + if (!areDefined(ProcType::Device)) + { + return SLANG_FAIL; + } + + m_device = device; + return SLANG_OK; +} + +int VulkanApi::findMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) const +{ + const int numMemoryTypes = int(m_deviceMemoryProperties.memoryTypeCount); + + // bit holds current test bit against typeBits. Ie bit == 1 << typeBits + + uint32_t bit = 1; + for (int i = 0; (typeBits != 0) && i < numMemoryTypes; ++i, bit += bit) + { + auto const& memoryType = m_deviceMemoryProperties.memoryTypes[i]; + if ((typeBits & bit) && (memoryType.propertyFlags & properties) == properties) + { + return i; + } + } + + //assert(!"failed to find a usable memory type"); + return -1; +} + +int VulkanApi::findQueue(VkQueueFlags reqFlags) const +{ + assert(m_physicalDevice != VK_NULL_HANDLE); + + uint32_t numQueueFamilies = 0; + vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &numQueueFamilies, nullptr); + + Slang::List queueFamilies; + queueFamilies.SetSize(numQueueFamilies); + vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &numQueueFamilies, queueFamilies.Buffer()); + + // Find a queue that can service our needs + //VkQueueFlags reqQueueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT; + + int queueFamilyIndex = -1; + for (int i = 0; i < int(numQueueFamilies); ++i) + { + if ((queueFamilies[i].queueFlags & reqFlags) == reqFlags) + { + return i; + } + } + + return -1; +} + +} // renderer_test -- cgit v1.2.3