上传YomovSDK
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
#include "../mock.h"
|
||||
|
||||
#define CHECK_EXT() \
|
||||
if (nullptr == s_ext) \
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
|
||||
struct ConformanceAutomation
|
||||
{
|
||||
std::map<XrPath, MockInputState> states;
|
||||
std::map<std::pair<XrPath, XrPath>, bool> activeStates;
|
||||
|
||||
MockInputState& GetState(XrPath path, XrActionType actionType)
|
||||
{
|
||||
auto it = states.find(path);
|
||||
if (it != states.end())
|
||||
return it->second;
|
||||
|
||||
MockInputState& state = states[path];
|
||||
state.type = actionType;
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
static ConformanceAutomation* s_ext = nullptr;
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceActiveEXT(XrSession session, XrPath interactionProfile, XrPath topLevelPath, XrBool32 isActive)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_RUNTIME();
|
||||
CHECK_EXT();
|
||||
s_ext->activeStates[std::pair<XrPath, XrPath>(interactionProfile, topLevelPath)] = isActive;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceStateBoolEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrBool32 state)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_EXT();
|
||||
s_ext->GetState(inputSourcePath, XR_ACTION_TYPE_BOOLEAN_INPUT).Set(state);
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceStateFloatEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, float state)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_EXT();
|
||||
CHECK_SESSION(session);
|
||||
s_ext->GetState(inputSourcePath, XR_ACTION_TYPE_FLOAT_INPUT).Set(state);
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceStateVector2fEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrVector2f state)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_EXT();
|
||||
s_ext->GetState(inputSourcePath, XR_ACTION_TYPE_VECTOR2F_INPUT).Set(state);
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceLocationEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrSpace space, XrPosef pose)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_EXT();
|
||||
s_ext->GetState(inputSourcePath, XR_ACTION_TYPE_POSE_INPUT).Set(space, pose);
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrSetInputDeviceVelocityUNITY(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, bool linearValid, XrVector3f linear, bool angularValid, XrVector3f angular)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_EXT();
|
||||
s_ext->GetState(inputSourcePath, XR_ACTION_TYPE_POSE_INPUT).SetVelocity(linearValid, linear, angularValid, angular);
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
void ConformanceAutomation_Create()
|
||||
{
|
||||
// Make sure there is no orphaned extension
|
||||
ConformanceAutomation_Destroy();
|
||||
|
||||
s_ext = new ConformanceAutomation();
|
||||
}
|
||||
|
||||
void ConformanceAutomation_Destroy()
|
||||
{
|
||||
delete s_ext;
|
||||
s_ext = nullptr;
|
||||
}
|
||||
|
||||
XrResult ConformanceAutomation_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
|
||||
{
|
||||
CHECK_EXT();
|
||||
GET_PROC_ADDRESS(xrSetInputDeviceActiveEXT)
|
||||
GET_PROC_ADDRESS(xrSetInputDeviceStateBoolEXT)
|
||||
GET_PROC_ADDRESS(xrSetInputDeviceStateFloatEXT)
|
||||
GET_PROC_ADDRESS(xrSetInputDeviceStateVector2fEXT)
|
||||
GET_PROC_ADDRESS(xrSetInputDeviceLocationEXT)
|
||||
GET_PROC_ADDRESS(xrSetInputDeviceVelocityUNITY)
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
}
|
||||
|
||||
XrResult ConformanceAutomation_GetInputState(MockInputState* state)
|
||||
{
|
||||
CHECK_EXT();
|
||||
|
||||
auto it = s_ext->states.find(state->path);
|
||||
if (it == s_ext->states.end())
|
||||
return XR_ERROR_HANDLE_INVALID;
|
||||
|
||||
state->CopyValue(it->second);
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
bool ConformanceAutomation_IsActive(XrPath interactionProfilePath, XrPath userPath, bool defaultValue)
|
||||
{
|
||||
if (nullptr == s_ext)
|
||||
return false;
|
||||
|
||||
auto active = s_ext->activeStates.find(std::pair<XrPath, XrPath>(interactionProfilePath, userPath));
|
||||
if (active == s_ext->activeStates.end())
|
||||
active = s_ext->activeStates.find(std::pair<XrPath, XrPath>(XR_NULL_PATH, userPath));
|
||||
|
||||
return (active != s_ext->activeStates.end()) ? active->second : defaultValue;
|
||||
}
|
||||
|
||||
#undef CHECK_EXT
|
||||
@@ -0,0 +1,187 @@
|
||||
#include "../mock.h"
|
||||
|
||||
#if defined(XR_USE_GRAPHICS_API_D3D11)
|
||||
|
||||
struct MockD3D11
|
||||
{
|
||||
ID3D11Device* device = nullptr;
|
||||
};
|
||||
|
||||
static MockD3D11 s_MockD3D11 = {};
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetD3D11GraphicsRequirementsKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
XrGraphicsRequirementsD3D11KHR* graphicsRequirements)
|
||||
{
|
||||
IDXGIAdapter* pAdapter;
|
||||
std::vector<IDXGIAdapter*> vAdapters;
|
||||
IDXGIFactory* pFactory = NULL;
|
||||
|
||||
// Create a DXGIFactory object.
|
||||
if (FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory)))
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
XrResult xrresult = XR_ERROR_RUNTIME_FAILURE;
|
||||
graphicsRequirements->adapterLuid = {};
|
||||
|
||||
for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc = {};
|
||||
pAdapter->GetDesc(&desc);
|
||||
graphicsRequirements->adapterLuid = desc.AdapterLuid;
|
||||
xrresult = XR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pFactory)
|
||||
pFactory->Release();
|
||||
|
||||
return xrresult;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t* formatCountOutput, int64_t* formats)
|
||||
{
|
||||
if (nullptr == formatCountOutput)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
*formatCountOutput = 6;
|
||||
|
||||
if (formatCapacityInput == 0)
|
||||
return XR_SUCCESS;
|
||||
|
||||
if (nullptr == formats)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
if (formatCapacityInput < 6)
|
||||
return XR_ERROR_SIZE_INSUFFICIENT;
|
||||
|
||||
formats[0] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
formats[1] = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||
formats[2] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
formats[3] = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
formats[4] = DXGI_FORMAT_D16_UNORM;
|
||||
formats[5] = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
static XrResult MockD3D11_xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
|
||||
{
|
||||
if (nullptr == s_MockD3D11.device)
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
ID3D11Texture2D* texture;
|
||||
D3D11_TEXTURE2D_DESC desc = {};
|
||||
desc.Width = createInfo->width;
|
||||
desc.Height = createInfo->height;
|
||||
desc.MipLevels = createInfo->mipCount;
|
||||
desc.ArraySize = createInfo->arraySize;
|
||||
desc.SampleDesc.Count = createInfo->sampleCount;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
|
||||
if (createInfo->usageFlags & XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||||
{
|
||||
if (createInfo->format == DXGI_FORMAT_D16_UNORM)
|
||||
desc.Format = DXGI_FORMAT_R16_TYPELESS;
|
||||
else
|
||||
desc.Format = DXGI_FORMAT_R32G8X24_TYPELESS;
|
||||
|
||||
desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
||||
}
|
||||
|
||||
if (FAILED(s_MockD3D11.device->CreateTexture2D(&desc, NULL, &texture)))
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
*swapchain = (XrSwapchain)texture;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrCreateSwapchainHook(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
|
||||
{
|
||||
LOG_FUNC();
|
||||
MOCK_HOOK_NAMED("xrCreateSwapchain", MockD3D11_xrCreateSwapchain(session, createInfo, swapchain));
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrDestroySwapChain(XrSwapchain swapchain)
|
||||
{
|
||||
ID3D11Texture2D* texture = (ID3D11Texture2D*)swapchain;
|
||||
texture->Release();
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t* imageCountOutput, XrSwapchainImageBaseHeader* images)
|
||||
{
|
||||
LOG_FUNC();
|
||||
|
||||
*imageCountOutput = 1;
|
||||
|
||||
if (images == nullptr)
|
||||
return XR_SUCCESS;
|
||||
|
||||
if (imageCapacityInput < *imageCountOutput)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
XrSwapchainImageD3D11KHR* d3d11images = (XrSwapchainImageD3D11KHR*)images;
|
||||
d3d11images[0].texture = (ID3D11Texture2D*)swapchain;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index)
|
||||
{
|
||||
LOG_FUNC();
|
||||
|
||||
*index = 0;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo)
|
||||
{
|
||||
LOG_FUNC();
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hook xrCreateSession to get the necessary D3D11 handles
|
||||
/// </summary>
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session);
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D11_xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session)
|
||||
{
|
||||
s_MockD3D11 = {};
|
||||
|
||||
if (createInfo->next != nullptr)
|
||||
{
|
||||
XrGraphicsBindingD3D11KHR* bindings = (XrGraphicsBindingD3D11KHR*)createInfo->next;
|
||||
if (bindings->type == XR_TYPE_GRAPHICS_BINDING_D3D11_KHR)
|
||||
{
|
||||
s_MockD3D11.device = bindings->device;
|
||||
}
|
||||
}
|
||||
|
||||
return xrCreateSession(instance, createInfo, session);
|
||||
}
|
||||
|
||||
XrResult MockD3D11_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
|
||||
{
|
||||
LOG_FUNC();
|
||||
GET_PROC_ADDRESS_REMAP(xrCreateSession, MockD3D11_xrCreateSession)
|
||||
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainFormats, MockD3D11_xrEnumerateSwapchainFormats)
|
||||
GET_PROC_ADDRESS_REMAP(xrCreateSwapchain, MockD3D11_xrCreateSwapchainHook)
|
||||
GET_PROC_ADDRESS_REMAP(xrDestroySwapChain, MockD3D11_xrDestroySwapChain)
|
||||
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainImages, MockD3D11_xrEnumerateSwapchainImages)
|
||||
GET_PROC_ADDRESS_REMAP(xrAcquireSwapchainImage, MockD3D11_xrAcquireSwapchainImage)
|
||||
GET_PROC_ADDRESS_REMAP(xrReleaseSwapchainImage, MockD3D11_xrReleaseSwapchainImage)
|
||||
GET_PROC_ADDRESS(xrGetD3D11GraphicsRequirementsKHR)
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,207 @@
|
||||
#include "../mock.h"
|
||||
|
||||
#if defined(XR_USE_GRAPHICS_API_D3D12)
|
||||
|
||||
struct MockD3D12
|
||||
{
|
||||
ID3D12Device* device = nullptr;
|
||||
};
|
||||
|
||||
static MockD3D12 s_MockD3D12 = {};
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetD3D12GraphicsRequirementsKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
XrGraphicsRequirementsD3D12KHR* graphicsRequirements)
|
||||
{
|
||||
IDXGIAdapter* pAdapter;
|
||||
std::vector<IDXGIAdapter*> vAdapters;
|
||||
IDXGIFactory* pFactory = NULL;
|
||||
|
||||
// Create a DXGIFactory object.
|
||||
if (FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory)))
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
XrResult xrresult = XR_ERROR_RUNTIME_FAILURE;
|
||||
graphicsRequirements->adapterLuid = {};
|
||||
|
||||
for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc = {};
|
||||
pAdapter->GetDesc(&desc);
|
||||
graphicsRequirements->adapterLuid = desc.AdapterLuid;
|
||||
xrresult = XR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pFactory)
|
||||
pFactory->Release();
|
||||
|
||||
return xrresult;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t* formatCountOutput, int64_t* formats)
|
||||
{
|
||||
if (nullptr == formatCountOutput)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
*formatCountOutput = 6;
|
||||
|
||||
if (formatCapacityInput == 0)
|
||||
return XR_SUCCESS;
|
||||
|
||||
if (nullptr == formats)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
if (formatCapacityInput < 6)
|
||||
return XR_ERROR_SIZE_INSUFFICIENT;
|
||||
|
||||
formats[0] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
formats[1] = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||
formats[2] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
formats[3] = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
formats[4] = DXGI_FORMAT_D16_UNORM;
|
||||
formats[5] = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
static XrResult MockD3D12_xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
|
||||
{
|
||||
if (nullptr == s_MockD3D12.device)
|
||||
{
|
||||
MOCK_TRACE_DEBUG("Mock device is null");
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
}
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProps{};
|
||||
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
D3D12_RESOURCE_DESC desc{};
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
desc.Width = createInfo->width;
|
||||
desc.Height = createInfo->height;
|
||||
desc.MipLevels = createInfo->mipCount;
|
||||
desc.DepthOrArraySize = createInfo->arraySize;
|
||||
desc.SampleDesc.Count = createInfo->sampleCount;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
|
||||
if (createInfo->usageFlags & XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||||
{
|
||||
if (createInfo->format == DXGI_FORMAT_D16_UNORM)
|
||||
desc.Format = DXGI_FORMAT_R16_TYPELESS;
|
||||
else
|
||||
desc.Format = DXGI_FORMAT_R32G8X24_TYPELESS;
|
||||
|
||||
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
|
||||
}
|
||||
|
||||
ID3D12Resource* texture;
|
||||
const HRESULT result = s_MockD3D12.device->CreateCommittedResource(
|
||||
&heapProps,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&texture));
|
||||
if (FAILED(result))
|
||||
{
|
||||
MOCK_TRACE_DEBUG("ID3D12Device::CreateCommittedResource failed, HRESULT: 0x%08x", result);
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
MOCK_TRACE_DEBUG("ID3D12Device::CreateCommittedResource success");
|
||||
}
|
||||
|
||||
*swapchain = (XrSwapchain)texture;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrCreateSwapchainHook(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
|
||||
{
|
||||
LOG_FUNC();
|
||||
MOCK_HOOK_NAMED("xrCreateSwapchain", MockD3D12_xrCreateSwapchain(session, createInfo, swapchain));
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrDestroySwapChain(XrSwapchain swapchain)
|
||||
{
|
||||
ID3D12Resource* texture = (ID3D12Resource*)swapchain;
|
||||
texture->Release();
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t* imageCountOutput, XrSwapchainImageBaseHeader* images)
|
||||
{
|
||||
LOG_FUNC();
|
||||
|
||||
*imageCountOutput = 1;
|
||||
|
||||
if (images == nullptr)
|
||||
return XR_SUCCESS;
|
||||
|
||||
if (imageCapacityInput < *imageCountOutput)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
XrSwapchainImageD3D12KHR* d3d12images = (XrSwapchainImageD3D12KHR*)images;
|
||||
d3d12images[0].texture = (ID3D12Resource*)swapchain;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index)
|
||||
{
|
||||
LOG_FUNC();
|
||||
|
||||
*index = 0;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo)
|
||||
{
|
||||
LOG_FUNC();
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hook xrCreateSession to get the necessary D3D12 handles
|
||||
/// </summary>
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session);
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockD3D12_xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session)
|
||||
{
|
||||
s_MockD3D12 = {};
|
||||
|
||||
if (createInfo->next != nullptr)
|
||||
{
|
||||
XrGraphicsBindingD3D12KHR* bindings = (XrGraphicsBindingD3D12KHR*)createInfo->next;
|
||||
if (bindings->type == XR_TYPE_GRAPHICS_BINDING_D3D12_KHR)
|
||||
{
|
||||
s_MockD3D12.device = bindings->device;
|
||||
}
|
||||
}
|
||||
|
||||
return xrCreateSession(instance, createInfo, session);
|
||||
}
|
||||
|
||||
XrResult MockD3D12_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
|
||||
{
|
||||
LOG_FUNC();
|
||||
GET_PROC_ADDRESS_REMAP(xrCreateSession, MockD3D12_xrCreateSession)
|
||||
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainFormats, MockD3D12_xrEnumerateSwapchainFormats)
|
||||
GET_PROC_ADDRESS_REMAP(xrCreateSwapchain, MockD3D12_xrCreateSwapchainHook)
|
||||
GET_PROC_ADDRESS_REMAP(xrDestroySwapChain, MockD3D12_xrDestroySwapChain)
|
||||
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainImages, MockD3D12_xrEnumerateSwapchainImages)
|
||||
GET_PROC_ADDRESS_REMAP(xrAcquireSwapchainImage, MockD3D12_xrAcquireSwapchainImage)
|
||||
GET_PROC_ADDRESS_REMAP(xrReleaseSwapchainImage, MockD3D12_xrReleaseSwapchainImage)
|
||||
GET_PROC_ADDRESS(xrGetD3D12GraphicsRequirementsKHR)
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "mock_khr_android_thread_settings.h"
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
|
||||
#define CHECK_EXT_INIT() \
|
||||
if (nullptr == MockAndroidThreadSettings::Instance()) \
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
|
||||
std::unique_ptr<MockAndroidThreadSettings> MockAndroidThreadSettings::s_Instance;
|
||||
|
||||
MockAndroidThreadSettings* MockAndroidThreadSettings::Instance()
|
||||
{
|
||||
return s_Instance.get();
|
||||
}
|
||||
|
||||
void MockAndroidThreadSettings::Init(MockRuntime& runtime)
|
||||
{
|
||||
s_Instance.reset(new MockAndroidThreadSettings(runtime));
|
||||
}
|
||||
|
||||
void MockAndroidThreadSettings::Deinit()
|
||||
{
|
||||
s_Instance.reset();
|
||||
}
|
||||
|
||||
MockAndroidThreadSettings::MockAndroidThreadSettings(MockRuntime& runtime)
|
||||
: m_Runtime{runtime}
|
||||
{
|
||||
}
|
||||
|
||||
XrResult MockAndroidThreadSettings::SetAndroidApplicationThread(XrAndroidThreadTypeKHR threadType, uint32_t threadId)
|
||||
{
|
||||
m_AssignedThreadTypes[threadId] = threadType;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
bool MockAndroidThreadSettings::IsAndroidThreadTypeRegistered(XrAndroidThreadTypeKHR threadType) const
|
||||
{
|
||||
for (auto i = m_AssignedThreadTypes.cbegin(); i != m_AssignedThreadTypes.cend(); ++i)
|
||||
{
|
||||
if (i->second == threadType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t MockAndroidThreadSettings::GetRegisteredAndroidThreadsCount() const
|
||||
{
|
||||
return m_AssignedThreadTypes.size();
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
|
||||
xrSetAndroidApplicationThreadKHR(
|
||||
XrSession session,
|
||||
XrAndroidThreadTypeKHR threadType,
|
||||
uint32_t threadId)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_SESSION(session);
|
||||
CHECK_EXT_INIT();
|
||||
MOCK_HOOK_BEFORE();
|
||||
|
||||
const XrResult result =
|
||||
MockAndroidThreadSettings::Instance()->SetAndroidApplicationThread(
|
||||
threadType,
|
||||
threadId);
|
||||
|
||||
MOCK_HOOK_AFTER(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
XrResult MockAndroidThreadSettings_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
|
||||
{
|
||||
GET_PROC_ADDRESS(xrSetAndroidApplicationThreadKHR)
|
||||
return XR_ERROR_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#undef CHECK_EXT_INIT
|
||||
#endif // XR_USE_PLATFORM_ANDROID
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "../mock.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
class MockAndroidThreadSettings
|
||||
{
|
||||
public:
|
||||
static MockAndroidThreadSettings* Instance();
|
||||
static void Init(MockRuntime& runtime);
|
||||
static void Deinit();
|
||||
|
||||
MockAndroidThreadSettings(MockRuntime& runtime);
|
||||
|
||||
XrResult SetAndroidApplicationThread(XrAndroidThreadTypeKHR threadType, uint32_t threadId);
|
||||
bool IsAndroidThreadTypeRegistered(XrAndroidThreadTypeKHR threadType) const;
|
||||
uint32_t GetRegisteredAndroidThreadsCount() const;
|
||||
|
||||
private:
|
||||
static std::unique_ptr<MockAndroidThreadSettings> s_Instance;
|
||||
|
||||
MockRuntime& m_Runtime;
|
||||
std::map<uint32_t, XrAndroidThreadTypeKHR> m_AssignedThreadTypes{};
|
||||
};
|
||||
|
||||
XrResult MockAndroidThreadSettings_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
|
||||
#endif
|
||||
@@ -0,0 +1,304 @@
|
||||
#include "mock_meta_performance_metrics.h"
|
||||
|
||||
#include "../mock.h"
|
||||
#include <sstream>
|
||||
|
||||
#define CHECK_EXT() \
|
||||
if (nullptr == MockMetaPerformanceMetrics::Instance()) \
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
|
||||
// storage for static
|
||||
std::unique_ptr<MockMetaPerformanceMetrics> MockMetaPerformanceMetrics::s_ext;
|
||||
|
||||
enum class MockMetaPerformanceMetrics::InternalPaths : int
|
||||
{
|
||||
Invalid = 0,
|
||||
AppCPUFrametime,
|
||||
AppGPUFrametime,
|
||||
AppMotionToPhotonLatency,
|
||||
CompositorCPUFrametime,
|
||||
CompositorGPUFrametime,
|
||||
CompositorDroppedFrameCount,
|
||||
CompositorSpacewarpMode,
|
||||
DeviceCPUUtilizationAvg,
|
||||
DeviceCPUUtilizationWorst,
|
||||
DeviceGPUUtilization,
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr char kAppCPUFrametimeStr[] = "/perfmetrics_meta/app/cpu_frametime";
|
||||
constexpr char kAppGPUFrametimeStr[] = "/perfmetrics_meta/app/gpu_frametime";
|
||||
constexpr char kAppMotionToPhotonLatencyStr[] = "/perfmetrics_meta/app/motion_to_photon_latency";
|
||||
constexpr char kCompositorCPUFrametimeStr[] = "/perfmetrics_meta/compositor/cpu_frametime";
|
||||
constexpr char kCompositorGPUFrametimeStr[] = "/perfmetrics_meta/compositor/gpu_frametime";
|
||||
constexpr char kCompositorDroppedFrameCountStr[] = "/perfmetrics_meta/compositor/dropped_frame_count";
|
||||
constexpr char kCompositorSpacewarpModeStr[] = "/perfmetrics_meta/compositor/spacewarp_mode";
|
||||
constexpr char kDeviceCPUUtilizationAvgStr[] = "/perfmetrics_meta/device/cpu_utilization_average";
|
||||
constexpr char kDeviceCPUUtilizationWorstStr[] = "/perfmetrics_meta/device/cpu_utilization_worst";
|
||||
constexpr char kDeviceGPUUtilizationStr[] = "/perfmetrics_meta/device/gpu_utilization";
|
||||
} // namespace
|
||||
|
||||
MockMetaPerformanceMetrics::InternalPaths MockMetaPerformanceMetrics::InternalPathFromString(
|
||||
const std::string& s)
|
||||
{
|
||||
if (s == kAppCPUFrametimeStr)
|
||||
return InternalPaths::AppCPUFrametime;
|
||||
if (s == kAppGPUFrametimeStr)
|
||||
return InternalPaths::AppGPUFrametime;
|
||||
if (s == kAppMotionToPhotonLatencyStr)
|
||||
return InternalPaths::AppMotionToPhotonLatency;
|
||||
if (s == kCompositorCPUFrametimeStr)
|
||||
return InternalPaths::CompositorCPUFrametime;
|
||||
if (s == kCompositorGPUFrametimeStr)
|
||||
return InternalPaths::CompositorGPUFrametime;
|
||||
if (s == kCompositorDroppedFrameCountStr)
|
||||
return InternalPaths::CompositorDroppedFrameCount;
|
||||
if (s == kCompositorSpacewarpModeStr)
|
||||
return InternalPaths::CompositorSpacewarpMode;
|
||||
if (s == kDeviceCPUUtilizationAvgStr)
|
||||
return InternalPaths::DeviceCPUUtilizationAvg;
|
||||
if (s == kDeviceCPUUtilizationWorstStr)
|
||||
return InternalPaths::DeviceCPUUtilizationWorst;
|
||||
if (s == kDeviceGPUUtilizationStr)
|
||||
return InternalPaths::DeviceGPUUtilization;
|
||||
return InternalPaths::Invalid;
|
||||
}
|
||||
|
||||
MockMetaPerformanceMetrics::MockMetaPerformanceMetrics(MockRuntime& runtime, const int numMockCPUs)
|
||||
: m_NumMockCPUs{numMockCPUs}
|
||||
, m_Runtime{runtime}
|
||||
{
|
||||
static constexpr const char* k_ListPaths[] = {
|
||||
kAppCPUFrametimeStr,
|
||||
kAppGPUFrametimeStr,
|
||||
kAppMotionToPhotonLatencyStr,
|
||||
kCompositorCPUFrametimeStr,
|
||||
kCompositorGPUFrametimeStr,
|
||||
kCompositorDroppedFrameCountStr,
|
||||
kCompositorSpacewarpModeStr,
|
||||
kDeviceCPUUtilizationAvgStr,
|
||||
kDeviceCPUUtilizationWorstStr,
|
||||
kDeviceGPUUtilizationStr,
|
||||
};
|
||||
|
||||
for (const char* const pathString : k_ListPaths)
|
||||
{
|
||||
const XrPath path = runtime.StringToPath(pathString);
|
||||
m_Paths[path] = InternalPathFromString(pathString);
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_NumMockCPUs; i++)
|
||||
{
|
||||
std::stringstream ss{"/perfmetrics_meta/device/cpu"};
|
||||
ss << i << "_utilization";
|
||||
|
||||
std::string pathString = ss.str();
|
||||
const XrPath path = runtime.StringToPath(pathString.c_str());
|
||||
m_Paths[path] = InternalPathFromString(pathString);
|
||||
}
|
||||
}
|
||||
|
||||
void MockMetaPerformanceMetrics::Init(MockRuntime& runtime, const int numMockCPUs)
|
||||
{
|
||||
s_ext.reset(new MockMetaPerformanceMetrics(runtime, numMockCPUs));
|
||||
}
|
||||
|
||||
void MockMetaPerformanceMetrics::Deinit()
|
||||
{
|
||||
s_ext.reset();
|
||||
}
|
||||
|
||||
MockMetaPerformanceMetrics* MockMetaPerformanceMetrics::Instance()
|
||||
{
|
||||
return s_ext.get();
|
||||
}
|
||||
|
||||
XrResult MockMetaPerformanceMetrics::EnumeratePaths(
|
||||
XrInstance instance,
|
||||
uint32_t counterPathCapacityInput,
|
||||
uint32_t* counterPathCountOutput,
|
||||
XrPath* counterPaths)
|
||||
{
|
||||
*counterPathCountOutput = static_cast<uint32_t>(m_Paths.size());
|
||||
if (counterPathCapacityInput >= *counterPathCountOutput)
|
||||
{
|
||||
int i = 0;
|
||||
for (const auto kv : m_Paths)
|
||||
{
|
||||
counterPaths[i] = kv.first;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
XrResult MockMetaPerformanceMetrics::SetState(XrSession session, const XrPerformanceMetricsStateMETA* state)
|
||||
{
|
||||
if (!state || state->type != XR_TYPE_PERFORMANCE_METRICS_STATE_META)
|
||||
{
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
}
|
||||
m_Enabled = state->enabled == XR_TRUE;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
XrResult MockMetaPerformanceMetrics::GetState(XrSession session, XrPerformanceMetricsStateMETA* state)
|
||||
{
|
||||
if (!state || state->type != XR_TYPE_PERFORMANCE_METRICS_STATE_META)
|
||||
{
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
}
|
||||
state->enabled = m_Enabled ? XR_TRUE : XR_FALSE;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
XrResult MockMetaPerformanceMetrics::QueryCounter(
|
||||
XrSession session,
|
||||
XrPath counterPath,
|
||||
XrPerformanceMetricsCounterMETA* counter)
|
||||
{
|
||||
if (!m_Enabled || !counter || counter->type != XR_TYPE_PERFORMANCE_METRICS_COUNTER_META)
|
||||
{
|
||||
// disabled state return value confirmed by Xiang Wei @ Meta.
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
}
|
||||
|
||||
std::list<MockResult>& values = m_SeededResults[m_Paths[counterPath]];
|
||||
if (values.empty())
|
||||
{
|
||||
if (!m_NoResultsSeededWarningShown)
|
||||
{
|
||||
m_NoResultsSeededWarningShown = true;
|
||||
MOCK_TRACE_DEBUG("No results were seeded for the requested stat. If you aren't testing stats, ignore this warning.");
|
||||
}
|
||||
*counter = m_DefaultResult.value;
|
||||
return m_DefaultResult.rv;
|
||||
}
|
||||
|
||||
// FIFO, fill in the counter struct and return the seeded return value.
|
||||
*counter = values.front().value;
|
||||
XrResult rv = values.front().rv;
|
||||
values.pop_front();
|
||||
return rv;
|
||||
}
|
||||
|
||||
void MockMetaPerformanceMetrics::SeedCounterOnce(const std::string& counterPathString, MockResult result)
|
||||
{
|
||||
const XrPath path = m_Runtime.StringToPath(counterPathString.c_str());
|
||||
if (path == XR_NULL_PATH)
|
||||
{
|
||||
// providing an invalid path during testing shouldn't happen, kill and warn our dev
|
||||
// if you want to test whether a path exists, use the runtime functions themselves.
|
||||
MOCK_TRACE_ERROR("Could not find path %s", counterPathString.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.value.type != XR_TYPE_PERFORMANCE_METRICS_COUNTER_META)
|
||||
{
|
||||
MOCK_TRACE_ERROR(
|
||||
"Invalid or no type supplied for XrPerformanceMetricsCounterMETA. Type MUST be"
|
||||
" XR_TYPE_PERFORMANCE_METRICS_COUNTER_META.");
|
||||
return;
|
||||
}
|
||||
if (result.value.next != nullptr)
|
||||
{
|
||||
MOCK_TRACE_ERROR(
|
||||
"This structure does not currently support chaining (`next` should be `nullptr`).");
|
||||
return;
|
||||
}
|
||||
std::list<MockResult>& values = m_SeededResults[m_Paths[path]];
|
||||
values.push_back(result);
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
|
||||
xrEnumeratePerformanceMetricsCounterPathsMETA(
|
||||
XrInstance instance,
|
||||
uint32_t counterPathCapacityInput,
|
||||
uint32_t* counterPathCountOutput,
|
||||
XrPath* counterPaths)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_RUNTIME();
|
||||
CHECK_INSTANCE(instance);
|
||||
CHECK_EXT();
|
||||
MOCK_HOOK_BEFORE();
|
||||
|
||||
const XrResult result =
|
||||
MockMetaPerformanceMetrics::Instance()->EnumeratePaths(
|
||||
instance,
|
||||
counterPathCapacityInput,
|
||||
counterPathCountOutput,
|
||||
counterPaths);
|
||||
|
||||
MOCK_HOOK_AFTER(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
|
||||
xrSetPerformanceMetricsStateMETA(
|
||||
XrSession session,
|
||||
const XrPerformanceMetricsStateMETA* state)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_SESSION(session);
|
||||
CHECK_EXT();
|
||||
MOCK_HOOK_BEFORE();
|
||||
|
||||
const XrResult result = MockMetaPerformanceMetrics::Instance()->SetState(session, state);
|
||||
|
||||
MOCK_HOOK_AFTER(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
|
||||
xrGetPerformanceMetricsStateMETA(
|
||||
XrSession session,
|
||||
XrPerformanceMetricsStateMETA* state)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_SESSION(session);
|
||||
CHECK_EXT();
|
||||
MOCK_HOOK_BEFORE();
|
||||
|
||||
const XrResult result = MockMetaPerformanceMetrics::Instance()->GetState(session, state);
|
||||
|
||||
MOCK_HOOK_AFTER(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
|
||||
xrQueryPerformanceMetricsCounterMETA(
|
||||
XrSession session,
|
||||
XrPath counterPath,
|
||||
XrPerformanceMetricsCounterMETA* counter)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_SESSION(session);
|
||||
CHECK_EXT();
|
||||
MOCK_HOOK_BEFORE();
|
||||
|
||||
const XrResult result =
|
||||
MockMetaPerformanceMetrics::Instance()->QueryCounter(
|
||||
session,
|
||||
counterPath,
|
||||
counter);
|
||||
|
||||
MOCK_HOOK_AFTER(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
XrResult MockMetaPerformanceMetrics_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
|
||||
{
|
||||
GET_PROC_ADDRESS(xrEnumeratePerformanceMetricsCounterPathsMETA)
|
||||
GET_PROC_ADDRESS(xrSetPerformanceMetricsStateMETA)
|
||||
GET_PROC_ADDRESS(xrGetPerformanceMetricsStateMETA)
|
||||
GET_PROC_ADDRESS(xrQueryPerformanceMetricsCounterMETA)
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#undef CHECK_EXT
|
||||
@@ -0,0 +1,73 @@
|
||||
// Mock extension for XR_META_performance_metrics extension
|
||||
// https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_META_performance_metrics
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openxr/openxr.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class MockRuntime;
|
||||
|
||||
class MockMetaPerformanceMetrics
|
||||
{
|
||||
public:
|
||||
enum class InternalPaths : int;
|
||||
|
||||
struct MockResult
|
||||
{
|
||||
XrResult rv;
|
||||
XrPerformanceMetricsCounterMETA value;
|
||||
};
|
||||
|
||||
static void Init(MockRuntime& runtime, const int numMockCPUs);
|
||||
static void Deinit();
|
||||
static MockMetaPerformanceMetrics* Instance();
|
||||
|
||||
static InternalPaths InternalPathFromString(const std::string& s);
|
||||
|
||||
XrResult EnumeratePaths(
|
||||
XrInstance instance,
|
||||
uint32_t counterPathCapacityInput,
|
||||
uint32_t* counterPathCountOutput,
|
||||
XrPath* counterPaths);
|
||||
XrResult SetState(XrSession session, const XrPerformanceMetricsStateMETA* state);
|
||||
XrResult GetState(XrSession session, XrPerformanceMetricsStateMETA* state);
|
||||
XrResult QueryCounter(
|
||||
XrSession session,
|
||||
XrPath counterPath,
|
||||
XrPerformanceMetricsCounterMETA* counter);
|
||||
|
||||
void SeedCounterOnce(const std::string& counterPath, MockResult result);
|
||||
|
||||
private:
|
||||
MockMetaPerformanceMetrics(MockRuntime& runtime, const int numMockCPUs);
|
||||
|
||||
static std::unique_ptr<MockMetaPerformanceMetrics> s_ext;
|
||||
MockRuntime& m_Runtime;
|
||||
|
||||
const int m_NumMockCPUs;
|
||||
|
||||
// we use an ordered set just to keep things consistent for enumeration
|
||||
std::map<XrPath, InternalPaths> m_Paths;
|
||||
|
||||
bool m_Enabled;
|
||||
bool m_NoResultsSeededWarningShown;
|
||||
|
||||
std::map<InternalPaths, std::list<MockResult>> m_SeededResults;
|
||||
MockResult m_DefaultResult{
|
||||
XR_SUCCESS,
|
||||
{
|
||||
XR_TYPE_PERFORMANCE_METRICS_COUNTER_META,
|
||||
nullptr,
|
||||
XR_PERFORMANCE_METRICS_COUNTER_ANY_VALUE_VALID_BIT_META,
|
||||
XR_PERFORMANCE_METRICS_COUNTER_UNIT_GENERIC_META,
|
||||
0,
|
||||
0.f,
|
||||
}};
|
||||
};
|
||||
|
||||
XrResult MockMetaPerformanceMetrics_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "../mock.h"
|
||||
|
||||
XrResult MockRuntime::MSFTFirstPersonObserver_Init()
|
||||
{
|
||||
MockViewConfiguration firstPersonConfig = {};
|
||||
firstPersonConfig.primary = false;
|
||||
firstPersonConfig.enabled = false;
|
||||
firstPersonConfig.active = false;
|
||||
firstPersonConfig.stateFlags = XR_VIEW_STATE_ORIENTATION_TRACKED_BIT |
|
||||
XR_VIEW_STATE_ORIENTATION_VALID_BIT |
|
||||
XR_VIEW_STATE_POSITION_TRACKED_BIT |
|
||||
XR_VIEW_STATE_POSITION_VALID_BIT;
|
||||
firstPersonConfig.views = {
|
||||
{viewConfigurations[XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO].views[0].configuration,
|
||||
{{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
|
||||
{-0.995535672f, 0.995566666f, 0.954059243f, -0.954661012f}}};
|
||||
|
||||
viewConfigurations[XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_FIRST_PERSON_OBSERVER_MSFT] = firstPersonConfig;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#include "../mock.h"
|
||||
|
||||
XrResult MockRuntime::MSFTSecondaryViewConfiguration_BeginSession(const XrSessionBeginInfo* beginInfo)
|
||||
{
|
||||
// Check for secondary view configuration
|
||||
const XrSecondaryViewConfigurationSessionBeginInfoMSFT* secondaryViewConfiguration =
|
||||
FindNextPointerType<XrSecondaryViewConfigurationSessionBeginInfoMSFT>(beginInfo, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT);
|
||||
|
||||
if (nullptr == secondaryViewConfiguration)
|
||||
return XR_SUCCESS;
|
||||
|
||||
if (secondaryViewConfiguration->viewConfigurationCount == 0)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
if (secondaryViewConfiguration->enabledViewConfigurationTypes == nullptr)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
secondaryViewConfigurationStates.reserve(secondaryViewConfiguration->viewConfigurationCount);
|
||||
for (uint32_t i = 0; i < secondaryViewConfiguration->viewConfigurationCount; i++)
|
||||
{
|
||||
MockViewConfiguration* viewConfiguration = GetMockViewConfiguration(secondaryViewConfiguration->enabledViewConfigurationTypes[i]);
|
||||
if (nullptr == viewConfiguration)
|
||||
return XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED;
|
||||
|
||||
if (viewConfiguration->primary || viewConfiguration->enabled)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
viewConfiguration->enabled = true;
|
||||
|
||||
XrSecondaryViewConfigurationStateMSFT viewState = {XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT};
|
||||
viewState.viewConfigurationType = secondaryViewConfiguration->enabledViewConfigurationTypes[i];
|
||||
viewState.active = viewConfiguration->active;
|
||||
secondaryViewConfigurationStates.push_back(viewState);
|
||||
}
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
XrResult MockRuntime::MSFTSecondaryViewConfiguration_WaitFrame(const XrFrameWaitInfo* frameWaitInfo, XrFrameState* frameState)
|
||||
{
|
||||
// Check for secondary view configuration
|
||||
XrSecondaryViewConfigurationFrameStateMSFT* secondaryFrameState =
|
||||
FindNextPointerType<XrSecondaryViewConfigurationFrameStateMSFT>(frameState, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT);
|
||||
|
||||
if (secondaryFrameState == nullptr)
|
||||
return XR_SUCCESS;
|
||||
|
||||
if (secondaryFrameState->viewConfigurationCount == 0 || secondaryFrameState->viewConfigurationStates == nullptr)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
if (secondaryFrameState->viewConfigurationCount != (uint32_t)secondaryViewConfigurationStates.size())
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
for (auto& viewConfiguration : secondaryViewConfigurationStates)
|
||||
{
|
||||
if (viewConfiguration.viewConfigurationType != 0)
|
||||
{
|
||||
viewConfiguration.active = GetMockViewConfiguration(viewConfiguration.viewConfigurationType)->active;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(secondaryFrameState->viewConfigurationStates, secondaryViewConfigurationStates.data(), secondaryViewConfigurationStates.size() * sizeof(XrSecondaryViewConfigurationStateMSFT));
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
XrResult MockRuntime::MSFTSecondaryViewConfiguration_EndFrame(const XrFrameEndInfo* frameEndInfo)
|
||||
{
|
||||
const XrSecondaryViewConfigurationFrameEndInfoMSFT* secondaryFrameEndInfo =
|
||||
FindNextPointerType<XrSecondaryViewConfigurationFrameEndInfoMSFT>(frameEndInfo, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT);
|
||||
|
||||
if (secondaryFrameEndInfo == nullptr)
|
||||
return XR_SUCCESS;
|
||||
|
||||
if (secondaryFrameEndInfo->viewConfigurationCount == 0 || secondaryFrameEndInfo->viewConfigurationLayersInfo == nullptr)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
for (uint32_t i = 0; i < secondaryFrameEndInfo->viewConfigurationCount; i++)
|
||||
{
|
||||
auto& info = secondaryFrameEndInfo->viewConfigurationLayersInfo[0];
|
||||
MockViewConfiguration* viewConfiguration = GetMockViewConfiguration(info.viewConfigurationType);
|
||||
if (viewConfiguration->primary)
|
||||
return XR_ERROR_LAYER_INVALID;
|
||||
if (!viewConfiguration->enabled)
|
||||
return XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT;
|
||||
if (!viewConfiguration->active)
|
||||
continue;
|
||||
|
||||
secondaryLayersRendered += info.layerCount;
|
||||
}
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
XrResult MockRuntime::ActivateSecondaryView(XrViewConfigurationType viewConfigurationType, bool active)
|
||||
{
|
||||
if (viewConfigurationType == 0)
|
||||
{
|
||||
// emulating a bug we saw with microsoft runtime
|
||||
secondaryViewConfigurationStates.clear();
|
||||
secondaryViewConfigurationStates.push_back({XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT});
|
||||
}
|
||||
|
||||
MockViewConfiguration* viewConfiguration = GetMockViewConfiguration(viewConfigurationType);
|
||||
if (nullptr == viewConfiguration || (IsSessionRunning() && !viewConfiguration->enabled))
|
||||
return XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT;
|
||||
|
||||
if (viewConfiguration->primary)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
viewConfiguration->active = active;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "../mock.h"
|
||||
|
||||
XrResult MockRuntime::MSFTThirdPersonObserver_Init()
|
||||
{
|
||||
MockViewConfiguration thirdPersonConfig = {};
|
||||
thirdPersonConfig.primary = false;
|
||||
thirdPersonConfig.enabled = false;
|
||||
thirdPersonConfig.active = false;
|
||||
thirdPersonConfig.stateFlags = XR_VIEW_STATE_ORIENTATION_TRACKED_BIT |
|
||||
XR_VIEW_STATE_ORIENTATION_VALID_BIT |
|
||||
XR_VIEW_STATE_POSITION_TRACKED_BIT |
|
||||
XR_VIEW_STATE_POSITION_VALID_BIT;
|
||||
thirdPersonConfig.views = {
|
||||
{viewConfigurations[XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO].views[0].configuration,
|
||||
{{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
|
||||
{-0.995535672f, 0.995566666f, 0.954059243f, -0.954661012f}}};
|
||||
|
||||
viewConfigurations[XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_THIRD_PERSON_OBSERVER_MSFT] = thirdPersonConfig;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "mock_performance_settings.h"
|
||||
|
||||
#define CHECK_PERF_SETTINGS_EXT() \
|
||||
if (nullptr == MockPerformanceSettings::Instance()) \
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
|
||||
std::unique_ptr<MockPerformanceSettings> MockPerformanceSettings::s_ext;
|
||||
|
||||
void MockPerformanceSettings::Init(MockRuntime& runtime)
|
||||
{
|
||||
s_ext.reset(new MockPerformanceSettings(runtime));
|
||||
}
|
||||
|
||||
void MockPerformanceSettings::Deinit()
|
||||
{
|
||||
s_ext.reset();
|
||||
}
|
||||
|
||||
MockPerformanceSettings* MockPerformanceSettings::Instance()
|
||||
{
|
||||
return s_ext.get();
|
||||
}
|
||||
|
||||
MockPerformanceSettings::MockPerformanceSettings(MockRuntime& runtime)
|
||||
: m_Runtime(runtime)
|
||||
{
|
||||
}
|
||||
|
||||
XrResult MockPerformanceSettings::SetPerformanceLevel(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsLevelEXT level)
|
||||
{
|
||||
if (domain != XR_PERF_SETTINGS_DOMAIN_CPU_EXT &&
|
||||
domain != XR_PERF_SETTINGS_DOMAIN_GPU_EXT)
|
||||
{
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
}
|
||||
|
||||
if (level != XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT &&
|
||||
level != XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT &&
|
||||
level != XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT &&
|
||||
level != XR_PERF_SETTINGS_LEVEL_BOOST_EXT)
|
||||
{
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
}
|
||||
|
||||
m_PerformanceLevelHints[domain] = level;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
XrPerfSettingsLevelEXT MockPerformanceSettings::GetPerformanceLevelHint(XrPerfSettingsDomainEXT domain)
|
||||
{
|
||||
if (m_PerformanceLevelHints.find(domain) != m_PerformanceLevelHints.end())
|
||||
{
|
||||
return m_PerformanceLevelHints[domain];
|
||||
}
|
||||
|
||||
return XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT; // Default value per spec
|
||||
}
|
||||
|
||||
XrPerfSettingsNotificationLevelEXT MockPerformanceSettings::GetPerformanceSettingsNotificationLevel(XrPerfSettingsDomainEXT domain, XrPerfSettingsSubDomainEXT subdomain)
|
||||
{
|
||||
auto pair = std::make_pair(domain, subdomain);
|
||||
return m_notificationLevel[pair];
|
||||
}
|
||||
|
||||
void MockPerformanceSettings::SetPerformanceSettingsNotificationLevel(XrPerfSettingsDomainEXT domain, XrPerfSettingsSubDomainEXT subdomain, XrPerfSettingsNotificationLevelEXT nextLevel)
|
||||
{
|
||||
auto pair = std::make_pair(domain, subdomain);
|
||||
m_notificationLevel[pair] = nextLevel;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR
|
||||
xrPerfSettingsSetPerformanceLevelEXT(
|
||||
XrSession session,
|
||||
XrPerfSettingsDomainEXT domain,
|
||||
XrPerfSettingsLevelEXT level)
|
||||
{
|
||||
LOG_FUNC();
|
||||
CHECK_SESSION(session);
|
||||
CHECK_PERF_SETTINGS_EXT();
|
||||
MOCK_HOOK_BEFORE();
|
||||
|
||||
const XrResult result =
|
||||
MockPerformanceSettings::Instance()->SetPerformanceLevel(session, domain, level);
|
||||
|
||||
MOCK_HOOK_AFTER(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
XrResult MockPerformanceSettings_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
|
||||
{
|
||||
GET_PROC_ADDRESS(xrPerfSettingsSetPerformanceLevelEXT);
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#undef CHECK_PERF_SETTINGS_EXT
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "../mock.h"
|
||||
#include "IUnityInterface.h"
|
||||
#include "openxr/openxr.h"
|
||||
#include "openxr/openxr_platform_defines.h"
|
||||
|
||||
class MockRuntime;
|
||||
|
||||
class MockPerformanceSettings
|
||||
{
|
||||
public:
|
||||
static void Init(MockRuntime& runtime);
|
||||
static void Deinit();
|
||||
static MockPerformanceSettings* Instance();
|
||||
|
||||
XrResult SetPerformanceLevel(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsLevelEXT level);
|
||||
XrPerfSettingsLevelEXT GetPerformanceLevelHint(XrPerfSettingsDomainEXT domain);
|
||||
|
||||
XrPerfSettingsNotificationLevelEXT GetPerformanceSettingsNotificationLevel(XrPerfSettingsDomainEXT domain, XrPerfSettingsSubDomainEXT subdomain);
|
||||
void SetPerformanceSettingsNotificationLevel(XrPerfSettingsDomainEXT domain, XrPerfSettingsSubDomainEXT subdomain, XrPerfSettingsNotificationLevelEXT nextLevel);
|
||||
|
||||
private:
|
||||
static std::unique_ptr<MockPerformanceSettings> s_ext;
|
||||
|
||||
MockRuntime& m_Runtime;
|
||||
|
||||
std::map<XrPerfSettingsDomainEXT, XrPerfSettingsLevelEXT> m_PerformanceLevelHints;
|
||||
std::map<std::pair<XrPerfSettingsDomainEXT, XrPerfSettingsSubDomainEXT>, XrPerfSettingsNotificationLevelEXT> m_notificationLevel;
|
||||
|
||||
MockPerformanceSettings(MockRuntime& runtime);
|
||||
};
|
||||
|
||||
XrResult MockPerformanceSettings_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
|
||||
@@ -0,0 +1,317 @@
|
||||
#include "../mock.h"
|
||||
|
||||
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||
|
||||
struct MockVulkan
|
||||
{
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice phsyicalDevice = VK_NULL_HANDLE;
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
VkQueue queue = VK_NULL_HANDLE;
|
||||
VkPhysicalDeviceMemoryProperties memoryProperties = {};
|
||||
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = nullptr;
|
||||
PFN_vkAllocateMemory vkAllocateMemory = nullptr;
|
||||
PFN_vkCreateImage vkCreateImage = nullptr;
|
||||
PFN_vkCreateDevice vkCreateDevice = nullptr;
|
||||
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = nullptr;
|
||||
PFN_vkBindImageMemory vkBindImageMemory = nullptr;
|
||||
PFN_vkDestroyImage vkDestroyImage = nullptr;
|
||||
PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements = nullptr;
|
||||
PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties = nullptr;
|
||||
};
|
||||
|
||||
static MockVulkan s_MockVulkan = {};
|
||||
|
||||
static bool GetVulkanMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties, uint32_t* index)
|
||||
{
|
||||
for (uint32_t i = 0; i < s_MockVulkan.memoryProperties.memoryTypeCount; i++, typeBits >>= 1)
|
||||
{
|
||||
// Only consider memory types included in the typeBits mask
|
||||
if ((typeBits & 1) == 0)
|
||||
continue;
|
||||
|
||||
// If all requested properties are a match then return this memory type
|
||||
if ((s_MockVulkan.memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||
{
|
||||
*index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVulkanInstanceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer)
|
||||
{
|
||||
if (nullptr == bufferCountOutput)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
*bufferCountOutput = 0;
|
||||
|
||||
if (bufferCapacityInput > 0 && buffer == nullptr)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVulkanDeviceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer)
|
||||
{
|
||||
if (nullptr == bufferCountOutput)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
*bufferCountOutput = 0;
|
||||
|
||||
if (bufferCapacityInput > 0 && buffer == nullptr)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVulkanGraphicsDeviceKHR(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice* vkPhysicalDevice)
|
||||
{
|
||||
*vkPhysicalDevice = s_MockVulkan.phsyicalDevice;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateVulkanInstanceKHR(
|
||||
XrInstance instance,
|
||||
const XrVulkanInstanceCreateInfoKHR* createInfo,
|
||||
VkInstance* vulkanInstance,
|
||||
VkResult* vulkanResult)
|
||||
{
|
||||
s_MockVulkan = {};
|
||||
s_MockVulkan.vkGetInstanceProcAddr = createInfo->pfnGetInstanceProcAddr;
|
||||
|
||||
if (s_MockVulkan.vkGetInstanceProcAddr == nullptr)
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
PFN_vkCreateInstance vkCreateInstance = (PFN_vkCreateInstance)s_MockVulkan.vkGetInstanceProcAddr(nullptr, "vkCreateInstance");
|
||||
if (nullptr == vkCreateInstance)
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
if (VK_SUCCESS != vkCreateInstance(createInfo->vulkanCreateInfo, createInfo->vulkanAllocator, vulkanInstance))
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
#define VK_GET_PROC_ADDR(func) s_MockVulkan.func = (PFN_##func)s_MockVulkan.vkGetInstanceProcAddr(*vulkanInstance, #func);
|
||||
VK_GET_PROC_ADDR(vkCreateImage)
|
||||
VK_GET_PROC_ADDR(vkCreateDevice)
|
||||
VK_GET_PROC_ADDR(vkDestroyImage)
|
||||
VK_GET_PROC_ADDR(vkGetPhysicalDeviceMemoryProperties)
|
||||
VK_GET_PROC_ADDR(vkGetImageMemoryRequirements)
|
||||
VK_GET_PROC_ADDR(vkAllocateMemory)
|
||||
VK_GET_PROC_ADDR(vkBindImageMemory)
|
||||
VK_GET_PROC_ADDR(vkEnumeratePhysicalDevices)
|
||||
#undef VK_GET_PROC_ADDR
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateVulkanDeviceKHR(XrInstance instance, const XrVulkanDeviceCreateInfoKHR* createInfo, VkDevice* device, VkResult* result)
|
||||
{
|
||||
*result = s_MockVulkan.vkCreateDevice(createInfo->vulkanPhysicalDevice, createInfo->vulkanCreateInfo, createInfo->vulkanAllocator, device);
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVulkanGraphicsRequirements2KHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements)
|
||||
{
|
||||
graphicsRequirements->minApiVersionSupported = VK_MAKE_VERSION(0, 0, 0);
|
||||
graphicsRequirements->maxApiVersionSupported = VK_MAKE_VERSION(255, 255, 255);
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrGetVulkanGraphicsDevice2KHR(
|
||||
XrInstance instance,
|
||||
const XrVulkanGraphicsDeviceGetInfoKHR* getInfo,
|
||||
VkPhysicalDevice* vulkanPhysicalDevice)
|
||||
{
|
||||
if (nullptr == s_MockVulkan.vkEnumeratePhysicalDevices)
|
||||
{
|
||||
*vulkanPhysicalDevice = nullptr;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t physicalDeviceCount = 0;
|
||||
s_MockVulkan.vkEnumeratePhysicalDevices(getInfo->vulkanInstance, &physicalDeviceCount, nullptr);
|
||||
if (physicalDeviceCount == 0)
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
std::vector<VkPhysicalDevice> physicalDevices;
|
||||
physicalDevices.resize(physicalDeviceCount);
|
||||
s_MockVulkan.vkEnumeratePhysicalDevices(getInfo->vulkanInstance, &physicalDeviceCount, physicalDevices.data());
|
||||
if (physicalDeviceCount != (uint32_t)physicalDevices.size())
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
*vulkanPhysicalDevice = physicalDevices[0];
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hook xrCreateSession to get the necessary vulkan handles
|
||||
/// </summary>
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session);
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session)
|
||||
{
|
||||
if (createInfo->next != nullptr)
|
||||
{
|
||||
XrGraphicsBindingVulkanKHR* bindings = (XrGraphicsBindingVulkanKHR*)createInfo->next;
|
||||
if (bindings->type == XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR)
|
||||
{
|
||||
s_MockVulkan.device = bindings->device;
|
||||
s_MockVulkan.instance = bindings->instance;
|
||||
s_MockVulkan.phsyicalDevice = bindings->physicalDevice;
|
||||
|
||||
if (s_MockVulkan.vkGetPhysicalDeviceMemoryProperties == nullptr)
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
s_MockVulkan.vkGetPhysicalDeviceMemoryProperties(s_MockVulkan.phsyicalDevice, &s_MockVulkan.memoryProperties);
|
||||
}
|
||||
}
|
||||
|
||||
return xrCreateSession(instance, createInfo, session);
|
||||
}
|
||||
|
||||
static VkImage CreateSwapchainImage(const XrSwapchainCreateInfo* createInfo)
|
||||
{
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageCreateInfo.format = (VkFormat)createInfo->format;
|
||||
imageCreateInfo.mipLevels = createInfo->mipCount;
|
||||
imageCreateInfo.arrayLayers = createInfo->arraySize;
|
||||
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
imageCreateInfo.extent.width = createInfo->width;
|
||||
imageCreateInfo.extent.height = createInfo->height;
|
||||
imageCreateInfo.extent.depth = 1;
|
||||
imageCreateInfo.usage = 0;
|
||||
|
||||
if (createInfo->usageFlags & XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT)
|
||||
imageCreateInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
if (createInfo->usageFlags & XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||||
imageCreateInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
|
||||
VkImage vkimage;
|
||||
s_MockVulkan.vkCreateImage(s_MockVulkan.device, &imageCreateInfo, nullptr, &vkimage);
|
||||
|
||||
// Allocate memory to back the destination image
|
||||
VkMemoryRequirements memRequirements;
|
||||
s_MockVulkan.vkGetImageMemoryRequirements(s_MockVulkan.device, vkimage, &memRequirements);
|
||||
|
||||
VkDeviceMemory imageMemory;
|
||||
VkMemoryAllocateInfo memAllocInfo = {};
|
||||
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memAllocInfo.allocationSize = memRequirements.size;
|
||||
|
||||
if (!GetVulkanMemoryTypeIndex(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAllocInfo.memoryTypeIndex))
|
||||
return VK_NULL_HANDLE;
|
||||
|
||||
s_MockVulkan.vkAllocateMemory(s_MockVulkan.device, &memAllocInfo, nullptr, &imageMemory);
|
||||
s_MockVulkan.vkBindImageMemory(s_MockVulkan.device, vkimage, imageMemory, 0);
|
||||
|
||||
return vkimage;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
|
||||
{
|
||||
LOG_FUNC();
|
||||
|
||||
*swapchain = (XrSwapchain)CreateSwapchainImage(createInfo);
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrCreateSwapchainHook(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain)
|
||||
{
|
||||
LOG_FUNC();
|
||||
MOCK_HOOK_NAMED("xrCreateSwapchain", MockVulkan_xrCreateSwapchain(session, createInfo, swapchain));
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrDestroySwapChain(XrSwapchain swapchain)
|
||||
{
|
||||
s_MockVulkan.vkDestroyImage(s_MockVulkan.device, (VkImage)swapchain, nullptr);
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index)
|
||||
{
|
||||
LOG_FUNC();
|
||||
|
||||
*index = 0;
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo)
|
||||
{
|
||||
LOG_FUNC();
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t* formatCountOutput, int64_t* formats)
|
||||
{
|
||||
if (nullptr == formatCountOutput)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
*formatCountOutput = 3;
|
||||
|
||||
if (formatCapacityInput == 0)
|
||||
return XR_SUCCESS;
|
||||
|
||||
if (nullptr == formats)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
if (formatCapacityInput < 3)
|
||||
return XR_ERROR_SIZE_INSUFFICIENT;
|
||||
|
||||
formats[0] = VK_FORMAT_R8G8B8A8_SRGB;
|
||||
formats[1] = VK_FORMAT_D16_UNORM;
|
||||
formats[2] = VK_FORMAT_D24_UNORM_S8_UINT;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t* imageCountOutput, XrSwapchainImageBaseHeader* images)
|
||||
{
|
||||
LOG_FUNC();
|
||||
|
||||
*imageCountOutput = 1;
|
||||
|
||||
if (images == nullptr)
|
||||
return XR_SUCCESS;
|
||||
|
||||
if (imageCapacityInput < *imageCountOutput)
|
||||
return XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
XrSwapchainImageVulkanKHR* vkimages = (XrSwapchainImageVulkanKHR*)images;
|
||||
vkimages[0].image = (VkImage)swapchain;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR xrEndFrame(XrSession session, const XrFrameEndInfo* frameEndInfo);
|
||||
extern "C" XrResult UNITY_INTERFACE_EXPORT XRAPI_PTR MockVulkan_xrEndFrame(XrSession session, const XrFrameEndInfo* frameEndInfo)
|
||||
{
|
||||
return xrEndFrame(session, frameEndInfo);
|
||||
}
|
||||
|
||||
XrResult MockVulkan_GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function)
|
||||
{
|
||||
LOG_FUNC();
|
||||
GET_PROC_ADDRESS_REMAP(xrCreateSession, MockVulkan_xrCreateSession)
|
||||
GET_PROC_ADDRESS_REMAP(xrCreateSwapchain, MockVulkan_xrCreateSwapchainHook)
|
||||
GET_PROC_ADDRESS_REMAP(xrDestroySwapChain, MockVulkan_xrDestroySwapChain)
|
||||
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainFormats, MockVulkan_xrEnumerateSwapchainFormats)
|
||||
GET_PROC_ADDRESS_REMAP(xrEnumerateSwapchainImages, MockVulkan_xrEnumerateSwapchainImages)
|
||||
GET_PROC_ADDRESS_REMAP(xrAcquireSwapchainImage, MockVulkan_xrAcquireSwapchainImage)
|
||||
GET_PROC_ADDRESS_REMAP(xrReleaseSwapchainImage, MockVulkan_xrReleaseSwapchainImage)
|
||||
GET_PROC_ADDRESS_REMAP(xrEndFrame, MockVulkan_xrEndFrame)
|
||||
GET_PROC_ADDRESS(xrCreateVulkanInstanceKHR)
|
||||
GET_PROC_ADDRESS(xrGetVulkanGraphicsRequirements2KHR)
|
||||
GET_PROC_ADDRESS(xrGetVulkanGraphicsDevice2KHR)
|
||||
GET_PROC_ADDRESS(xrCreateVulkanDeviceKHR)
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#endif // XR_USE_GRAPHICS_API_VULKAN
|
||||
Reference in New Issue
Block a user