Files
renderdoc/renderdoc/driver/vulkan/vk_linux.cpp
T
baldurk 7db90232f9 Allow creating completely headless outputs and reading back their output
* This is useful when writing automated tests that want to test the output of
  rendering which only happens to outputs, such as mesh rendering, or could
  potentially be bypassed with direct readback like GetTextureData vs rendering
  a texture.
2019-05-06 15:52:43 +01:00

249 lines
7.9 KiB
C++

/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016-2019 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "api/replay/renderdoc_replay.h"
#include "vk_core.h"
#include "vk_replay.h"
#if defined(VK_USE_PLATFORM_XCB_KHR)
VkBool32 WrappedVulkan::vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
xcb_connection_t *connection,
xcb_visualid_t visual_id)
{
return ObjDisp(physicalDevice)
->GetPhysicalDeviceXcbPresentationSupportKHR(Unwrap(physicalDevice), queueFamilyIndex,
connection, visual_id);
}
namespace Keyboard
{
void UseConnection(xcb_connection_t *conn);
}
VkResult WrappedVulkan::vkCreateXcbSurfaceKHR(VkInstance instance,
const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkSurfaceKHR *pSurface)
{
// should not come in here at all on replay
RDCASSERT(IsCaptureMode(m_State));
VkResult ret =
ObjDisp(instance)->CreateXcbSurfaceKHR(Unwrap(instance), pCreateInfo, pAllocator, pSurface);
if(ret == VK_SUCCESS)
{
GetResourceManager()->WrapResource(Unwrap(instance), *pSurface);
WrappedVkSurfaceKHR *wrapped = GetWrapped(*pSurface);
// since there's no point in allocating a full resource record and storing the window
// handle under there somewhere, we just cast. We won't use the resource record for anything
wrapped->record = (VkResourceRecord *)(uintptr_t)pCreateInfo->window;
Keyboard::UseConnection(pCreateInfo->connection);
}
return ret;
}
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
VkBool32 WrappedVulkan::vkGetPhysicalDeviceXlibPresentationSupportKHR(
VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display *dpy, VisualID visualID)
{
return ObjDisp(physicalDevice)
->GetPhysicalDeviceXlibPresentationSupportKHR(Unwrap(physicalDevice), queueFamilyIndex, dpy,
visualID);
}
namespace Keyboard
{
void CloneDisplay(Display *dpy);
}
VkResult WrappedVulkan::vkCreateXlibSurfaceKHR(VkInstance instance,
const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkSurfaceKHR *pSurface)
{
// should not come in here at all on replay
RDCASSERT(IsCaptureMode(m_State));
VkResult ret =
ObjDisp(instance)->CreateXlibSurfaceKHR(Unwrap(instance), pCreateInfo, pAllocator, pSurface);
if(ret == VK_SUCCESS)
{
GetResourceManager()->WrapResource(Unwrap(instance), *pSurface);
WrappedVkSurfaceKHR *wrapped = GetWrapped(*pSurface);
// since there's no point in allocating a full resource record and storing the window
// handle under there somewhere, we just cast. We won't use the resource record for anything
wrapped->record = (VkResourceRecord *)pCreateInfo->window;
Keyboard::CloneDisplay(pCreateInfo->dpy);
}
return ret;
}
VkResult WrappedVulkan::vkAcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy,
VkDisplayKHR display)
{
// display is not wrapped so we can pass straight through
return ObjDisp(physicalDevice)->AcquireXlibDisplayEXT(Unwrap(physicalDevice), dpy, display);
}
VkResult WrappedVulkan::vkGetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy,
RROutput rrOutput, VkDisplayKHR *pDisplay)
{
// display is not wrapped so we can pass straight through
return ObjDisp(physicalDevice)
->GetRandROutputDisplayEXT(Unwrap(physicalDevice), dpy, rrOutput, pDisplay);
}
#endif
void VulkanReplay::OutputWindow::SetWindowHandle(WindowingData window)
{
#if ENABLED(RDOC_XLIB)
if(window.system == WindowingSystem::Xlib)
{
xlib.display = window.xlib.display;
xlib.window = window.xlib.window;
return;
}
#endif
#if ENABLED(RDOC_XCB)
if(window.system == WindowingSystem::XCB)
{
xcb.connection = window.xcb.connection;
xcb.window = window.xcb.window;
return;
}
#endif
RDCERR("Unrecognised/unsupported window system %d", window.system);
}
void VulkanReplay::OutputWindow::CreateSurface(VkInstance inst)
{
#if ENABLED(RDOC_XLIB)
if(m_WindowSystem == WindowingSystem::Xlib)
{
VkXlibSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.dpy = xlib.display;
createInfo.window = xlib.window;
VkResult vkr = ObjDisp(inst)->CreateXlibSurfaceKHR(Unwrap(inst), &createInfo, NULL, &surface);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
return;
}
#endif
#if ENABLED(RDOC_XCB)
if(m_WindowSystem == WindowingSystem::XCB)
{
VkXcbSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.connection = xcb.connection;
createInfo.window = xcb.window;
VkResult vkr = ObjDisp(inst)->CreateXcbSurfaceKHR(Unwrap(inst), &createInfo, NULL, &surface);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
return;
}
#endif
RDCERR("Unrecognised/unsupported window system %d", m_WindowSystem);
}
void VulkanReplay::GetOutputWindowDimensions(uint64_t id, int32_t &w, int32_t &h)
{
if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
return;
OutputWindow &outw = m_OutputWindows[id];
if(outw.m_WindowSystem == WindowingSystem::Headless)
{
w = outw.width;
h = outw.height;
return;
}
#if ENABLED(RDOC_XLIB)
if(outw.m_WindowSystem == WindowingSystem::Xlib)
{
XWindowAttributes attr = {};
XGetWindowAttributes(outw.xlib.display, outw.xlib.window, &attr);
w = (int32_t)attr.width;
h = (int32_t)attr.height;
return;
}
#endif
#if ENABLED(RDOC_XCB)
if(outw.m_WindowSystem == WindowingSystem::XCB)
{
xcb_get_geometry_cookie_t geomCookie =
xcb_get_geometry(outw.xcb.connection, outw.xcb.window); // window is a xcb_drawable_t
xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(outw.xcb.connection, geomCookie, NULL);
w = (int32_t)geom->width;
h = (int32_t)geom->height;
free(geom);
return;
}
#endif
RDCERR("Unrecognised/unsupported window system %d", outw.m_WindowSystem);
}
void *LoadVulkanLibrary()
{
return Process::LoadModule("libvulkan.so.1");
}