mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57fc87061d | ||
|
|
cc9f7e723a | ||
|
|
6a41e05694 | ||
|
|
c8e1dc5328 | ||
|
|
c2ee5a0234 | ||
|
|
3cafd2dc69 | ||
|
|
4b8890c438 | ||
|
|
19882dc160 | ||
|
|
0c21023bb2 | ||
|
|
68e6ede47e | ||
|
|
1ed3001358 | ||
|
|
b8ff171127 | ||
|
|
7d16a915ed | ||
|
|
ecc24ce2e9 | ||
|
|
65748351c7 | ||
|
|
a60489b6fd | ||
|
|
e8dbcc31aa | ||
|
|
5dbaf194c5 |
2
3rdparty/d3d12memalloc/LICENSE.txt
vendored
2
3rdparty/d3d12memalloc/LICENSE.txt
vendored
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
22
3rdparty/d3d12memalloc/README.md
vendored
22
3rdparty/d3d12memalloc/README.md
vendored
@@ -2,7 +2,7 @@
|
||||
|
||||
Easy to integrate memory allocation library for Direct3D 12.
|
||||
|
||||
**Documentation:** Browse online: [D3D12 Memory Allocator](https://gpuopen-librariesandsdks.github.io/D3D12MemoryAllocator/html/) (generated from Doxygen-style comments in [src/D3D12MemAlloc.h](src/D3D12MemAlloc.h))
|
||||
**Documentation:** Browse online: [D3D12 Memory Allocator](https://gpuopen-librariesandsdks.github.io/D3D12MemoryAllocator/html/) (generated from Doxygen-style comments in [include/D3D12MemAlloc.h](include/D3D12MemAlloc.h))
|
||||
|
||||
**License:** MIT. See [LICENSE.txt](LICENSE.txt)
|
||||
|
||||
@@ -36,6 +36,7 @@ Additional features:
|
||||
- Customization and integration with custom engines: Predefine appropriate macros to provide your own implementation of external facilities used by the library, like assert, mutex, and atomic.
|
||||
- Support for resource aliasing (overlap).
|
||||
- Custom memory pools: Create a pool with desired parameters (e.g. fixed or limited maximum size, custom `D3D12_HEAP_PROPERTIES` and `D3D12_HEAP_FLAGS`) and allocate memory out of it.
|
||||
- Support for GPU Upload Heaps from preview Agility SDK (needs compilation with `D3D12MA_OPTIONS16_SUPPORTED` macro).
|
||||
- Linear allocator: Create a pool with linear algorithm and use it for much faster allocations and deallocations in free-at-once, stack, double stack, or ring buffer fashion.
|
||||
- Defragmentation: Let the library move data around to free some memory blocks and make your allocations better compacted.
|
||||
- Statistics: Obtain brief or detailed statistics about the amount of memory used, unused, number of allocated heaps, number of allocations etc. - globally and per memory heap type. Current memory usage and budget as reported by the system can also be queried.
|
||||
@@ -101,15 +102,18 @@ This software package uses third party software:
|
||||
|
||||
For more information see [NOTICES.txt](NOTICES.txt).
|
||||
|
||||
# Software using this library
|
||||
|
||||
- **[The Forge](https://github.com/ConfettiFX/The-Forge)** - cross-platform rendering framework. Apache License 2.0.
|
||||
- **[Wicked Engine<img src="https://github.com/turanszkij/WickedEngine/blob/master/Content/logo_small.png" width="28px" align="center"/>](https://github.com/turanszkij/WickedEngine)** - 3D engine with modern graphics
|
||||
|
||||
[Some other projects on GitHub](https://github.com/search?q=D3D12MemAlloc.h&type=Code) and some game development studios that use DX12 in their games.
|
||||
|
||||
# See also
|
||||
|
||||
- **[Vcpkg](https://github.com/Microsoft/vcpkg)** dependency manager from Microsoft offers a port of this library that is easy to install.
|
||||
- **[Vulkan Memory Allocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/)** - equivalent library for Vulkan. License: MIT.
|
||||
- **[d3d12ma.c](https://github.com/milliewalky/d3d12ma.c)** - C bindings for this library. Author: Mateusz Maciejewski (Matt Walky). License: MIT.
|
||||
- **[TerraFX.Interop.D3D12MemoryAllocator](https://github.com/terrafx/terrafx.interop.d3d12memoryallocator)** - interop bindings for this library for C#, as used by [TerraFX](https://github.com/terrafx/terrafx). License: MIT.
|
||||
- **[Vulkan Memory Allocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/)** - equivalent library for Vulkan. License: MIT.
|
||||
|
||||
# Software using this library
|
||||
|
||||
- **[Qt Project](https://github.com/qt)**
|
||||
- **[Ghost of Tsushima: Director's Cut PC](https://www.youtube.com/watch?v=cPKBDbCYctc&t=698s)** - Information avaliable in 11:38 of credits
|
||||
- **[The Forge](https://github.com/ConfettiFX/The-Forge)** - cross-platform rendering framework. Apache License 2.0.
|
||||
- **[Wicked Engine<img src="https://github.com/turanszkij/WickedEngine/blob/master/Content/logo_small.png" width="28px" align="center"/>](https://github.com/turanszkij/WickedEngine)** - 3D engine with modern graphics
|
||||
|
||||
[Some other projects on GitHub](https://github.com/search?q=D3D12MemAlloc.h&type=Code) and some game development studios that use DX12 in their games.
|
||||
|
||||
81
3rdparty/d3d12memalloc/include/D3D12MemAlloc.h
vendored
81
3rdparty/d3d12memalloc/include/D3D12MemAlloc.h
vendored
@@ -24,9 +24,9 @@
|
||||
|
||||
/** \mainpage D3D12 Memory Allocator
|
||||
|
||||
<b>Version 2.1.0-development</b> (2023-07-05)
|
||||
<b>Version 2.1.0-development</b> (2024-07-05)
|
||||
|
||||
Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. \n
|
||||
Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved. \n
|
||||
License: MIT
|
||||
|
||||
Documentation of all members: D3D12MemAlloc.h
|
||||
@@ -160,9 +160,9 @@ class D3D12MA_API IUnknownImpl : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual ~IUnknownImpl() = default;
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||
virtual ULONG STDMETHODCALLTYPE Release();
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
protected:
|
||||
virtual void ReleaseThis() { delete this; }
|
||||
private:
|
||||
@@ -265,18 +265,18 @@ enum ALLOCATION_FLAGS
|
||||
*/
|
||||
ALLOCATION_FLAG_CAN_ALIAS = 0x10,
|
||||
|
||||
/** Allocation strategy that chooses smallest possible free range for the allocation
|
||||
/** %Allocation strategy that chooses smallest possible free range for the allocation
|
||||
to minimize memory usage and fragmentation, possibly at the expense of allocation time.
|
||||
*/
|
||||
ALLOCATION_FLAG_STRATEGY_MIN_MEMORY = 0x00010000,
|
||||
|
||||
/** Allocation strategy that chooses first suitable free range for the allocation -
|
||||
/** %Allocation strategy that chooses first suitable free range for the allocation -
|
||||
not necessarily in terms of the smallest offset but the one that is easiest and fastest to find
|
||||
to minimize allocation time, possibly at the expense of allocation quality.
|
||||
*/
|
||||
ALLOCATION_FLAG_STRATEGY_MIN_TIME = 0x00020000,
|
||||
|
||||
/** Allocation strategy that chooses always the lowest offset in available space.
|
||||
/** %Allocation strategy that chooses always the lowest offset in available space.
|
||||
This is not the most efficient strategy but achieves highly packed data.
|
||||
Used internally by defragmentation, not recomended in typical usage.
|
||||
*/
|
||||
@@ -402,8 +402,9 @@ struct TotalStatistics
|
||||
- 1 = `D3D12_HEAP_TYPE_UPLOAD`
|
||||
- 2 = `D3D12_HEAP_TYPE_READBACK`
|
||||
- 3 = `D3D12_HEAP_TYPE_CUSTOM`
|
||||
- 4 = `D3D12_HEAP_TYPE_GPU_UPLOAD`
|
||||
*/
|
||||
DetailedStatistics HeapType[4];
|
||||
DetailedStatistics HeapType[5];
|
||||
/** \brief One element for each memory segment group located at the following indices:
|
||||
|
||||
- 0 = `DXGI_MEMORY_SEGMENT_GROUP_LOCAL`
|
||||
@@ -413,9 +414,9 @@ struct TotalStatistics
|
||||
|
||||
- When `IsUMA() == FALSE` (discrete graphics card):
|
||||
- `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` (index 0) represents GPU memory
|
||||
(resources allocated in `D3D12_HEAP_TYPE_DEFAULT` or `D3D12_MEMORY_POOL_L1`).
|
||||
(resources allocated in `D3D12_HEAP_TYPE_DEFAULT`, `D3D12_HEAP_TYPE_GPU_UPLOAD` or `D3D12_MEMORY_POOL_L1`).
|
||||
- `DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL` (index 1) represents system memory
|
||||
(resources allocated in `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`, or `D3D12_MEMORY_POOL_L0`).
|
||||
(resources allocated in `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`, or `D3D12_MEMORY_POOL_L0`).
|
||||
- When `IsUMA() == TRUE` (integrated graphics chip):
|
||||
- `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` = (index 0) represents memory shared for all the resources.
|
||||
- `DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL` = (index 1) is unused and always 0.
|
||||
@@ -542,26 +543,6 @@ public:
|
||||
*/
|
||||
LPCWSTR GetName() const { return m_Name; }
|
||||
|
||||
/** \brief Returns `TRUE` if the memory of the allocation was filled with zeros when the allocation was created.
|
||||
|
||||
Returns `TRUE` only if the allocator is sure that the entire memory where the
|
||||
allocation was created was filled with zeros at the moment the allocation was made.
|
||||
|
||||
Returns `FALSE` if the memory could potentially contain garbage data.
|
||||
If it's a render-target or depth-stencil texture, it then needs proper
|
||||
initialization with `ClearRenderTargetView`, `ClearDepthStencilView`, `DiscardResource`,
|
||||
or a copy operation, as described on page
|
||||
"ID3D12Device::CreatePlacedResource method - Notes on the required resource initialization" in Microsoft documentation.
|
||||
Please note that rendering a fullscreen triangle or quad to the texture as
|
||||
a render target is not a proper way of initialization!
|
||||
|
||||
See also articles:
|
||||
|
||||
- "Coming to DirectX 12: More control over memory allocation" on DirectX Developer Blog
|
||||
- ["Initializing DX12 Textures After Allocation and Aliasing"](https://asawicki.info/news_1724_initializing_dx12_textures_after_allocation_and_aliasing).
|
||||
*/
|
||||
BOOL WasZeroInitialized() const { return m_PackedData.WasZeroInitialized(); }
|
||||
|
||||
protected:
|
||||
void ReleaseThis() override;
|
||||
|
||||
@@ -620,29 +601,26 @@ private:
|
||||
{
|
||||
public:
|
||||
PackedData() :
|
||||
m_Type(0), m_ResourceDimension(0), m_ResourceFlags(0), m_TextureLayout(0), m_WasZeroInitialized(0) { }
|
||||
m_Type(0), m_ResourceDimension(0), m_ResourceFlags(0), m_TextureLayout(0) { }
|
||||
|
||||
Type GetType() const { return (Type)m_Type; }
|
||||
D3D12_RESOURCE_DIMENSION GetResourceDimension() const { return (D3D12_RESOURCE_DIMENSION)m_ResourceDimension; }
|
||||
D3D12_RESOURCE_FLAGS GetResourceFlags() const { return (D3D12_RESOURCE_FLAGS)m_ResourceFlags; }
|
||||
D3D12_TEXTURE_LAYOUT GetTextureLayout() const { return (D3D12_TEXTURE_LAYOUT)m_TextureLayout; }
|
||||
BOOL WasZeroInitialized() const { return (BOOL)m_WasZeroInitialized; }
|
||||
|
||||
void SetType(Type type);
|
||||
void SetResourceDimension(D3D12_RESOURCE_DIMENSION resourceDimension);
|
||||
void SetResourceFlags(D3D12_RESOURCE_FLAGS resourceFlags);
|
||||
void SetTextureLayout(D3D12_TEXTURE_LAYOUT textureLayout);
|
||||
void SetWasZeroInitialized(BOOL wasZeroInitialized) { m_WasZeroInitialized = wasZeroInitialized ? 1 : 0; }
|
||||
|
||||
private:
|
||||
UINT m_Type : 2; // enum Type
|
||||
UINT m_ResourceDimension : 3; // enum D3D12_RESOURCE_DIMENSION
|
||||
UINT m_ResourceFlags : 24; // flags D3D12_RESOURCE_FLAGS
|
||||
UINT m_TextureLayout : 9; // enum D3D12_TEXTURE_LAYOUT
|
||||
UINT m_WasZeroInitialized : 1; // BOOL
|
||||
} m_PackedData;
|
||||
|
||||
Allocation(AllocatorPimpl* allocator, UINT64 size, UINT64 alignment, BOOL wasZeroInitialized);
|
||||
Allocation(AllocatorPimpl* allocator, UINT64 size, UINT64 alignment);
|
||||
// Nothing here, everything already done in Release.
|
||||
virtual ~Allocation() = default;
|
||||
|
||||
@@ -1065,6 +1043,16 @@ enum ALLOCATOR_FLAGS
|
||||
to create its heaps on smaller alignment not suitable for MSAA textures.
|
||||
*/
|
||||
ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED = 0x8,
|
||||
/** \brief Disable optimization that prefers creating small buffers as committed to avoid 64 KB alignment.
|
||||
|
||||
By default, the library prefers creating small buffers <= 32 KB as committed,
|
||||
because drivers tend to pack them better, while placed buffers require 64 KB alignment.
|
||||
This, however, may decrease performance, as creating committed resources involves allocation of implicit heaps,
|
||||
which may take longer than creating placed resources in existing heaps.
|
||||
Passing this flag will disable this committed preference globally for the allocator.
|
||||
It can also be disabled for a single allocation by using #ALLOCATION_FLAG_STRATEGY_MIN_TIME.
|
||||
*/
|
||||
ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED = 0x10,
|
||||
};
|
||||
|
||||
/// \brief Parameters of created Allocator object. To be used with CreateAllocator().
|
||||
@@ -1130,6 +1118,15 @@ public:
|
||||
- "ID3D12Device::GetCustomHeapProperties method (d3d12.h)"
|
||||
*/
|
||||
BOOL IsCacheCoherentUMA() const;
|
||||
/** \brief Returns true if GPU Upload Heaps are supported on the current system.
|
||||
|
||||
When true, you can use `D3D12_HEAP_TYPE_GPU_UPLOAD`.
|
||||
|
||||
This flag is fetched from `D3D12_FEATURE_D3D12_OPTIONS16::GPUUploadHeapSupported`.
|
||||
|
||||
`#define D3D12MA_OPTIONS16_SUPPORTED 1` is needed for the compilation of this library. Otherwise the flag is always false.
|
||||
*/
|
||||
BOOL IsGPUUploadHeapSupported() const;
|
||||
/** \brief Returns total amount of memory of specific segment group, in bytes.
|
||||
|
||||
\param memorySegmentGroup use `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` or DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL`.
|
||||
@@ -1447,11 +1444,11 @@ enum VIRTUAL_ALLOCATION_FLAGS
|
||||
*/
|
||||
VIRTUAL_ALLOCATION_FLAG_UPPER_ADDRESS = ALLOCATION_FLAG_UPPER_ADDRESS,
|
||||
|
||||
/// Allocation strategy that tries to minimize memory usage.
|
||||
/// %Allocation strategy that tries to minimize memory usage.
|
||||
VIRTUAL_ALLOCATION_FLAG_STRATEGY_MIN_MEMORY = ALLOCATION_FLAG_STRATEGY_MIN_MEMORY,
|
||||
/// Allocation strategy that tries to minimize allocation time.
|
||||
/// %Allocation strategy that tries to minimize allocation time.
|
||||
VIRTUAL_ALLOCATION_FLAG_STRATEGY_MIN_TIME = ALLOCATION_FLAG_STRATEGY_MIN_TIME,
|
||||
/** \brief Allocation strategy that chooses always the lowest offset in available space.
|
||||
/** %Allocation strategy that chooses always the lowest offset in available space.
|
||||
This is not the most efficient strategy but achieves highly packed data.
|
||||
*/
|
||||
VIRTUAL_ALLOCATION_FLAG_STRATEGY_MIN_OFFSET = ALLOCATION_FLAG_STRATEGY_MIN_OFFSET,
|
||||
@@ -1640,6 +1637,9 @@ ID3D12Device* device = (...)
|
||||
D3D12MA::ALLOCATOR_DESC allocatorDesc = {};
|
||||
allocatorDesc.pDevice = device;
|
||||
allocatorDesc.pAdapter = adapter;
|
||||
// These flags are optional but recommended.
|
||||
allocatorDesc.Flags = D3D12MA::ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED |
|
||||
D3D12MA::ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED;
|
||||
|
||||
D3D12MA::Allocator* allocator;
|
||||
HRESULT hr = D3D12MA::CreateAllocator(&allocatorDesc, &allocator);
|
||||
@@ -1864,6 +1864,9 @@ to obtain object D3D12MA::Pool. Example:
|
||||
\code
|
||||
POOL_DESC poolDesc = {};
|
||||
poolDesc.HeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
// These flags are optional but recommended.
|
||||
poolDesc.Flags = D3D12MA::POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED;
|
||||
poolDesc.HeapFlags = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
|
||||
|
||||
Pool* pool;
|
||||
HRESULT hr = allocator->CreatePool(&poolDesc, &pool);
|
||||
|
||||
863
3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp
vendored
863
3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp
vendored
File diff suppressed because it is too large
Load Diff
1
3rdparty/libchdr/include/libchdr/chd.h
vendored
1
3rdparty/libchdr/include/libchdr/chd.h
vendored
@@ -259,7 +259,6 @@ extern "C" {
|
||||
/* CHD open values */
|
||||
#define CHD_OPEN_READ 1
|
||||
#define CHD_OPEN_READWRITE 2
|
||||
#define CHD_OPEN_TRANSFER_FILE 4 /* Freeing of the FILE* is now libchdr's responsibility if open was successful */
|
||||
|
||||
/* error types */
|
||||
enum _chd_error
|
||||
|
||||
8
3rdparty/libchdr/src/libchdr_chd.c
vendored
8
3rdparty/libchdr/src/libchdr_chd.c
vendored
@@ -1737,13 +1737,7 @@ CHD_EXPORT chd_error chd_open_file(FILE *file, int mode, chd_file *parent, chd_f
|
||||
stream->fclose = core_stdio_fclose_nonowner;
|
||||
stream->fseek = core_stdio_fseek;
|
||||
|
||||
chd_error err = chd_open_core_file(stream, mode, parent, chd);
|
||||
if (err != CHDERR_NONE)
|
||||
return err;
|
||||
|
||||
// swap out the fclose so that we close it on chd clost
|
||||
stream->fclose = core_stdio_fclose;
|
||||
return CHDERR_NONE;
|
||||
return chd_open_core_file(stream, mode, parent, chd);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
|
||||
523
3rdparty/vulkan/include/vk_mem_alloc.h
vendored
523
3rdparty/vulkan/include/vk_mem_alloc.h
vendored
@@ -95,6 +95,7 @@ See also: [product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-me
|
||||
- \subpage enabling_buffer_device_address
|
||||
- \subpage vk_ext_memory_priority
|
||||
- \subpage vk_amd_device_coherent_memory
|
||||
- \subpage vk_khr_external_memory_win32
|
||||
- \subpage general_considerations
|
||||
- [Thread safety](@ref general_considerations_thread_safety)
|
||||
- [Versioning and compatibility](@ref general_considerations_versioning_and_compatibility)
|
||||
@@ -127,7 +128,9 @@ See documentation chapter: \ref statistics.
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(VULKAN_H_)
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
|
||||
#if !defined(VMA_VULKAN_VERSION)
|
||||
#if defined(VK_VERSION_1_3)
|
||||
@@ -240,6 +243,15 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Defined to 1 when VK_KHR_external_memory_win32 device extension is defined in Vulkan headers.
|
||||
#if !defined(VMA_EXTERNAL_MEMORY_WIN32)
|
||||
#if VK_KHR_external_memory_win32
|
||||
#define VMA_EXTERNAL_MEMORY_WIN32 1
|
||||
#else
|
||||
#define VMA_EXTERNAL_MEMORY_WIN32 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Define these macros to decorate all public functions with additional code,
|
||||
// before and after returned type, appropriately. This may be useful for
|
||||
// exporting the functions when compiling VMA as a separate library. Example:
|
||||
@@ -459,6 +471,15 @@ typedef enum VmaAllocatorCreateFlagBits
|
||||
*/
|
||||
VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT = 0x00000100,
|
||||
|
||||
/**
|
||||
Enables usage of VK_KHR_external_memory_win32 extension in the library.
|
||||
|
||||
You should set this flag if you found available and enabled this device extension,
|
||||
while creating Vulkan device passed as VmaAllocatorCreateInfo::device.
|
||||
For more information, see \ref vk_khr_external_memory_win32.
|
||||
*/
|
||||
VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT = 0x00000200,
|
||||
|
||||
VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||
} VmaAllocatorCreateFlagBits;
|
||||
/// See #VmaAllocatorCreateFlagBits.
|
||||
@@ -1033,6 +1054,11 @@ typedef struct VmaVulkanFunctions
|
||||
/// Fetch from "vkGetDeviceImageMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceImageMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4.
|
||||
PFN_vkGetDeviceImageMemoryRequirementsKHR VMA_NULLABLE vkGetDeviceImageMemoryRequirements;
|
||||
#endif
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
PFN_vkGetMemoryWin32HandleKHR VMA_NULLABLE vkGetMemoryWin32HandleKHR;
|
||||
#else
|
||||
void* VMA_NULLABLE vkGetMemoryWin32HandleKHR;
|
||||
#endif
|
||||
} VmaVulkanFunctions;
|
||||
|
||||
/// Description of a Allocator to be created.
|
||||
@@ -1810,6 +1836,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(
|
||||
\param allocator Allocator object.
|
||||
\param pool Pool object.
|
||||
\param[out] pPoolStats Statistics of specified pool.
|
||||
|
||||
Note that when using the pool from multiple threads, returned information may immediately
|
||||
become outdated.
|
||||
*/
|
||||
VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics(
|
||||
VmaAllocator VMA_NOT_NULL allocator,
|
||||
@@ -2050,6 +2079,40 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties(
|
||||
VmaAllocation VMA_NOT_NULL allocation,
|
||||
VkMemoryPropertyFlags* VMA_NOT_NULL pFlags);
|
||||
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
/**
|
||||
\brief Given an allocation, returns Win32 handle that may be imported by other processes or APIs.
|
||||
|
||||
\param hTargetProcess Must be a valid handle to target process or null. If it's null, the function returns
|
||||
handle for the current process.
|
||||
\param[out] pHandle Output parameter that returns the handle.
|
||||
|
||||
The function fills `pHandle` with handle that can be used in target process.
|
||||
The handle is fetched using function `vkGetMemoryWin32HandleKHR`.
|
||||
When no longer needed, you must close it using:
|
||||
|
||||
\code
|
||||
CloseHandle(handle);
|
||||
\endcode
|
||||
|
||||
You can close it any time, before or after destroying the allocation object.
|
||||
It is reference-counted internally by Windows.
|
||||
|
||||
Note the handle is returned for the entire `VkDeviceMemory` block that the allocation belongs to.
|
||||
If the allocation is sub-allocated from a larger block, you may need to consider the offset of the allocation
|
||||
(VmaAllocationInfo::offset).
|
||||
|
||||
If the function fails with `VK_ERROR_FEATURE_NOT_PRESENT` error code, please double-check
|
||||
that VmaVulkanFunctions::vkGetMemoryWin32HandleKHR function pointer is set, e.g. either by using `VMA_DYNAMIC_VULKAN_FUNCTIONS`
|
||||
or by manually passing it through VmaAllocatorCreateInfo::pVulkanFunctions.
|
||||
|
||||
For more information, see chapter \ref vk_khr_external_memory_win32.
|
||||
*/
|
||||
VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle(VmaAllocator VMA_NOT_NULL allocator,
|
||||
VmaAllocation VMA_NOT_NULL allocation, HANDLE hTargetProcess, HANDLE* VMA_NOT_NULL pHandle);
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
|
||||
/** \brief Maps memory represented by given allocation and returns pointer to it.
|
||||
|
||||
Maps memory represented by given allocation to make it accessible to CPU code.
|
||||
@@ -3097,7 +3160,7 @@ static void vma_aligned_free(void* VMA_NULLABLE ptr)
|
||||
std::shared_mutex m_Mutex;
|
||||
};
|
||||
#define VMA_RW_MUTEX VmaRWMutex
|
||||
#elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600
|
||||
#elif defined(_WIN32) && defined(WINVER) && defined(SRWLOCK_INIT) && WINVER >= 0x0600
|
||||
// Use SRWLOCK from WinAPI.
|
||||
// Minimum supported client = Windows Vista, server = Windows Server 2008.
|
||||
class VmaRWMutex
|
||||
@@ -3838,12 +3901,6 @@ struct VmaBufferImageUsage
|
||||
|
||||
const VmaBufferImageUsage VmaBufferImageUsage::UNKNOWN = VmaBufferImageUsage(0);
|
||||
|
||||
static void swap(VmaBufferImageUsage& lhs, VmaBufferImageUsage& rhs) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(lhs.Value, rhs.Value);
|
||||
}
|
||||
|
||||
VmaBufferImageUsage::VmaBufferImageUsage(const VkBufferCreateInfo &createInfo,
|
||||
bool useKhrMaintenance5)
|
||||
{
|
||||
@@ -6073,6 +6130,84 @@ private:
|
||||
|
||||
#endif // _VMA_MAPPING_HYSTERESIS
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
class VmaWin32Handle
|
||||
{
|
||||
public:
|
||||
VmaWin32Handle() noexcept : m_hHandle(VMA_NULL) { }
|
||||
explicit VmaWin32Handle(HANDLE hHandle) noexcept : m_hHandle(hHandle) { }
|
||||
~VmaWin32Handle() noexcept { if (m_hHandle != VMA_NULL) { ::CloseHandle(m_hHandle); } }
|
||||
VMA_CLASS_NO_COPY_NO_MOVE(VmaWin32Handle)
|
||||
|
||||
public:
|
||||
// Strengthened
|
||||
VkResult GetHandle(VkDevice device, VkDeviceMemory memory, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, bool useMutex, HANDLE* pHandle) noexcept
|
||||
{
|
||||
*pHandle = VMA_NULL;
|
||||
// Try to get handle first.
|
||||
if (m_hHandle != VMA_NULL)
|
||||
{
|
||||
*pHandle = Duplicate(hTargetProcess);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult res = VK_SUCCESS;
|
||||
// If failed, try to create it.
|
||||
{
|
||||
VmaMutexLockWrite lock(m_Mutex, useMutex);
|
||||
if (m_hHandle == VMA_NULL)
|
||||
{
|
||||
res = Create(device, memory, pvkGetMemoryWin32HandleKHR, &m_hHandle);
|
||||
}
|
||||
}
|
||||
|
||||
*pHandle = Duplicate(hTargetProcess);
|
||||
return res;
|
||||
}
|
||||
|
||||
operator bool() const noexcept { return m_hHandle != VMA_NULL; }
|
||||
private:
|
||||
// Not atomic
|
||||
static VkResult Create(VkDevice device, VkDeviceMemory memory, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE* pHandle) noexcept
|
||||
{
|
||||
VkResult res = VK_ERROR_FEATURE_NOT_PRESENT;
|
||||
if (pvkGetMemoryWin32HandleKHR != VMA_NULL)
|
||||
{
|
||||
VkMemoryGetWin32HandleInfoKHR handleInfo{ };
|
||||
handleInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
|
||||
handleInfo.memory = memory;
|
||||
handleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
|
||||
res = pvkGetMemoryWin32HandleKHR(device, &handleInfo, pHandle);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
HANDLE Duplicate(HANDLE hTargetProcess = VMA_NULL) const noexcept
|
||||
{
|
||||
if (!m_hHandle)
|
||||
return m_hHandle;
|
||||
|
||||
HANDLE hCurrentProcess = ::GetCurrentProcess();
|
||||
HANDLE hDupHandle = VMA_NULL;
|
||||
if (!::DuplicateHandle(hCurrentProcess, m_hHandle, hTargetProcess ? hTargetProcess : hCurrentProcess, &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
VMA_ASSERT(0 && "Failed to duplicate handle.");
|
||||
}
|
||||
return hDupHandle;
|
||||
}
|
||||
private:
|
||||
HANDLE m_hHandle;
|
||||
VMA_RW_MUTEX m_Mutex; // Protects access m_Handle
|
||||
};
|
||||
#else
|
||||
class VmaWin32Handle
|
||||
{
|
||||
// ABI compatibility
|
||||
void* placeholder = VMA_NULL;
|
||||
VMA_RW_MUTEX placeholder2;
|
||||
};
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
|
||||
|
||||
#ifndef _VMA_DEVICE_MEMORY_BLOCK
|
||||
/*
|
||||
Represents a single block of device memory (`VkDeviceMemory`) with all the
|
||||
@@ -6139,7 +6274,13 @@ public:
|
||||
VkDeviceSize allocationLocalOffset,
|
||||
VkImage hImage,
|
||||
const void* pNext);
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VkResult CreateWin32Handle(
|
||||
const VmaAllocator hAllocator,
|
||||
PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR,
|
||||
HANDLE hTargetProcess,
|
||||
HANDLE* pHandle)noexcept;
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
private:
|
||||
VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
|
||||
uint32_t m_MemoryTypeIndex;
|
||||
@@ -6155,10 +6296,18 @@ private:
|
||||
VmaMappingHysteresis m_MappingHysteresis;
|
||||
uint32_t m_MapCount;
|
||||
void* m_pMappedData;
|
||||
|
||||
VmaWin32Handle m_Handle;
|
||||
};
|
||||
#endif // _VMA_DEVICE_MEMORY_BLOCK
|
||||
|
||||
#ifndef _VMA_ALLOCATION_T
|
||||
struct VmaAllocationExtraData
|
||||
{
|
||||
void* m_pMappedData = VMA_NULL; // Not null means memory is mapped.
|
||||
VmaWin32Handle m_Handle;
|
||||
};
|
||||
|
||||
struct VmaAllocation_T
|
||||
{
|
||||
friend struct VmaDedicatedAllocationListItemTraits;
|
||||
@@ -6191,12 +6340,14 @@ public:
|
||||
bool mapped);
|
||||
// pMappedData not null means allocation is created with MAPPED flag.
|
||||
void InitDedicatedAllocation(
|
||||
VmaAllocator allocator,
|
||||
VmaPool hParentPool,
|
||||
uint32_t memoryTypeIndex,
|
||||
VkDeviceMemory hMemory,
|
||||
VmaSuballocationType suballocationType,
|
||||
void* pMappedData,
|
||||
VkDeviceSize size);
|
||||
void Destroy(VmaAllocator allocator);
|
||||
|
||||
ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }
|
||||
VkDeviceSize GetAlignment() const { return m_Alignment; }
|
||||
@@ -6240,6 +6391,10 @@ public:
|
||||
void PrintParameters(class VmaJsonWriter& json) const;
|
||||
#endif
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VkResult GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* hHandle) noexcept;
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
|
||||
private:
|
||||
// Allocation out of VmaDeviceMemoryBlock.
|
||||
struct BlockAllocation
|
||||
@@ -6252,7 +6407,7 @@ private:
|
||||
{
|
||||
VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
|
||||
VkDeviceMemory m_hMemory;
|
||||
void* m_pMappedData; // Not null means memory is mapped.
|
||||
VmaAllocationExtraData* m_ExtraData;
|
||||
VmaAllocation_T* m_Prev;
|
||||
VmaAllocation_T* m_Next;
|
||||
};
|
||||
@@ -6277,6 +6432,8 @@ private:
|
||||
#if VMA_STATS_STRING_ENABLED
|
||||
VmaBufferImageUsage m_BufferImageUsage; // 0 if unknown.
|
||||
#endif
|
||||
|
||||
void EnsureExtraData(VmaAllocator hAllocator);
|
||||
};
|
||||
#endif // _VMA_ALLOCATION_T
|
||||
|
||||
@@ -10075,6 +10232,7 @@ public:
|
||||
bool m_UseExtMemoryPriority;
|
||||
bool m_UseKhrMaintenance4;
|
||||
bool m_UseKhrMaintenance5;
|
||||
bool m_UseKhrExternalMemoryWin32;
|
||||
const VkDevice m_hDevice;
|
||||
const VkInstance m_hInstance;
|
||||
const bool m_AllocationCallbacksSpecified;
|
||||
@@ -10438,7 +10596,7 @@ VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator)
|
||||
m_Id(0),
|
||||
m_hMemory(VK_NULL_HANDLE),
|
||||
m_MapCount(0),
|
||||
m_pMappedData(VMA_NULL) {}
|
||||
m_pMappedData(VMA_NULL){}
|
||||
|
||||
VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock()
|
||||
{
|
||||
@@ -10681,6 +10839,14 @@ VkResult VmaDeviceMemoryBlock::BindImageMemory(
|
||||
VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);
|
||||
return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext);
|
||||
}
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VkResult VmaDeviceMemoryBlock::CreateWin32Handle(const VmaAllocator hAllocator, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, HANDLE* pHandle) noexcept
|
||||
{
|
||||
VMA_ASSERT(pHandle);
|
||||
return m_Handle.GetHandle(hAllocator->m_hDevice, m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle);
|
||||
}
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
#endif // _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS
|
||||
|
||||
#ifndef _VMA_ALLOCATION_T_FUNCTIONS
|
||||
@@ -10733,6 +10899,7 @@ void VmaAllocation_T::InitBlockAllocation(
|
||||
}
|
||||
|
||||
void VmaAllocation_T::InitDedicatedAllocation(
|
||||
VmaAllocator allocator,
|
||||
VmaPool hParentPool,
|
||||
uint32_t memoryTypeIndex,
|
||||
VkDeviceMemory hMemory,
|
||||
@@ -10747,16 +10914,29 @@ void VmaAllocation_T::InitDedicatedAllocation(
|
||||
m_Size = size;
|
||||
m_MemoryTypeIndex = memoryTypeIndex;
|
||||
m_SuballocationType = (uint8_t)suballocationType;
|
||||
if(pMappedData != VMA_NULL)
|
||||
m_DedicatedAllocation.m_ExtraData = VMA_NULL;
|
||||
m_DedicatedAllocation.m_hParentPool = hParentPool;
|
||||
m_DedicatedAllocation.m_hMemory = hMemory;
|
||||
m_DedicatedAllocation.m_Prev = VMA_NULL;
|
||||
m_DedicatedAllocation.m_Next = VMA_NULL;
|
||||
|
||||
if (pMappedData != VMA_NULL)
|
||||
{
|
||||
VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
|
||||
m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP;
|
||||
EnsureExtraData(allocator);
|
||||
m_DedicatedAllocation.m_ExtraData->m_pMappedData = pMappedData;
|
||||
}
|
||||
}
|
||||
|
||||
void VmaAllocation_T::Destroy(VmaAllocator allocator)
|
||||
{
|
||||
FreeName(allocator);
|
||||
|
||||
if (GetType() == ALLOCATION_TYPE_DEDICATED)
|
||||
{
|
||||
vma_delete(allocator, m_DedicatedAllocation.m_ExtraData);
|
||||
}
|
||||
m_DedicatedAllocation.m_hParentPool = hParentPool;
|
||||
m_DedicatedAllocation.m_hMemory = hMemory;
|
||||
m_DedicatedAllocation.m_pMappedData = pMappedData;
|
||||
m_DedicatedAllocation.m_Prev = VMA_NULL;
|
||||
m_DedicatedAllocation.m_Next = VMA_NULL;
|
||||
}
|
||||
|
||||
void VmaAllocation_T::SetName(VmaAllocator hAllocator, const char* pName)
|
||||
@@ -10861,8 +11041,9 @@ void* VmaAllocation_T::GetMappedData() const
|
||||
}
|
||||
break;
|
||||
case ALLOCATION_TYPE_DEDICATED:
|
||||
VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0 || IsPersistentMap()));
|
||||
return m_DedicatedAllocation.m_pMappedData;
|
||||
VMA_ASSERT((m_DedicatedAllocation.m_ExtraData != VMA_NULL && m_DedicatedAllocation.m_ExtraData->m_pMappedData != VMA_NULL) ==
|
||||
(m_MapCount != 0 || IsPersistentMap()));
|
||||
return m_DedicatedAllocation.m_ExtraData != VMA_NULL ? m_DedicatedAllocation.m_ExtraData->m_pMappedData : VMA_NULL;
|
||||
default:
|
||||
VMA_ASSERT(0);
|
||||
return VMA_NULL;
|
||||
@@ -10903,12 +11084,14 @@ VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppDa
|
||||
VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
|
||||
VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
|
||||
|
||||
EnsureExtraData(hAllocator);
|
||||
|
||||
if (m_MapCount != 0 || IsPersistentMap())
|
||||
{
|
||||
if (m_MapCount < 0xFF)
|
||||
{
|
||||
VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);
|
||||
*ppData = m_DedicatedAllocation.m_pMappedData;
|
||||
VMA_ASSERT(m_DedicatedAllocation.m_ExtraData->m_pMappedData != VMA_NULL);
|
||||
*ppData = m_DedicatedAllocation.m_ExtraData->m_pMappedData;
|
||||
++m_MapCount;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
@@ -10929,7 +11112,7 @@ VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppDa
|
||||
ppData);
|
||||
if (result == VK_SUCCESS)
|
||||
{
|
||||
m_DedicatedAllocation.m_pMappedData = *ppData;
|
||||
m_DedicatedAllocation.m_ExtraData->m_pMappedData = *ppData;
|
||||
m_MapCount = 1;
|
||||
}
|
||||
return result;
|
||||
@@ -10945,7 +11128,8 @@ void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator)
|
||||
--m_MapCount;
|
||||
if (m_MapCount == 0 && !IsPersistentMap())
|
||||
{
|
||||
m_DedicatedAllocation.m_pMappedData = VMA_NULL;
|
||||
VMA_ASSERT(m_DedicatedAllocation.m_ExtraData != VMA_NULL);
|
||||
m_DedicatedAllocation.m_ExtraData->m_pMappedData = VMA_NULL;
|
||||
(*hAllocator->GetVulkanFunctions().vkUnmapMemory)(
|
||||
hAllocator->m_hDevice,
|
||||
m_DedicatedAllocation.m_hMemory);
|
||||
@@ -10981,8 +11165,33 @@ void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const
|
||||
json.WriteString(m_pName);
|
||||
}
|
||||
}
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VkResult VmaAllocation_T::GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* pHandle) noexcept
|
||||
{
|
||||
auto pvkGetMemoryWin32HandleKHR = hAllocator->GetVulkanFunctions().vkGetMemoryWin32HandleKHR;
|
||||
switch (m_Type)
|
||||
{
|
||||
case ALLOCATION_TYPE_BLOCK:
|
||||
return m_BlockAllocation.m_Block->CreateWin32Handle(hAllocator, pvkGetMemoryWin32HandleKHR, hTargetProcess, pHandle);
|
||||
case ALLOCATION_TYPE_DEDICATED:
|
||||
EnsureExtraData(hAllocator);
|
||||
return m_DedicatedAllocation.m_ExtraData->m_Handle.GetHandle(hAllocator->m_hDevice, m_DedicatedAllocation.m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle);
|
||||
default:
|
||||
VMA_ASSERT(0);
|
||||
return VK_ERROR_FEATURE_NOT_PRESENT;
|
||||
}
|
||||
}
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
#endif // VMA_STATS_STRING_ENABLED
|
||||
|
||||
void VmaAllocation_T::EnsureExtraData(VmaAllocator hAllocator)
|
||||
{
|
||||
if (m_DedicatedAllocation.m_ExtraData == VMA_NULL)
|
||||
{
|
||||
m_DedicatedAllocation.m_ExtraData = vma_new(hAllocator, VmaAllocationExtraData)();
|
||||
}
|
||||
}
|
||||
|
||||
void VmaAllocation_T::FreeName(VmaAllocator hAllocator)
|
||||
{
|
||||
if(m_pName)
|
||||
@@ -11399,6 +11608,10 @@ void VmaBlockVector::Free(const VmaAllocation hAllocation)
|
||||
}
|
||||
|
||||
IncrementallySortBlocks();
|
||||
|
||||
m_hAllocator->m_Budget.RemoveAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), hAllocation->GetSize());
|
||||
hAllocation->Destroy(m_hAllocator);
|
||||
m_hAllocator->m_AllocationObjectAllocator.Free(hAllocation);
|
||||
}
|
||||
|
||||
// Destruction of a free block. Deferred until this point, outside of mutex
|
||||
@@ -11409,9 +11622,6 @@ void VmaBlockVector::Free(const VmaAllocation hAllocation)
|
||||
pBlockToDelete->Destroy(m_hAllocator);
|
||||
vma_delete(m_hAllocator, pBlockToDelete);
|
||||
}
|
||||
|
||||
m_hAllocator->m_Budget.RemoveAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), hAllocation->GetSize());
|
||||
m_hAllocator->m_AllocationObjectAllocator.Free(hAllocation);
|
||||
}
|
||||
|
||||
VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const
|
||||
@@ -12711,6 +12921,7 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
|
||||
m_UseExtMemoryPriority((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT) != 0),
|
||||
m_UseKhrMaintenance4((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT) != 0),
|
||||
m_UseKhrMaintenance5((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT) != 0),
|
||||
m_UseKhrExternalMemoryWin32((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT) != 0),
|
||||
m_hDevice(pCreateInfo->device),
|
||||
m_hInstance(pCreateInfo->instance),
|
||||
m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL),
|
||||
@@ -12802,6 +13013,19 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
|
||||
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
||||
}
|
||||
#endif
|
||||
#if !(VMA_KHR_MAINTENANCE5)
|
||||
if(m_UseKhrMaintenance5)
|
||||
{
|
||||
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !(VMA_EXTERNAL_MEMORY_WIN32)
|
||||
if(m_UseKhrExternalMemoryWin32)
|
||||
{
|
||||
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks));
|
||||
memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties));
|
||||
@@ -13026,7 +13250,9 @@ void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVul
|
||||
VMA_COPY_IF_NOT_NULL(vkGetDeviceBufferMemoryRequirements);
|
||||
VMA_COPY_IF_NOT_NULL(vkGetDeviceImageMemoryRequirements);
|
||||
#endif
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VMA_COPY_IF_NOT_NULL(vkGetMemoryWin32HandleKHR);
|
||||
#endif
|
||||
#undef VMA_COPY_IF_NOT_NULL
|
||||
}
|
||||
|
||||
@@ -13128,7 +13354,12 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
|
||||
VMA_FETCH_DEVICE_FUNC(vkGetDeviceImageMemoryRequirements, PFN_vkGetDeviceImageMemoryRequirementsKHR, "vkGetDeviceImageMemoryRequirementsKHR");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
if (m_UseKhrExternalMemoryWin32)
|
||||
{
|
||||
VMA_FETCH_DEVICE_FUNC(vkGetMemoryWin32HandleKHR, PFN_vkGetMemoryWin32HandleKHR, "vkGetMemoryWin32HandleKHR");
|
||||
}
|
||||
#endif
|
||||
#undef VMA_FETCH_DEVICE_FUNC
|
||||
#undef VMA_FETCH_INSTANCE_FUNC
|
||||
}
|
||||
@@ -13177,6 +13408,12 @@ void VmaAllocator_T::ValidateVulkanFunctions()
|
||||
VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);
|
||||
}
|
||||
#endif
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
if (m_UseKhrExternalMemoryWin32)
|
||||
{
|
||||
VMA_ASSERT(m_VulkanFunctions.vkGetMemoryWin32HandleKHR != VMA_NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Not validating these due to suspected driver bugs with these function
|
||||
// pointers being null despite correct extension or Vulkan version is enabled.
|
||||
@@ -13527,7 +13764,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemoryPage(
|
||||
}
|
||||
|
||||
*pAllocation = m_AllocationObjectAllocator.Allocate(isMappingAllowed);
|
||||
(*pAllocation)->InitDedicatedAllocation(pool, memTypeIndex, hMemory, suballocType, pMappedData, size);
|
||||
(*pAllocation)->InitDedicatedAllocation(this, pool, memTypeIndex, hMemory, suballocType, pMappedData, size);
|
||||
if (isUserDataString)
|
||||
(*pAllocation)->SetName(this, (const char*)pUserData);
|
||||
else
|
||||
@@ -13863,8 +14100,6 @@ void VmaAllocator_T::FreeMemory(
|
||||
FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);
|
||||
}
|
||||
|
||||
allocation->FreeName(this);
|
||||
|
||||
switch(allocation->GetType())
|
||||
{
|
||||
case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
|
||||
@@ -14335,7 +14570,6 @@ VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData)
|
||||
}
|
||||
return res;
|
||||
}
|
||||
VMA_FALLTHROUGH; // Fallthrough
|
||||
case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
|
||||
return hAllocation->DedicatedAllocMap(this, ppData);
|
||||
default:
|
||||
@@ -14549,6 +14783,7 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)
|
||||
FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);
|
||||
|
||||
m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize());
|
||||
allocation->Destroy(this);
|
||||
m_AllocationObjectAllocator.Free(allocation);
|
||||
|
||||
VMA_DEBUG_LOG_FORMAT(" Freed DedicatedMemory MemoryTypeIndex=%" PRIu32, memTypeIndex);
|
||||
@@ -16169,7 +16404,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
|
||||
pImageCreateInfo,
|
||||
allocator->GetAllocationCallbacks(),
|
||||
pImage);
|
||||
if(res >= 0)
|
||||
if(res == VK_SUCCESS)
|
||||
{
|
||||
VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ?
|
||||
VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL :
|
||||
@@ -16194,14 +16429,14 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
|
||||
1, // allocationCount
|
||||
pAllocation);
|
||||
|
||||
if(res >= 0)
|
||||
if(res == VK_SUCCESS)
|
||||
{
|
||||
// 3. Bind image with memory.
|
||||
if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)
|
||||
{
|
||||
res = allocator->BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL);
|
||||
}
|
||||
if(res >= 0)
|
||||
if(res == VK_SUCCESS)
|
||||
{
|
||||
// All steps succeeded.
|
||||
#if VMA_STATS_STRING_ENABLED
|
||||
@@ -16434,6 +16669,15 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock V
|
||||
VmaFreeString(virtualBlock->GetAllocationCallbacks(), pStatsString);
|
||||
}
|
||||
}
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle(VmaAllocator VMA_NOT_NULL allocator,
|
||||
VmaAllocation VMA_NOT_NULL allocation, HANDLE hTargetProcess, HANDLE* VMA_NOT_NULL pHandle)
|
||||
{
|
||||
VMA_ASSERT(allocator && allocation && pHandle);
|
||||
VMA_DEBUG_GLOBAL_MUTEX_LOCK;
|
||||
return allocation->GetWin32Handle(allocator, hTargetProcess, pHandle);
|
||||
}
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
#endif // VMA_STATS_STRING_ENABLED
|
||||
#endif // _VMA_PUBLIC_INTERFACE
|
||||
#endif // VMA_IMPLEMENTATION
|
||||
@@ -16567,6 +16811,7 @@ VK_EXT_memory_budget | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT
|
||||
VK_KHR_buffer_device_address | #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
|
||||
VK_EXT_memory_priority | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT
|
||||
VK_AMD_device_coherent_memory | #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT
|
||||
VK_KHR_external_memory_win32 | #VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT
|
||||
|
||||
Example with fetching pointers to Vulkan functions dynamically:
|
||||
|
||||
@@ -17053,7 +17298,7 @@ implementation whether the allocation succeeds or fails. You can change this beh
|
||||
by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is
|
||||
not made if it would exceed the budget or if the budget is already exceeded.
|
||||
VMA then tries to make the allocation from the next eligible Vulkan memory type.
|
||||
The all of them fail, the call then fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
|
||||
If all of them fail, the call then fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
|
||||
Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag
|
||||
when creating resources that are not essential for the application (e.g. the texture
|
||||
of a specific object) and not to pass it when creating critically important resources
|
||||
@@ -18193,7 +18438,8 @@ allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||
VkBuffer buf;
|
||||
VmaAllocation alloc;
|
||||
VmaAllocationInfo allocInfo;
|
||||
vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
|
||||
VkResult result = vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
|
||||
// Check result...
|
||||
|
||||
VkMemoryPropertyFlags memPropFlags;
|
||||
vmaGetAllocationMemoryProperties(allocator, alloc, &memPropFlags);
|
||||
@@ -18204,10 +18450,24 @@ if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||
|
||||
// [Executed in runtime]:
|
||||
memcpy(allocInfo.pMappedData, myData, myDataSize);
|
||||
result = vmaFlushAllocation(allocator, alloc, 0, VK_WHOLE_SIZE);
|
||||
// Check result...
|
||||
|
||||
VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
|
||||
bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
|
||||
bufMemBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT;
|
||||
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier.buffer = buf;
|
||||
bufMemBarrier.offset = 0;
|
||||
bufMemBarrier.size = VK_WHOLE_SIZE;
|
||||
|
||||
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
|
||||
0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocation ended up in a non-mappable memory - need to transfer.
|
||||
// Allocation ended up in a non-mappable memory - a transfer using a staging buffer is required.
|
||||
VkBufferCreateInfo stagingBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
stagingBufCreateInfo.size = 65536;
|
||||
stagingBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
@@ -18220,18 +18480,46 @@ else
|
||||
VkBuffer stagingBuf;
|
||||
VmaAllocation stagingAlloc;
|
||||
VmaAllocationInfo stagingAllocInfo;
|
||||
vmaCreateBuffer(allocator, &stagingBufCreateInfo, &stagingAllocCreateInfo,
|
||||
&stagingBuf, &stagingAlloc, stagingAllocInfo);
|
||||
result = vmaCreateBuffer(allocator, &stagingBufCreateInfo, &stagingAllocCreateInfo,
|
||||
&stagingBuf, &stagingAlloc, &stagingAllocInfo);
|
||||
// Check result...
|
||||
|
||||
// [Executed in runtime]:
|
||||
memcpy(stagingAllocInfo.pMappedData, myData, myDataSize);
|
||||
vmaFlushAllocation(allocator, stagingAlloc, 0, VK_WHOLE_SIZE);
|
||||
//vkCmdPipelineBarrier: VK_ACCESS_HOST_WRITE_BIT --> VK_ACCESS_TRANSFER_READ_BIT
|
||||
result = vmaFlushAllocation(allocator, stagingAlloc, 0, VK_WHOLE_SIZE);
|
||||
// Check result...
|
||||
|
||||
VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
|
||||
bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
|
||||
bufMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier.buffer = stagingBuf;
|
||||
bufMemBarrier.offset = 0;
|
||||
bufMemBarrier.size = VK_WHOLE_SIZE;
|
||||
|
||||
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
|
||||
|
||||
VkBufferCopy bufCopy = {
|
||||
0, // srcOffset
|
||||
0, // dstOffset,
|
||||
myDataSize); // size
|
||||
myDataSize, // size
|
||||
};
|
||||
|
||||
vkCmdCopyBuffer(cmdBuf, stagingBuf, buf, 1, &bufCopy);
|
||||
|
||||
VkBufferMemoryBarrier bufMemBarrier2 = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
|
||||
bufMemBarrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
bufMemBarrier2.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; // We created a uniform buffer
|
||||
bufMemBarrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier2.buffer = buf;
|
||||
bufMemBarrier2.offset = 0;
|
||||
bufMemBarrier2.size = VK_WHOLE_SIZE;
|
||||
|
||||
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
|
||||
0, 0, nullptr, 1, &bufMemBarrier2, 0, nullptr);
|
||||
}
|
||||
\endcode
|
||||
|
||||
@@ -18264,14 +18552,22 @@ Please check "CONFIGURATION SECTION" in the code to find macros that you can def
|
||||
before each include of this file or change directly in this file to provide
|
||||
your own implementation of basic facilities like assert, `min()` and `max()` functions,
|
||||
mutex, atomic etc.
|
||||
The library uses its own implementation of containers by default, but you can switch to using
|
||||
STL containers instead.
|
||||
|
||||
For example, define `VMA_ASSERT(expr)` before including the library to provide
|
||||
custom implementation of the assertion, compatible with your project.
|
||||
By default it is defined to standard C `assert(expr)` in `_DEBUG` configuration
|
||||
and empty otherwise.
|
||||
|
||||
Similarly, you can define `VMA_LEAK_LOG_FORMAT` macro to enable printing of leaked (unfreed) allocations,
|
||||
including their names and other parameters. Example:
|
||||
|
||||
\code
|
||||
#define VMA_LEAK_LOG_FORMAT(format, ...) do { \
|
||||
printf((format), __VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} while(false)
|
||||
\endcode
|
||||
|
||||
\section config_Vulkan_functions Pointers to Vulkan functions
|
||||
|
||||
There are multiple ways to import pointers to Vulkan functions in the library.
|
||||
@@ -18526,6 +18822,145 @@ Example use of this extension can be found in the code of the sample and test su
|
||||
accompanying this library.
|
||||
|
||||
|
||||
\page vk_khr_external_memory_win32 VK_KHR_external_memory_win32
|
||||
|
||||
On Windows, the VK_KHR_external_memory_win32 device extension allows exporting a Win32 `HANDLE`
|
||||
of a `VkDeviceMemory` block, to be able to reference the memory on other Vulkan logical devices or instances,
|
||||
in multiple processes, and/or in multiple APIs.
|
||||
VMA offers support for it.
|
||||
|
||||
\section vk_khr_external_memory_win32_initialization Initialization
|
||||
|
||||
1) Make sure the extension is defined in the code by including following header before including VMA:
|
||||
|
||||
\code
|
||||
#include <vulkan/vulkan_win32.h>
|
||||
\endcode
|
||||
|
||||
2) Check if "VK_KHR_external_memory_win32" is available among device extensions.
|
||||
Enable it when creating the `VkDevice` object.
|
||||
|
||||
3) Enable the usage of this extension in VMA by setting flag #VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT
|
||||
when calling vmaCreateAllocator().
|
||||
|
||||
4) Make sure that VMA has access to the `vkGetMemoryWin32HandleKHR` function by either enabling `VMA_DYNAMIC_VULKAN_FUNCTIONS` macro
|
||||
or setting VmaVulkanFunctions::vkGetMemoryWin32HandleKHR explicitly.
|
||||
For more information, see \ref quick_start_initialization_importing_vulkan_functions.
|
||||
|
||||
\section vk_khr_external_memory_win32_preparations Preparations
|
||||
|
||||
You can find example usage among tests, in file "Tests.cpp", function `TestWin32Handles()`.
|
||||
|
||||
To use the extenion, buffers need to be created with `VkExternalMemoryBufferCreateInfoKHR` attached to their `pNext` chain,
|
||||
and memory allocations need to be made with `VkExportMemoryAllocateInfoKHR` attached to their `pNext` chain.
|
||||
To make use of them, you need to use \ref custom_memory_pools. Example:
|
||||
|
||||
\code
|
||||
// Define an example buffer and allocation parameters.
|
||||
VkExternalMemoryBufferCreateInfoKHR externalMemBufCreateInfo = {
|
||||
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
|
||||
nullptr,
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
|
||||
};
|
||||
VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
exampleBufCreateInfo.size = 0x10000; // Doesn't matter here.
|
||||
exampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
exampleBufCreateInfo.pNext = &externalMemBufCreateInfo;
|
||||
|
||||
VmaAllocationCreateInfo exampleAllocCreateInfo = {};
|
||||
exampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||
|
||||
// Find memory type index to use for the custom pool.
|
||||
uint32_t memTypeIndex;
|
||||
VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_Allocator,
|
||||
&exampleBufCreateInfo, &exampleAllocCreateInfo, &memTypeIndex);
|
||||
// Check res...
|
||||
|
||||
// Create a custom pool.
|
||||
constexpr static VkExportMemoryAllocateInfoKHR exportMemAllocInfo = {
|
||||
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
|
||||
nullptr,
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
|
||||
};
|
||||
VmaPoolCreateInfo poolCreateInfo = {};
|
||||
poolCreateInfo.memoryTypeIndex = memTypeIndex;
|
||||
poolCreateInfo.pMemoryAllocateNext = (void*)&exportMemAllocInfo;
|
||||
|
||||
VmaPool pool;
|
||||
res = vmaCreatePool(g_Allocator, &poolCreateInfo, &pool);
|
||||
// Check res...
|
||||
|
||||
// YOUR OTHER CODE COMES HERE....
|
||||
|
||||
// At the end, don't forget to destroy it!
|
||||
vmaDestroyPool(g_Allocator, pool);
|
||||
\endcode
|
||||
|
||||
Note that the structure passed as VmaPoolCreateInfo::pMemoryAllocateNext must remain alive and unchanged
|
||||
for the whole lifetime of the custom pool, because it will be used when the pool allocates a new device memory block.
|
||||
No copy is made internally. This is why variable `exportMemAllocInfo` is defined as `static`.
|
||||
|
||||
\section vk_khr_external_memory_win32_memory_allocation Memory allocation
|
||||
|
||||
Finally, you can create a buffer with an allocation out of the custom pool.
|
||||
The buffer should use same flags as the sample buffer used to find the memory type.
|
||||
It should also specify `VkExternalMemoryBufferCreateInfoKHR` in its `pNext` chain.
|
||||
|
||||
\code
|
||||
VkExternalMemoryBufferCreateInfoKHR externalMemBufCreateInfo = {
|
||||
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
|
||||
nullptr,
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
|
||||
};
|
||||
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
bufCreateInfo.size = // Your desired buffer size.
|
||||
bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
bufCreateInfo.pNext = &externalMemBufCreateInfo;
|
||||
|
||||
VmaAllocationCreateInfo allocCreateInfo = {};
|
||||
allocCreateInfo.pool = pool; // It is enough to set this one member.
|
||||
|
||||
VkBuffer buf;
|
||||
VmaAllocation alloc;
|
||||
res = vmaCreateBuffer(g_Allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr);
|
||||
// Check res...
|
||||
|
||||
// YOUR OTHER CODE COMES HERE....
|
||||
|
||||
// At the end, don't forget to destroy it!
|
||||
vmaDestroyBuffer(g_Allocator, buf, alloc);
|
||||
\endcode
|
||||
|
||||
If you need each allocation to have its own device memory block and start at offset 0, you can still do
|
||||
by using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag. It works also with custom pools.
|
||||
|
||||
\section vk_khr_external_memory_win32_exporting_win32_handle Exporting Win32 handle
|
||||
|
||||
After the allocation is created, you can acquire a Win32 `HANDLE` to the `VkDeviceMemory` block it belongs to.
|
||||
VMA function vmaGetMemoryWin32Handle() is a replacement of the Vulkan function `vkGetMemoryWin32HandleKHR`.
|
||||
|
||||
\code
|
||||
HANDLE handle;
|
||||
res = vmaGetMemoryWin32Handle(g_Allocator, alloc, nullptr, &handle);
|
||||
// Check res...
|
||||
|
||||
// YOUR OTHER CODE COMES HERE....
|
||||
|
||||
// At the end, you must close the handle.
|
||||
CloseHandle(handle);
|
||||
\endcode
|
||||
|
||||
Documentation of the VK_KHR_external_memory_win32 extension states that:
|
||||
|
||||
> If handleType is defined as an NT handle, vkGetMemoryWin32HandleKHR must be called no more than once for each valid unique combination of memory and handleType.
|
||||
|
||||
This is ensured automatically inside VMA.
|
||||
The library fetches the handle on first use, remembers it internally, and closes it when the memory block or dedicated allocation is destroyed.
|
||||
Every time you call vmaGetMemoryWin32Handle(), VMA calls `DuplicateHandle` and returns a new handle that you need to close.
|
||||
|
||||
For further information, please check documentation of the vmaGetMemoryWin32Handle() function.
|
||||
|
||||
|
||||
\page enabling_buffer_device_address Enabling buffer device address
|
||||
|
||||
Device extension VK_KHR_buffer_device_address
|
||||
|
||||
523
3rdparty/vulkan/include/vulkan/vk_mem_alloc.h
vendored
523
3rdparty/vulkan/include/vulkan/vk_mem_alloc.h
vendored
@@ -95,6 +95,7 @@ See also: [product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-me
|
||||
- \subpage enabling_buffer_device_address
|
||||
- \subpage vk_ext_memory_priority
|
||||
- \subpage vk_amd_device_coherent_memory
|
||||
- \subpage vk_khr_external_memory_win32
|
||||
- \subpage general_considerations
|
||||
- [Thread safety](@ref general_considerations_thread_safety)
|
||||
- [Versioning and compatibility](@ref general_considerations_versioning_and_compatibility)
|
||||
@@ -127,7 +128,9 @@ See documentation chapter: \ref statistics.
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(VULKAN_H_)
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
|
||||
#if !defined(VMA_VULKAN_VERSION)
|
||||
#if defined(VK_VERSION_1_3)
|
||||
@@ -240,6 +243,15 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Defined to 1 when VK_KHR_external_memory_win32 device extension is defined in Vulkan headers.
|
||||
#if !defined(VMA_EXTERNAL_MEMORY_WIN32)
|
||||
#if VK_KHR_external_memory_win32
|
||||
#define VMA_EXTERNAL_MEMORY_WIN32 1
|
||||
#else
|
||||
#define VMA_EXTERNAL_MEMORY_WIN32 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Define these macros to decorate all public functions with additional code,
|
||||
// before and after returned type, appropriately. This may be useful for
|
||||
// exporting the functions when compiling VMA as a separate library. Example:
|
||||
@@ -459,6 +471,15 @@ typedef enum VmaAllocatorCreateFlagBits
|
||||
*/
|
||||
VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT = 0x00000100,
|
||||
|
||||
/**
|
||||
Enables usage of VK_KHR_external_memory_win32 extension in the library.
|
||||
|
||||
You should set this flag if you found available and enabled this device extension,
|
||||
while creating Vulkan device passed as VmaAllocatorCreateInfo::device.
|
||||
For more information, see \ref vk_khr_external_memory_win32.
|
||||
*/
|
||||
VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT = 0x00000200,
|
||||
|
||||
VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||
} VmaAllocatorCreateFlagBits;
|
||||
/// See #VmaAllocatorCreateFlagBits.
|
||||
@@ -1033,6 +1054,11 @@ typedef struct VmaVulkanFunctions
|
||||
/// Fetch from "vkGetDeviceImageMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceImageMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4.
|
||||
PFN_vkGetDeviceImageMemoryRequirementsKHR VMA_NULLABLE vkGetDeviceImageMemoryRequirements;
|
||||
#endif
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
PFN_vkGetMemoryWin32HandleKHR VMA_NULLABLE vkGetMemoryWin32HandleKHR;
|
||||
#else
|
||||
void* VMA_NULLABLE vkGetMemoryWin32HandleKHR;
|
||||
#endif
|
||||
} VmaVulkanFunctions;
|
||||
|
||||
/// Description of a Allocator to be created.
|
||||
@@ -1810,6 +1836,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(
|
||||
\param allocator Allocator object.
|
||||
\param pool Pool object.
|
||||
\param[out] pPoolStats Statistics of specified pool.
|
||||
|
||||
Note that when using the pool from multiple threads, returned information may immediately
|
||||
become outdated.
|
||||
*/
|
||||
VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics(
|
||||
VmaAllocator VMA_NOT_NULL allocator,
|
||||
@@ -2050,6 +2079,40 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties(
|
||||
VmaAllocation VMA_NOT_NULL allocation,
|
||||
VkMemoryPropertyFlags* VMA_NOT_NULL pFlags);
|
||||
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
/**
|
||||
\brief Given an allocation, returns Win32 handle that may be imported by other processes or APIs.
|
||||
|
||||
\param hTargetProcess Must be a valid handle to target process or null. If it's null, the function returns
|
||||
handle for the current process.
|
||||
\param[out] pHandle Output parameter that returns the handle.
|
||||
|
||||
The function fills `pHandle` with handle that can be used in target process.
|
||||
The handle is fetched using function `vkGetMemoryWin32HandleKHR`.
|
||||
When no longer needed, you must close it using:
|
||||
|
||||
\code
|
||||
CloseHandle(handle);
|
||||
\endcode
|
||||
|
||||
You can close it any time, before or after destroying the allocation object.
|
||||
It is reference-counted internally by Windows.
|
||||
|
||||
Note the handle is returned for the entire `VkDeviceMemory` block that the allocation belongs to.
|
||||
If the allocation is sub-allocated from a larger block, you may need to consider the offset of the allocation
|
||||
(VmaAllocationInfo::offset).
|
||||
|
||||
If the function fails with `VK_ERROR_FEATURE_NOT_PRESENT` error code, please double-check
|
||||
that VmaVulkanFunctions::vkGetMemoryWin32HandleKHR function pointer is set, e.g. either by using `VMA_DYNAMIC_VULKAN_FUNCTIONS`
|
||||
or by manually passing it through VmaAllocatorCreateInfo::pVulkanFunctions.
|
||||
|
||||
For more information, see chapter \ref vk_khr_external_memory_win32.
|
||||
*/
|
||||
VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle(VmaAllocator VMA_NOT_NULL allocator,
|
||||
VmaAllocation VMA_NOT_NULL allocation, HANDLE hTargetProcess, HANDLE* VMA_NOT_NULL pHandle);
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
|
||||
/** \brief Maps memory represented by given allocation and returns pointer to it.
|
||||
|
||||
Maps memory represented by given allocation to make it accessible to CPU code.
|
||||
@@ -3097,7 +3160,7 @@ static void vma_aligned_free(void* VMA_NULLABLE ptr)
|
||||
std::shared_mutex m_Mutex;
|
||||
};
|
||||
#define VMA_RW_MUTEX VmaRWMutex
|
||||
#elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600
|
||||
#elif defined(_WIN32) && defined(WINVER) && defined(SRWLOCK_INIT) && WINVER >= 0x0600
|
||||
// Use SRWLOCK from WinAPI.
|
||||
// Minimum supported client = Windows Vista, server = Windows Server 2008.
|
||||
class VmaRWMutex
|
||||
@@ -3838,12 +3901,6 @@ struct VmaBufferImageUsage
|
||||
|
||||
const VmaBufferImageUsage VmaBufferImageUsage::UNKNOWN = VmaBufferImageUsage(0);
|
||||
|
||||
static void swap(VmaBufferImageUsage& lhs, VmaBufferImageUsage& rhs) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(lhs.Value, rhs.Value);
|
||||
}
|
||||
|
||||
VmaBufferImageUsage::VmaBufferImageUsage(const VkBufferCreateInfo &createInfo,
|
||||
bool useKhrMaintenance5)
|
||||
{
|
||||
@@ -6073,6 +6130,84 @@ private:
|
||||
|
||||
#endif // _VMA_MAPPING_HYSTERESIS
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
class VmaWin32Handle
|
||||
{
|
||||
public:
|
||||
VmaWin32Handle() noexcept : m_hHandle(VMA_NULL) { }
|
||||
explicit VmaWin32Handle(HANDLE hHandle) noexcept : m_hHandle(hHandle) { }
|
||||
~VmaWin32Handle() noexcept { if (m_hHandle != VMA_NULL) { ::CloseHandle(m_hHandle); } }
|
||||
VMA_CLASS_NO_COPY_NO_MOVE(VmaWin32Handle)
|
||||
|
||||
public:
|
||||
// Strengthened
|
||||
VkResult GetHandle(VkDevice device, VkDeviceMemory memory, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, bool useMutex, HANDLE* pHandle) noexcept
|
||||
{
|
||||
*pHandle = VMA_NULL;
|
||||
// Try to get handle first.
|
||||
if (m_hHandle != VMA_NULL)
|
||||
{
|
||||
*pHandle = Duplicate(hTargetProcess);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult res = VK_SUCCESS;
|
||||
// If failed, try to create it.
|
||||
{
|
||||
VmaMutexLockWrite lock(m_Mutex, useMutex);
|
||||
if (m_hHandle == VMA_NULL)
|
||||
{
|
||||
res = Create(device, memory, pvkGetMemoryWin32HandleKHR, &m_hHandle);
|
||||
}
|
||||
}
|
||||
|
||||
*pHandle = Duplicate(hTargetProcess);
|
||||
return res;
|
||||
}
|
||||
|
||||
operator bool() const noexcept { return m_hHandle != VMA_NULL; }
|
||||
private:
|
||||
// Not atomic
|
||||
static VkResult Create(VkDevice device, VkDeviceMemory memory, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE* pHandle) noexcept
|
||||
{
|
||||
VkResult res = VK_ERROR_FEATURE_NOT_PRESENT;
|
||||
if (pvkGetMemoryWin32HandleKHR != VMA_NULL)
|
||||
{
|
||||
VkMemoryGetWin32HandleInfoKHR handleInfo{ };
|
||||
handleInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
|
||||
handleInfo.memory = memory;
|
||||
handleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
|
||||
res = pvkGetMemoryWin32HandleKHR(device, &handleInfo, pHandle);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
HANDLE Duplicate(HANDLE hTargetProcess = VMA_NULL) const noexcept
|
||||
{
|
||||
if (!m_hHandle)
|
||||
return m_hHandle;
|
||||
|
||||
HANDLE hCurrentProcess = ::GetCurrentProcess();
|
||||
HANDLE hDupHandle = VMA_NULL;
|
||||
if (!::DuplicateHandle(hCurrentProcess, m_hHandle, hTargetProcess ? hTargetProcess : hCurrentProcess, &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
VMA_ASSERT(0 && "Failed to duplicate handle.");
|
||||
}
|
||||
return hDupHandle;
|
||||
}
|
||||
private:
|
||||
HANDLE m_hHandle;
|
||||
VMA_RW_MUTEX m_Mutex; // Protects access m_Handle
|
||||
};
|
||||
#else
|
||||
class VmaWin32Handle
|
||||
{
|
||||
// ABI compatibility
|
||||
void* placeholder = VMA_NULL;
|
||||
VMA_RW_MUTEX placeholder2;
|
||||
};
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
|
||||
|
||||
#ifndef _VMA_DEVICE_MEMORY_BLOCK
|
||||
/*
|
||||
Represents a single block of device memory (`VkDeviceMemory`) with all the
|
||||
@@ -6139,7 +6274,13 @@ public:
|
||||
VkDeviceSize allocationLocalOffset,
|
||||
VkImage hImage,
|
||||
const void* pNext);
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VkResult CreateWin32Handle(
|
||||
const VmaAllocator hAllocator,
|
||||
PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR,
|
||||
HANDLE hTargetProcess,
|
||||
HANDLE* pHandle)noexcept;
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
private:
|
||||
VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
|
||||
uint32_t m_MemoryTypeIndex;
|
||||
@@ -6155,10 +6296,18 @@ private:
|
||||
VmaMappingHysteresis m_MappingHysteresis;
|
||||
uint32_t m_MapCount;
|
||||
void* m_pMappedData;
|
||||
|
||||
VmaWin32Handle m_Handle;
|
||||
};
|
||||
#endif // _VMA_DEVICE_MEMORY_BLOCK
|
||||
|
||||
#ifndef _VMA_ALLOCATION_T
|
||||
struct VmaAllocationExtraData
|
||||
{
|
||||
void* m_pMappedData = VMA_NULL; // Not null means memory is mapped.
|
||||
VmaWin32Handle m_Handle;
|
||||
};
|
||||
|
||||
struct VmaAllocation_T
|
||||
{
|
||||
friend struct VmaDedicatedAllocationListItemTraits;
|
||||
@@ -6191,12 +6340,14 @@ public:
|
||||
bool mapped);
|
||||
// pMappedData not null means allocation is created with MAPPED flag.
|
||||
void InitDedicatedAllocation(
|
||||
VmaAllocator allocator,
|
||||
VmaPool hParentPool,
|
||||
uint32_t memoryTypeIndex,
|
||||
VkDeviceMemory hMemory,
|
||||
VmaSuballocationType suballocationType,
|
||||
void* pMappedData,
|
||||
VkDeviceSize size);
|
||||
void Destroy(VmaAllocator allocator);
|
||||
|
||||
ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }
|
||||
VkDeviceSize GetAlignment() const { return m_Alignment; }
|
||||
@@ -6240,6 +6391,10 @@ public:
|
||||
void PrintParameters(class VmaJsonWriter& json) const;
|
||||
#endif
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VkResult GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* hHandle) noexcept;
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
|
||||
private:
|
||||
// Allocation out of VmaDeviceMemoryBlock.
|
||||
struct BlockAllocation
|
||||
@@ -6252,7 +6407,7 @@ private:
|
||||
{
|
||||
VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
|
||||
VkDeviceMemory m_hMemory;
|
||||
void* m_pMappedData; // Not null means memory is mapped.
|
||||
VmaAllocationExtraData* m_ExtraData;
|
||||
VmaAllocation_T* m_Prev;
|
||||
VmaAllocation_T* m_Next;
|
||||
};
|
||||
@@ -6277,6 +6432,8 @@ private:
|
||||
#if VMA_STATS_STRING_ENABLED
|
||||
VmaBufferImageUsage m_BufferImageUsage; // 0 if unknown.
|
||||
#endif
|
||||
|
||||
void EnsureExtraData(VmaAllocator hAllocator);
|
||||
};
|
||||
#endif // _VMA_ALLOCATION_T
|
||||
|
||||
@@ -10075,6 +10232,7 @@ public:
|
||||
bool m_UseExtMemoryPriority;
|
||||
bool m_UseKhrMaintenance4;
|
||||
bool m_UseKhrMaintenance5;
|
||||
bool m_UseKhrExternalMemoryWin32;
|
||||
const VkDevice m_hDevice;
|
||||
const VkInstance m_hInstance;
|
||||
const bool m_AllocationCallbacksSpecified;
|
||||
@@ -10438,7 +10596,7 @@ VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator)
|
||||
m_Id(0),
|
||||
m_hMemory(VK_NULL_HANDLE),
|
||||
m_MapCount(0),
|
||||
m_pMappedData(VMA_NULL) {}
|
||||
m_pMappedData(VMA_NULL){}
|
||||
|
||||
VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock()
|
||||
{
|
||||
@@ -10681,6 +10839,14 @@ VkResult VmaDeviceMemoryBlock::BindImageMemory(
|
||||
VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);
|
||||
return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext);
|
||||
}
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VkResult VmaDeviceMemoryBlock::CreateWin32Handle(const VmaAllocator hAllocator, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, HANDLE* pHandle) noexcept
|
||||
{
|
||||
VMA_ASSERT(pHandle);
|
||||
return m_Handle.GetHandle(hAllocator->m_hDevice, m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle);
|
||||
}
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
#endif // _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS
|
||||
|
||||
#ifndef _VMA_ALLOCATION_T_FUNCTIONS
|
||||
@@ -10733,6 +10899,7 @@ void VmaAllocation_T::InitBlockAllocation(
|
||||
}
|
||||
|
||||
void VmaAllocation_T::InitDedicatedAllocation(
|
||||
VmaAllocator allocator,
|
||||
VmaPool hParentPool,
|
||||
uint32_t memoryTypeIndex,
|
||||
VkDeviceMemory hMemory,
|
||||
@@ -10747,16 +10914,29 @@ void VmaAllocation_T::InitDedicatedAllocation(
|
||||
m_Size = size;
|
||||
m_MemoryTypeIndex = memoryTypeIndex;
|
||||
m_SuballocationType = (uint8_t)suballocationType;
|
||||
if(pMappedData != VMA_NULL)
|
||||
m_DedicatedAllocation.m_ExtraData = VMA_NULL;
|
||||
m_DedicatedAllocation.m_hParentPool = hParentPool;
|
||||
m_DedicatedAllocation.m_hMemory = hMemory;
|
||||
m_DedicatedAllocation.m_Prev = VMA_NULL;
|
||||
m_DedicatedAllocation.m_Next = VMA_NULL;
|
||||
|
||||
if (pMappedData != VMA_NULL)
|
||||
{
|
||||
VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
|
||||
m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP;
|
||||
EnsureExtraData(allocator);
|
||||
m_DedicatedAllocation.m_ExtraData->m_pMappedData = pMappedData;
|
||||
}
|
||||
}
|
||||
|
||||
void VmaAllocation_T::Destroy(VmaAllocator allocator)
|
||||
{
|
||||
FreeName(allocator);
|
||||
|
||||
if (GetType() == ALLOCATION_TYPE_DEDICATED)
|
||||
{
|
||||
vma_delete(allocator, m_DedicatedAllocation.m_ExtraData);
|
||||
}
|
||||
m_DedicatedAllocation.m_hParentPool = hParentPool;
|
||||
m_DedicatedAllocation.m_hMemory = hMemory;
|
||||
m_DedicatedAllocation.m_pMappedData = pMappedData;
|
||||
m_DedicatedAllocation.m_Prev = VMA_NULL;
|
||||
m_DedicatedAllocation.m_Next = VMA_NULL;
|
||||
}
|
||||
|
||||
void VmaAllocation_T::SetName(VmaAllocator hAllocator, const char* pName)
|
||||
@@ -10861,8 +11041,9 @@ void* VmaAllocation_T::GetMappedData() const
|
||||
}
|
||||
break;
|
||||
case ALLOCATION_TYPE_DEDICATED:
|
||||
VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0 || IsPersistentMap()));
|
||||
return m_DedicatedAllocation.m_pMappedData;
|
||||
VMA_ASSERT((m_DedicatedAllocation.m_ExtraData != VMA_NULL && m_DedicatedAllocation.m_ExtraData->m_pMappedData != VMA_NULL) ==
|
||||
(m_MapCount != 0 || IsPersistentMap()));
|
||||
return m_DedicatedAllocation.m_ExtraData != VMA_NULL ? m_DedicatedAllocation.m_ExtraData->m_pMappedData : VMA_NULL;
|
||||
default:
|
||||
VMA_ASSERT(0);
|
||||
return VMA_NULL;
|
||||
@@ -10903,12 +11084,14 @@ VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppDa
|
||||
VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
|
||||
VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
|
||||
|
||||
EnsureExtraData(hAllocator);
|
||||
|
||||
if (m_MapCount != 0 || IsPersistentMap())
|
||||
{
|
||||
if (m_MapCount < 0xFF)
|
||||
{
|
||||
VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);
|
||||
*ppData = m_DedicatedAllocation.m_pMappedData;
|
||||
VMA_ASSERT(m_DedicatedAllocation.m_ExtraData->m_pMappedData != VMA_NULL);
|
||||
*ppData = m_DedicatedAllocation.m_ExtraData->m_pMappedData;
|
||||
++m_MapCount;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
@@ -10929,7 +11112,7 @@ VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppDa
|
||||
ppData);
|
||||
if (result == VK_SUCCESS)
|
||||
{
|
||||
m_DedicatedAllocation.m_pMappedData = *ppData;
|
||||
m_DedicatedAllocation.m_ExtraData->m_pMappedData = *ppData;
|
||||
m_MapCount = 1;
|
||||
}
|
||||
return result;
|
||||
@@ -10945,7 +11128,8 @@ void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator)
|
||||
--m_MapCount;
|
||||
if (m_MapCount == 0 && !IsPersistentMap())
|
||||
{
|
||||
m_DedicatedAllocation.m_pMappedData = VMA_NULL;
|
||||
VMA_ASSERT(m_DedicatedAllocation.m_ExtraData != VMA_NULL);
|
||||
m_DedicatedAllocation.m_ExtraData->m_pMappedData = VMA_NULL;
|
||||
(*hAllocator->GetVulkanFunctions().vkUnmapMemory)(
|
||||
hAllocator->m_hDevice,
|
||||
m_DedicatedAllocation.m_hMemory);
|
||||
@@ -10981,8 +11165,33 @@ void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const
|
||||
json.WriteString(m_pName);
|
||||
}
|
||||
}
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VkResult VmaAllocation_T::GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* pHandle) noexcept
|
||||
{
|
||||
auto pvkGetMemoryWin32HandleKHR = hAllocator->GetVulkanFunctions().vkGetMemoryWin32HandleKHR;
|
||||
switch (m_Type)
|
||||
{
|
||||
case ALLOCATION_TYPE_BLOCK:
|
||||
return m_BlockAllocation.m_Block->CreateWin32Handle(hAllocator, pvkGetMemoryWin32HandleKHR, hTargetProcess, pHandle);
|
||||
case ALLOCATION_TYPE_DEDICATED:
|
||||
EnsureExtraData(hAllocator);
|
||||
return m_DedicatedAllocation.m_ExtraData->m_Handle.GetHandle(hAllocator->m_hDevice, m_DedicatedAllocation.m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle);
|
||||
default:
|
||||
VMA_ASSERT(0);
|
||||
return VK_ERROR_FEATURE_NOT_PRESENT;
|
||||
}
|
||||
}
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
#endif // VMA_STATS_STRING_ENABLED
|
||||
|
||||
void VmaAllocation_T::EnsureExtraData(VmaAllocator hAllocator)
|
||||
{
|
||||
if (m_DedicatedAllocation.m_ExtraData == VMA_NULL)
|
||||
{
|
||||
m_DedicatedAllocation.m_ExtraData = vma_new(hAllocator, VmaAllocationExtraData)();
|
||||
}
|
||||
}
|
||||
|
||||
void VmaAllocation_T::FreeName(VmaAllocator hAllocator)
|
||||
{
|
||||
if(m_pName)
|
||||
@@ -11399,6 +11608,10 @@ void VmaBlockVector::Free(const VmaAllocation hAllocation)
|
||||
}
|
||||
|
||||
IncrementallySortBlocks();
|
||||
|
||||
m_hAllocator->m_Budget.RemoveAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), hAllocation->GetSize());
|
||||
hAllocation->Destroy(m_hAllocator);
|
||||
m_hAllocator->m_AllocationObjectAllocator.Free(hAllocation);
|
||||
}
|
||||
|
||||
// Destruction of a free block. Deferred until this point, outside of mutex
|
||||
@@ -11409,9 +11622,6 @@ void VmaBlockVector::Free(const VmaAllocation hAllocation)
|
||||
pBlockToDelete->Destroy(m_hAllocator);
|
||||
vma_delete(m_hAllocator, pBlockToDelete);
|
||||
}
|
||||
|
||||
m_hAllocator->m_Budget.RemoveAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), hAllocation->GetSize());
|
||||
m_hAllocator->m_AllocationObjectAllocator.Free(hAllocation);
|
||||
}
|
||||
|
||||
VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const
|
||||
@@ -12711,6 +12921,7 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
|
||||
m_UseExtMemoryPriority((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT) != 0),
|
||||
m_UseKhrMaintenance4((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT) != 0),
|
||||
m_UseKhrMaintenance5((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT) != 0),
|
||||
m_UseKhrExternalMemoryWin32((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT) != 0),
|
||||
m_hDevice(pCreateInfo->device),
|
||||
m_hInstance(pCreateInfo->instance),
|
||||
m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL),
|
||||
@@ -12802,6 +13013,19 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
|
||||
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
||||
}
|
||||
#endif
|
||||
#if !(VMA_KHR_MAINTENANCE5)
|
||||
if(m_UseKhrMaintenance5)
|
||||
{
|
||||
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !(VMA_EXTERNAL_MEMORY_WIN32)
|
||||
if(m_UseKhrExternalMemoryWin32)
|
||||
{
|
||||
VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks));
|
||||
memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties));
|
||||
@@ -13026,7 +13250,9 @@ void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVul
|
||||
VMA_COPY_IF_NOT_NULL(vkGetDeviceBufferMemoryRequirements);
|
||||
VMA_COPY_IF_NOT_NULL(vkGetDeviceImageMemoryRequirements);
|
||||
#endif
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VMA_COPY_IF_NOT_NULL(vkGetMemoryWin32HandleKHR);
|
||||
#endif
|
||||
#undef VMA_COPY_IF_NOT_NULL
|
||||
}
|
||||
|
||||
@@ -13128,7 +13354,12 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
|
||||
VMA_FETCH_DEVICE_FUNC(vkGetDeviceImageMemoryRequirements, PFN_vkGetDeviceImageMemoryRequirementsKHR, "vkGetDeviceImageMemoryRequirementsKHR");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
if (m_UseKhrExternalMemoryWin32)
|
||||
{
|
||||
VMA_FETCH_DEVICE_FUNC(vkGetMemoryWin32HandleKHR, PFN_vkGetMemoryWin32HandleKHR, "vkGetMemoryWin32HandleKHR");
|
||||
}
|
||||
#endif
|
||||
#undef VMA_FETCH_DEVICE_FUNC
|
||||
#undef VMA_FETCH_INSTANCE_FUNC
|
||||
}
|
||||
@@ -13177,6 +13408,12 @@ void VmaAllocator_T::ValidateVulkanFunctions()
|
||||
VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);
|
||||
}
|
||||
#endif
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
if (m_UseKhrExternalMemoryWin32)
|
||||
{
|
||||
VMA_ASSERT(m_VulkanFunctions.vkGetMemoryWin32HandleKHR != VMA_NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Not validating these due to suspected driver bugs with these function
|
||||
// pointers being null despite correct extension or Vulkan version is enabled.
|
||||
@@ -13527,7 +13764,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemoryPage(
|
||||
}
|
||||
|
||||
*pAllocation = m_AllocationObjectAllocator.Allocate(isMappingAllowed);
|
||||
(*pAllocation)->InitDedicatedAllocation(pool, memTypeIndex, hMemory, suballocType, pMappedData, size);
|
||||
(*pAllocation)->InitDedicatedAllocation(this, pool, memTypeIndex, hMemory, suballocType, pMappedData, size);
|
||||
if (isUserDataString)
|
||||
(*pAllocation)->SetName(this, (const char*)pUserData);
|
||||
else
|
||||
@@ -13863,8 +14100,6 @@ void VmaAllocator_T::FreeMemory(
|
||||
FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);
|
||||
}
|
||||
|
||||
allocation->FreeName(this);
|
||||
|
||||
switch(allocation->GetType())
|
||||
{
|
||||
case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
|
||||
@@ -14335,7 +14570,6 @@ VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData)
|
||||
}
|
||||
return res;
|
||||
}
|
||||
VMA_FALLTHROUGH; // Fallthrough
|
||||
case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
|
||||
return hAllocation->DedicatedAllocMap(this, ppData);
|
||||
default:
|
||||
@@ -14549,6 +14783,7 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)
|
||||
FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);
|
||||
|
||||
m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize());
|
||||
allocation->Destroy(this);
|
||||
m_AllocationObjectAllocator.Free(allocation);
|
||||
|
||||
VMA_DEBUG_LOG_FORMAT(" Freed DedicatedMemory MemoryTypeIndex=%" PRIu32, memTypeIndex);
|
||||
@@ -16169,7 +16404,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
|
||||
pImageCreateInfo,
|
||||
allocator->GetAllocationCallbacks(),
|
||||
pImage);
|
||||
if(res >= 0)
|
||||
if(res == VK_SUCCESS)
|
||||
{
|
||||
VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ?
|
||||
VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL :
|
||||
@@ -16194,14 +16429,14 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
|
||||
1, // allocationCount
|
||||
pAllocation);
|
||||
|
||||
if(res >= 0)
|
||||
if(res == VK_SUCCESS)
|
||||
{
|
||||
// 3. Bind image with memory.
|
||||
if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)
|
||||
{
|
||||
res = allocator->BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL);
|
||||
}
|
||||
if(res >= 0)
|
||||
if(res == VK_SUCCESS)
|
||||
{
|
||||
// All steps succeeded.
|
||||
#if VMA_STATS_STRING_ENABLED
|
||||
@@ -16434,6 +16669,15 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock V
|
||||
VmaFreeString(virtualBlock->GetAllocationCallbacks(), pStatsString);
|
||||
}
|
||||
}
|
||||
#if VMA_EXTERNAL_MEMORY_WIN32
|
||||
VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle(VmaAllocator VMA_NOT_NULL allocator,
|
||||
VmaAllocation VMA_NOT_NULL allocation, HANDLE hTargetProcess, HANDLE* VMA_NOT_NULL pHandle)
|
||||
{
|
||||
VMA_ASSERT(allocator && allocation && pHandle);
|
||||
VMA_DEBUG_GLOBAL_MUTEX_LOCK;
|
||||
return allocation->GetWin32Handle(allocator, hTargetProcess, pHandle);
|
||||
}
|
||||
#endif // VMA_EXTERNAL_MEMORY_WIN32
|
||||
#endif // VMA_STATS_STRING_ENABLED
|
||||
#endif // _VMA_PUBLIC_INTERFACE
|
||||
#endif // VMA_IMPLEMENTATION
|
||||
@@ -16567,6 +16811,7 @@ VK_EXT_memory_budget | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT
|
||||
VK_KHR_buffer_device_address | #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
|
||||
VK_EXT_memory_priority | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT
|
||||
VK_AMD_device_coherent_memory | #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT
|
||||
VK_KHR_external_memory_win32 | #VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT
|
||||
|
||||
Example with fetching pointers to Vulkan functions dynamically:
|
||||
|
||||
@@ -17053,7 +17298,7 @@ implementation whether the allocation succeeds or fails. You can change this beh
|
||||
by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is
|
||||
not made if it would exceed the budget or if the budget is already exceeded.
|
||||
VMA then tries to make the allocation from the next eligible Vulkan memory type.
|
||||
The all of them fail, the call then fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
|
||||
If all of them fail, the call then fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
|
||||
Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag
|
||||
when creating resources that are not essential for the application (e.g. the texture
|
||||
of a specific object) and not to pass it when creating critically important resources
|
||||
@@ -18193,7 +18438,8 @@ allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||
VkBuffer buf;
|
||||
VmaAllocation alloc;
|
||||
VmaAllocationInfo allocInfo;
|
||||
vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
|
||||
VkResult result = vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
|
||||
// Check result...
|
||||
|
||||
VkMemoryPropertyFlags memPropFlags;
|
||||
vmaGetAllocationMemoryProperties(allocator, alloc, &memPropFlags);
|
||||
@@ -18204,10 +18450,24 @@ if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||
|
||||
// [Executed in runtime]:
|
||||
memcpy(allocInfo.pMappedData, myData, myDataSize);
|
||||
result = vmaFlushAllocation(allocator, alloc, 0, VK_WHOLE_SIZE);
|
||||
// Check result...
|
||||
|
||||
VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
|
||||
bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
|
||||
bufMemBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT;
|
||||
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier.buffer = buf;
|
||||
bufMemBarrier.offset = 0;
|
||||
bufMemBarrier.size = VK_WHOLE_SIZE;
|
||||
|
||||
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
|
||||
0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocation ended up in a non-mappable memory - need to transfer.
|
||||
// Allocation ended up in a non-mappable memory - a transfer using a staging buffer is required.
|
||||
VkBufferCreateInfo stagingBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
stagingBufCreateInfo.size = 65536;
|
||||
stagingBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
@@ -18220,18 +18480,46 @@ else
|
||||
VkBuffer stagingBuf;
|
||||
VmaAllocation stagingAlloc;
|
||||
VmaAllocationInfo stagingAllocInfo;
|
||||
vmaCreateBuffer(allocator, &stagingBufCreateInfo, &stagingAllocCreateInfo,
|
||||
&stagingBuf, &stagingAlloc, stagingAllocInfo);
|
||||
result = vmaCreateBuffer(allocator, &stagingBufCreateInfo, &stagingAllocCreateInfo,
|
||||
&stagingBuf, &stagingAlloc, &stagingAllocInfo);
|
||||
// Check result...
|
||||
|
||||
// [Executed in runtime]:
|
||||
memcpy(stagingAllocInfo.pMappedData, myData, myDataSize);
|
||||
vmaFlushAllocation(allocator, stagingAlloc, 0, VK_WHOLE_SIZE);
|
||||
//vkCmdPipelineBarrier: VK_ACCESS_HOST_WRITE_BIT --> VK_ACCESS_TRANSFER_READ_BIT
|
||||
result = vmaFlushAllocation(allocator, stagingAlloc, 0, VK_WHOLE_SIZE);
|
||||
// Check result...
|
||||
|
||||
VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
|
||||
bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
|
||||
bufMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier.buffer = stagingBuf;
|
||||
bufMemBarrier.offset = 0;
|
||||
bufMemBarrier.size = VK_WHOLE_SIZE;
|
||||
|
||||
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
|
||||
|
||||
VkBufferCopy bufCopy = {
|
||||
0, // srcOffset
|
||||
0, // dstOffset,
|
||||
myDataSize); // size
|
||||
myDataSize, // size
|
||||
};
|
||||
|
||||
vkCmdCopyBuffer(cmdBuf, stagingBuf, buf, 1, &bufCopy);
|
||||
|
||||
VkBufferMemoryBarrier bufMemBarrier2 = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
|
||||
bufMemBarrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
bufMemBarrier2.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; // We created a uniform buffer
|
||||
bufMemBarrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier2.buffer = buf;
|
||||
bufMemBarrier2.offset = 0;
|
||||
bufMemBarrier2.size = VK_WHOLE_SIZE;
|
||||
|
||||
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
|
||||
0, 0, nullptr, 1, &bufMemBarrier2, 0, nullptr);
|
||||
}
|
||||
\endcode
|
||||
|
||||
@@ -18264,14 +18552,22 @@ Please check "CONFIGURATION SECTION" in the code to find macros that you can def
|
||||
before each include of this file or change directly in this file to provide
|
||||
your own implementation of basic facilities like assert, `min()` and `max()` functions,
|
||||
mutex, atomic etc.
|
||||
The library uses its own implementation of containers by default, but you can switch to using
|
||||
STL containers instead.
|
||||
|
||||
For example, define `VMA_ASSERT(expr)` before including the library to provide
|
||||
custom implementation of the assertion, compatible with your project.
|
||||
By default it is defined to standard C `assert(expr)` in `_DEBUG` configuration
|
||||
and empty otherwise.
|
||||
|
||||
Similarly, you can define `VMA_LEAK_LOG_FORMAT` macro to enable printing of leaked (unfreed) allocations,
|
||||
including their names and other parameters. Example:
|
||||
|
||||
\code
|
||||
#define VMA_LEAK_LOG_FORMAT(format, ...) do { \
|
||||
printf((format), __VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} while(false)
|
||||
\endcode
|
||||
|
||||
\section config_Vulkan_functions Pointers to Vulkan functions
|
||||
|
||||
There are multiple ways to import pointers to Vulkan functions in the library.
|
||||
@@ -18526,6 +18822,145 @@ Example use of this extension can be found in the code of the sample and test su
|
||||
accompanying this library.
|
||||
|
||||
|
||||
\page vk_khr_external_memory_win32 VK_KHR_external_memory_win32
|
||||
|
||||
On Windows, the VK_KHR_external_memory_win32 device extension allows exporting a Win32 `HANDLE`
|
||||
of a `VkDeviceMemory` block, to be able to reference the memory on other Vulkan logical devices or instances,
|
||||
in multiple processes, and/or in multiple APIs.
|
||||
VMA offers support for it.
|
||||
|
||||
\section vk_khr_external_memory_win32_initialization Initialization
|
||||
|
||||
1) Make sure the extension is defined in the code by including following header before including VMA:
|
||||
|
||||
\code
|
||||
#include <vulkan/vulkan_win32.h>
|
||||
\endcode
|
||||
|
||||
2) Check if "VK_KHR_external_memory_win32" is available among device extensions.
|
||||
Enable it when creating the `VkDevice` object.
|
||||
|
||||
3) Enable the usage of this extension in VMA by setting flag #VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT
|
||||
when calling vmaCreateAllocator().
|
||||
|
||||
4) Make sure that VMA has access to the `vkGetMemoryWin32HandleKHR` function by either enabling `VMA_DYNAMIC_VULKAN_FUNCTIONS` macro
|
||||
or setting VmaVulkanFunctions::vkGetMemoryWin32HandleKHR explicitly.
|
||||
For more information, see \ref quick_start_initialization_importing_vulkan_functions.
|
||||
|
||||
\section vk_khr_external_memory_win32_preparations Preparations
|
||||
|
||||
You can find example usage among tests, in file "Tests.cpp", function `TestWin32Handles()`.
|
||||
|
||||
To use the extenion, buffers need to be created with `VkExternalMemoryBufferCreateInfoKHR` attached to their `pNext` chain,
|
||||
and memory allocations need to be made with `VkExportMemoryAllocateInfoKHR` attached to their `pNext` chain.
|
||||
To make use of them, you need to use \ref custom_memory_pools. Example:
|
||||
|
||||
\code
|
||||
// Define an example buffer and allocation parameters.
|
||||
VkExternalMemoryBufferCreateInfoKHR externalMemBufCreateInfo = {
|
||||
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
|
||||
nullptr,
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
|
||||
};
|
||||
VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
exampleBufCreateInfo.size = 0x10000; // Doesn't matter here.
|
||||
exampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
exampleBufCreateInfo.pNext = &externalMemBufCreateInfo;
|
||||
|
||||
VmaAllocationCreateInfo exampleAllocCreateInfo = {};
|
||||
exampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||
|
||||
// Find memory type index to use for the custom pool.
|
||||
uint32_t memTypeIndex;
|
||||
VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_Allocator,
|
||||
&exampleBufCreateInfo, &exampleAllocCreateInfo, &memTypeIndex);
|
||||
// Check res...
|
||||
|
||||
// Create a custom pool.
|
||||
constexpr static VkExportMemoryAllocateInfoKHR exportMemAllocInfo = {
|
||||
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
|
||||
nullptr,
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
|
||||
};
|
||||
VmaPoolCreateInfo poolCreateInfo = {};
|
||||
poolCreateInfo.memoryTypeIndex = memTypeIndex;
|
||||
poolCreateInfo.pMemoryAllocateNext = (void*)&exportMemAllocInfo;
|
||||
|
||||
VmaPool pool;
|
||||
res = vmaCreatePool(g_Allocator, &poolCreateInfo, &pool);
|
||||
// Check res...
|
||||
|
||||
// YOUR OTHER CODE COMES HERE....
|
||||
|
||||
// At the end, don't forget to destroy it!
|
||||
vmaDestroyPool(g_Allocator, pool);
|
||||
\endcode
|
||||
|
||||
Note that the structure passed as VmaPoolCreateInfo::pMemoryAllocateNext must remain alive and unchanged
|
||||
for the whole lifetime of the custom pool, because it will be used when the pool allocates a new device memory block.
|
||||
No copy is made internally. This is why variable `exportMemAllocInfo` is defined as `static`.
|
||||
|
||||
\section vk_khr_external_memory_win32_memory_allocation Memory allocation
|
||||
|
||||
Finally, you can create a buffer with an allocation out of the custom pool.
|
||||
The buffer should use same flags as the sample buffer used to find the memory type.
|
||||
It should also specify `VkExternalMemoryBufferCreateInfoKHR` in its `pNext` chain.
|
||||
|
||||
\code
|
||||
VkExternalMemoryBufferCreateInfoKHR externalMemBufCreateInfo = {
|
||||
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
|
||||
nullptr,
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
|
||||
};
|
||||
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
bufCreateInfo.size = // Your desired buffer size.
|
||||
bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
bufCreateInfo.pNext = &externalMemBufCreateInfo;
|
||||
|
||||
VmaAllocationCreateInfo allocCreateInfo = {};
|
||||
allocCreateInfo.pool = pool; // It is enough to set this one member.
|
||||
|
||||
VkBuffer buf;
|
||||
VmaAllocation alloc;
|
||||
res = vmaCreateBuffer(g_Allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr);
|
||||
// Check res...
|
||||
|
||||
// YOUR OTHER CODE COMES HERE....
|
||||
|
||||
// At the end, don't forget to destroy it!
|
||||
vmaDestroyBuffer(g_Allocator, buf, alloc);
|
||||
\endcode
|
||||
|
||||
If you need each allocation to have its own device memory block and start at offset 0, you can still do
|
||||
by using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag. It works also with custom pools.
|
||||
|
||||
\section vk_khr_external_memory_win32_exporting_win32_handle Exporting Win32 handle
|
||||
|
||||
After the allocation is created, you can acquire a Win32 `HANDLE` to the `VkDeviceMemory` block it belongs to.
|
||||
VMA function vmaGetMemoryWin32Handle() is a replacement of the Vulkan function `vkGetMemoryWin32HandleKHR`.
|
||||
|
||||
\code
|
||||
HANDLE handle;
|
||||
res = vmaGetMemoryWin32Handle(g_Allocator, alloc, nullptr, &handle);
|
||||
// Check res...
|
||||
|
||||
// YOUR OTHER CODE COMES HERE....
|
||||
|
||||
// At the end, you must close the handle.
|
||||
CloseHandle(handle);
|
||||
\endcode
|
||||
|
||||
Documentation of the VK_KHR_external_memory_win32 extension states that:
|
||||
|
||||
> If handleType is defined as an NT handle, vkGetMemoryWin32HandleKHR must be called no more than once for each valid unique combination of memory and handleType.
|
||||
|
||||
This is ensured automatically inside VMA.
|
||||
The library fetches the handle on first use, remembers it internally, and closes it when the memory block or dedicated allocation is destroyed.
|
||||
Every time you call vmaGetMemoryWin32Handle(), VMA calls `DuplicateHandle` and returns a new handle that you need to close.
|
||||
|
||||
For further information, please check documentation of the vmaGetMemoryWin32Handle() function.
|
||||
|
||||
|
||||
\page enabling_buffer_device_address Enabling buffer device address
|
||||
|
||||
Device extension VK_KHR_buffer_device_address
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -176,8 +176,6 @@
|
||||
030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
|
||||
03000000bd12000002e0000000000000,Dual Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
|
||||
03000000ff1100003133000000000000,DualForce,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b1,platform:Windows,
|
||||
030000008f0e00000910000000000000,Sony DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
|
||||
03000000317300000100000000000000,Sony DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
030000006f0e00003001000000000000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000fc0400000250000000000000,Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
|
||||
03000000bc2000000091000000000000,EasySMX Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
@@ -247,6 +245,7 @@
|
||||
03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000d11800000094000000000000,Google Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
|
||||
030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
@@ -489,13 +488,6 @@
|
||||
030000006f0e00000901000000000000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000006f0e00008901000000000000,PDP Realmz Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows,
|
||||
03000000666600006706000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
|
||||
03000000e30500009605000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
|
||||
030000004c050000da0c000000000000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000632500002306000000000000,Sony PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000f0250000c183000000000000,Sony PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000d9040000160f000000000000,Sony PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
|
||||
030000004c0500003713000000000000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000d620000011a7000000000000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -685,13 +677,21 @@
|
||||
03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
|
||||
030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
|
||||
03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
|
||||
030000008f0e00000910000000000000,Sony DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
|
||||
03000000317300000100000000000000,Sony DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000666600006706000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
|
||||
03000000e30500009605000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
|
||||
030000004c050000da0c000000000000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000632500002306000000000000,Sony PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000f0250000c183000000000000,Sony PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000d9040000160f000000000000,Sony PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000004c0500003713000000000000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000380700001722000000000000,Speedlink Competition Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b2,y:b3,platform:Windows,
|
||||
030000008f0e00000800000000000000,Speedlink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000d11800000094000000000000,Google Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
|
||||
@@ -701,7 +701,6 @@
|
||||
03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000790000001c18000000000000,STK 7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000380700003847000000000000,Street Fighter Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
|
||||
@@ -716,7 +715,8 @@
|
||||
03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
|
||||
03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows,
|
||||
03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
|
||||
03000000790000002601000000000000,TGZ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000790000001c18000000000000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000790000002601000000000000,TGZ Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000591c00002400000000000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000591c00002600000000000000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,start:b7,x:b3,y:b0,platform:Windows,
|
||||
030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
|
||||
@@ -920,6 +920,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
|
||||
030000006f0e00000102000000000000,GameStop Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000ff1100003133000007010000,GameWare PC Control Pad,a:b2,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Mac OS X,
|
||||
03000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
|
||||
030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000280400000140000000020000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000008f0e00000300000007010000,GreenAsia Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X,
|
||||
@@ -996,11 +997,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X,
|
||||
030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000790000001c18000000010000,PB Tails Choc,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000006f0e00000901000002010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
03000000666600006706000088020000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X,
|
||||
030000004c050000da0c000000010000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
030000004c0500003713000000010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000d620000011a7000000020000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000d620000011a7000010050000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
@@ -1053,7 +1052,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X,
|
||||
030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
|
||||
030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000666600006706000088020000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X,
|
||||
030000004c050000da0c000000010000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
030000004c0500003713000000010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1284,6 +1285,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux,
|
||||
190000004b4800000011000000010000,GO-Super Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b2,y:b3,platform:Linux,
|
||||
03000000f0250000c183000010010000,Goodbetterbest Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000d11800000094000011010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
05000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400008e02000001010000,GPD Win Max 2 6800U Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
@@ -1299,7 +1302,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000000d0f00008400000011010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000000d0f00005001000009040000,Hori Fighting Commander Octa Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000000d0f00008500000010010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
030000000d0f00003701000013010000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b3,y:b2,platform:Linux,
|
||||
@@ -1347,6 +1350,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000300f00001001000010010000,Jess Tech Dual Analog Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
|
||||
03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000ba2200002010000001010000,Jess Technology Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000300f00001101000010010000,Jess Tech Colour Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Linux,
|
||||
030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,
|
||||
050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,
|
||||
030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,
|
||||
@@ -1494,10 +1498,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e0000d802000006640000,PDP Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e0000ef02000007640000,PDP Xbox Series Kinetic Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000666600006706000000010000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
|
||||
030000004c050000da0c000011010000,Sony PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000d9040000160f000000010000,Sony PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
030000004c0500003713000011010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000d620000011a7000011010000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
@@ -1534,8 +1534,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000504c415953544154494f4e00,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
|
||||
060000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
|
||||
030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
030000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
@@ -1552,9 +1552,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000004c050000f20d000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
030000004c050000f20d000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
|
||||
050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
|
||||
050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
050000004c050000f20d000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
|
||||
03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,
|
||||
03000000222c00000225000011010000,Qanba Dragon Arcade Joystick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000222c00000025000011010000,Qanba Dragon Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
@@ -1631,12 +1633,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
030000004b2900000430000011000000,Snakebyte Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
03000000666600006706000000010000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
|
||||
030000004c050000da0c000011010000,Sony PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000d9040000160f000000010000,Sony PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000004c0500003713000011010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000250900000500000000010000,Sony PS2 pad with SmartJoy Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
|
||||
030000005e0400008e02000073050000,Speedlink Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000d11800000094000011010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
05000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
|
||||
03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
@@ -1666,7 +1670,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000e40a00000307000011010000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux,
|
||||
03000000e40a00000207000011010000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux,
|
||||
03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux,
|
||||
03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
|
||||
030000004f04000015b3000001010000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
|
||||
@@ -1730,9 +1734,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
030000005e040000ea02000011050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000ea02000015050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000ea02000015050000,Xbox One S Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
|
||||
060000005e040000ea02000016050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b000005050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
|
||||
@@ -453,6 +453,11 @@ std::string Path::RealPath(const std::string_view path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If any relative symlinks were resolved, there may be '.' and '..'
|
||||
// components in the resultant path, which must be removed.
|
||||
realpath = Path::Canonicalize(realpath);
|
||||
|
||||
#endif
|
||||
|
||||
return realpath;
|
||||
@@ -994,6 +999,37 @@ std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode, Error*
|
||||
#endif
|
||||
}
|
||||
|
||||
std::FILE* FileSystem::OpenCFileTryIgnoreCase(const char* filename, const char* mode, Error* error)
|
||||
{
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
return OpenCFile(filename, mode, error);
|
||||
#else
|
||||
std::FILE* fp = std::fopen(filename, mode);
|
||||
const auto cur_errno = errno;
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
const auto dir = std::string(Path::GetDirectory(filename));
|
||||
FindResultsArray files;
|
||||
if (FindFiles(dir.c_str(), "*", FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES, &files))
|
||||
{
|
||||
for (auto& file : files)
|
||||
{
|
||||
if (StringUtil::compareNoCase(file.FileName, filename))
|
||||
{
|
||||
fp = std::fopen(file.FileName.c_str(), mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fp)
|
||||
Error::SetErrno(error, cur_errno);
|
||||
return fp;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int FileSystem::OpenFDFile(const char* filename, int flags, int mode, Error* error)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -1015,6 +1051,11 @@ FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, c
|
||||
return ManagedCFilePtr(OpenCFile(filename, mode, error));
|
||||
}
|
||||
|
||||
FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFileTryIgnoreCase(const char* filename, const char* mode, Error* error)
|
||||
{
|
||||
return ManagedCFilePtr(OpenCFileTryIgnoreCase(filename, mode, error));
|
||||
}
|
||||
|
||||
std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -1925,6 +1966,26 @@ bool FileSystem::SetPathCompression(const char* path, bool enable)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool FileSystem::CreateSymLink(const char* link, const char* target)
|
||||
{
|
||||
// convert to wide string
|
||||
const std::wstring wlink = GetWin32Path(link);
|
||||
if (wlink.empty())
|
||||
return false;
|
||||
|
||||
const std::wstring wtarget = GetWin32Path(target);
|
||||
if (wtarget.empty())
|
||||
return false;
|
||||
|
||||
// check if it's a directory
|
||||
DWORD flags = 0;
|
||||
if (DirectoryExists(target))
|
||||
flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
|
||||
|
||||
// create the symbolic link
|
||||
return CreateSymbolicLinkW(wlink.c_str(), wtarget.c_str(), flags) != 0;
|
||||
}
|
||||
|
||||
bool FileSystem::IsSymbolicLink(const char* path)
|
||||
{
|
||||
// convert to wide string
|
||||
@@ -2505,6 +2566,11 @@ bool FileSystem::SetPathCompression(const char* path, bool enable)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileSystem::CreateSymLink(const char* link, const char* target)
|
||||
{
|
||||
return symlink(target, link) == 0;
|
||||
}
|
||||
|
||||
bool FileSystem::IsSymbolicLink(const char* path)
|
||||
{
|
||||
struct stat sysStatData;
|
||||
|
||||
@@ -106,7 +106,16 @@ namespace FileSystem
|
||||
/// open files
|
||||
using ManagedCFilePtr = std::unique_ptr<std::FILE, FileDeleter>;
|
||||
ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode, Error* error = nullptr);
|
||||
// Tries to open a file using the given filename, but if that fails searches
|
||||
// the directory for a file with a case-insensitive match.
|
||||
// This is the same as OpenManagedCFile on Windows and MacOS
|
||||
ManagedCFilePtr OpenManagedCFileTryIgnoreCase(const char* filename, const char* mode, Error* error = nullptr);
|
||||
std::FILE* OpenCFile(const char* filename, const char* mode, Error* error = nullptr);
|
||||
// Tries to open a file using the given filename, but if that fails searches
|
||||
// the directory for a file with a case-insensitive match.
|
||||
// This is the same as OpenCFile on Windows and MacOS
|
||||
std::FILE* OpenCFileTryIgnoreCase(const char* filename, const char* mode, Error* error = nullptr);
|
||||
|
||||
int FSeek64(std::FILE* fp, s64 offset, int whence);
|
||||
s64 FTell64(std::FILE* fp);
|
||||
s64 FSize64(std::FILE* fp);
|
||||
@@ -169,6 +178,10 @@ namespace FileSystem
|
||||
/// Does nothing and returns false on non-Windows platforms.
|
||||
bool SetPathCompression(const char* path, bool enable);
|
||||
|
||||
// Creates a symbolic link. Note that on Windows this requires elevated
|
||||
// privileges so this is mostly useful for testing purposes.
|
||||
bool CreateSymLink(const char* link, const char* target);
|
||||
|
||||
/// Checks if a file or directory is a symbolic link.
|
||||
bool IsSymbolicLink(const char* path);
|
||||
|
||||
|
||||
@@ -88,8 +88,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.interlacing, "EmuCore/GS", "deinterlace_mode", DEFAULT_INTERLACE_MODE);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.bilinearFiltering, "EmuCore/GS", "linear_present_mode", static_cast<int>(GSPostBilinearMode::BilinearSmooth));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.widescreenPatches, "EmuCore", "EnableWideScreenPatches", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.noInterlacingPatches, "EmuCore", "EnableNoInterlacingPatches", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.integerScaling, "EmuCore/GS", "IntegerScaling", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCOffsets, "EmuCore/GS", "pcrtc_offsets", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCOverscan, "EmuCore/GS", "pcrtc_overscan", false);
|
||||
@@ -321,24 +319,22 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get rid of widescreen/no-interlace checkboxes from per-game settings, unless the user previously had them set.
|
||||
if (m_dialog->isPerGameSettings())
|
||||
// Prompt user to get rid of widescreen/no-interlace config from the ini if the user has enabled them before.
|
||||
if ((m_dialog->getBoolValue("EmuCore", "EnableWideScreenPatches", false) == true ||
|
||||
m_dialog->getBoolValue("EmuCore", "EnableWideScreenPatches", false) == true) &&
|
||||
!m_dialog->containsSettingValue("UI", "UserHasDeniedWSPatchWarning"))
|
||||
{
|
||||
if ((m_dialog->containsSettingValue("EmuCore", "EnableWideScreenPatches") || m_dialog->containsSettingValue("EmuCore", "EnableNoInterlacingPatches")) &&
|
||||
QMessageBox::question(QtUtils::GetRootWidget(this), tr("Remove Unsupported Settings"),
|
||||
tr("You currently have the <strong>Enable Widescreen Patches</strong> or <strong>Enable No-Interlacing Patches</strong> options enabled for this game.<br><br>"
|
||||
"We no longer support these options, instead <strong>you should select the \"Patches\" section, and explicitly enable the patches you want.</strong><br><br>"
|
||||
"Do you want to remove these options from your game configuration now?"),
|
||||
if (QMessageBox::question(QtUtils::GetRootWidget(this), tr("Remove Unsupported Settings"),
|
||||
tr("You previously had the <strong>Enable Widescreen Patches</strong> or <strong>Enable No-Interlacing Patches</strong> options enabled.<br><br>"
|
||||
"We no longer provide these options, instead <strong>you should go to the \"Patches\" section on the per-game settings, and explicitly enable the patches that you want.</strong><br><br>"
|
||||
"Do you want to remove these options from your configuration now?"),
|
||||
QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
|
||||
{
|
||||
m_dialog->removeSettingValue("EmuCore", "EnableWideScreenPatches");
|
||||
m_dialog->removeSettingValue("EmuCore", "EnableNoInterlacingPatches");
|
||||
}
|
||||
|
||||
m_ui.displayGridLayout->removeWidget(m_ui.widescreenPatches);
|
||||
m_ui.displayGridLayout->removeWidget(m_ui.noInterlacingPatches);
|
||||
safe_delete(m_ui.widescreenPatches);
|
||||
safe_delete(m_ui.noInterlacingPatches);
|
||||
else
|
||||
m_dialog->setBoolSettingValue("UI", "UserHasDeniedWSPatchWarning", true);
|
||||
}
|
||||
|
||||
// Hide advanced options by default.
|
||||
@@ -350,10 +346,13 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
m_ui.advancedTab = nullptr;
|
||||
m_ui.gsDownloadMode = nullptr;
|
||||
m_ui.gsDumpCompression = nullptr;
|
||||
m_ui.texturePreloading = nullptr;
|
||||
m_ui.exclusiveFullscreenControl = nullptr;
|
||||
m_ui.useBlitSwapChain = nullptr;
|
||||
m_ui.disableMailboxPresentation = nullptr;
|
||||
m_ui.extendedUpscales = nullptr;
|
||||
m_ui.spinCPUDuringReadbacks = nullptr;
|
||||
m_ui.spinGPUDuringReadbacks = nullptr;
|
||||
m_ui.skipPresentingDuplicateFrames = nullptr;
|
||||
m_ui.overrideTextureBarriers = nullptr;
|
||||
m_ui.disableFramebufferFetch = nullptr;
|
||||
@@ -428,12 +427,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
|
||||
// Display tab
|
||||
{
|
||||
dialog->registerWidgetHelp(m_ui.widescreenPatches, tr("Enable Widescreen Patches"), tr("Unchecked"),
|
||||
tr("Automatically loads and applies widescreen patches on game start. Can cause issues."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.noInterlacingPatches, tr("Enable No-Interlacing Patches"), tr("Unchecked"),
|
||||
tr("Automatically loads and applies no-interlacing patches on game start. Can cause issues."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.DisableInterlaceOffset, tr("Disable Interlace Offset"), tr("Unchecked"),
|
||||
tr("Disables interlacing offset which may reduce blurring in some situations."));
|
||||
|
||||
|
||||
@@ -404,28 +404,28 @@
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="displayGridLayout">
|
||||
<item row="1" column="1">
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="integerScaling">
|
||||
<property name="text">
|
||||
<string>Integer Scaling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="widescreenPatches">
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="PCRTCOverscan">
|
||||
<property name="text">
|
||||
<string>Apply Widescreen Patches</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="noInterlacingPatches">
|
||||
<property name="text">
|
||||
<string>Apply No-Interlacing Patches</string>
|
||||
<string>Show Overscan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="PCRTCOffsets">
|
||||
<property name="text">
|
||||
<string>Screen Offsets</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="PCRTCAntiBlur">
|
||||
<property name="text">
|
||||
<string>Anti-Blur</string>
|
||||
@@ -435,27 +435,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="DisableInterlaceOffset">
|
||||
<property name="text">
|
||||
<string>Disable Interlace Offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="PCRTCOffsets">
|
||||
<property name="text">
|
||||
<string>Screen Offsets</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="PCRTCOverscan">
|
||||
<property name="text">
|
||||
<string>Show Overscan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -2125,7 +2111,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<layout class="QGridLayout" name="advancedOptionsGrid">
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="disableMailboxPresentation">
|
||||
<property name="text">
|
||||
|
||||
@@ -155,7 +155,7 @@ void cdvdLoadNVRAM()
|
||||
{
|
||||
Error error;
|
||||
const std::string nvmfile = cdvdGetNVRAMPath();
|
||||
auto fp = FileSystem::OpenManagedCFile(nvmfile.c_str(), "rb", &error);
|
||||
auto fp = FileSystem::OpenManagedCFileTryIgnoreCase(nvmfile.c_str(), "rb", &error);
|
||||
if (!fp || std::fread(s_nvram, sizeof(s_nvram), 1, fp.get()) != 1)
|
||||
{
|
||||
ERROR_LOG("Failed to open or read NVRAM at {}: {}", Path::GetFileName(nvmfile), error.GetDescription());
|
||||
@@ -178,7 +178,7 @@ void cdvdLoadNVRAM()
|
||||
|
||||
// Also load the mechacon version while we're here.
|
||||
const std::string mecfile = Path::ReplaceExtension(BiosPath, "mec");
|
||||
fp = FileSystem::OpenManagedCFile(mecfile.c_str(), "rb", &error);
|
||||
fp = FileSystem::OpenManagedCFileTryIgnoreCase(mecfile.c_str(), "rb", &error);
|
||||
if (!fp || std::fread(&s_mecha_version, sizeof(s_mecha_version), 1, fp.get()) != 1)
|
||||
{
|
||||
s_mecha_version = DEFAULT_MECHA_VERSION;
|
||||
@@ -186,7 +186,7 @@ void cdvdLoadNVRAM()
|
||||
ERROR_LOG("Failed to open or read MEC file at {}: {}, creating default.", Path::GetFileName(nvmfile),
|
||||
error.GetDescription());
|
||||
fp.reset();
|
||||
fp = FileSystem::OpenManagedCFile(mecfile.c_str(), "wb");
|
||||
fp = FileSystem::OpenManagedCFileTryIgnoreCase(mecfile.c_str(), "wb");
|
||||
if (!fp || std::fwrite(&s_mecha_version, sizeof(s_mecha_version), 1, fp.get()) != 1)
|
||||
Host::ReportErrorAsync("Error", "Failed to write MEC file. Check your BIOS setup/permission settings.");
|
||||
}
|
||||
@@ -197,10 +197,10 @@ void cdvdSaveNVRAM()
|
||||
{
|
||||
Error error;
|
||||
const std::string nvmfile = cdvdGetNVRAMPath();
|
||||
auto fp = FileSystem::OpenManagedCFile(nvmfile.c_str(), "r+b", &error);
|
||||
auto fp = FileSystem::OpenManagedCFileTryIgnoreCase(nvmfile.c_str(), "r+b", &error);
|
||||
if (!fp)
|
||||
{
|
||||
fp = FileSystem::OpenManagedCFile(nvmfile.c_str(), "w+b", &error);
|
||||
fp = FileSystem::OpenManagedCFileTryIgnoreCase(nvmfile.c_str(), "w+b", &error);
|
||||
if (!fp) [[unlikely]]
|
||||
{
|
||||
ERROR_LOG("Failed to open NVRAM at {} for updating: {}", Path::GetFileName(nvmfile), error.GetDescription());
|
||||
|
||||
@@ -20,6 +20,74 @@ static constexpr u32 MAX_PARENTS = 32; // Surely someone wouldn't be insane enou
|
||||
static std::vector<std::pair<std::string, chd_header>> s_chd_hash_cache; // <filename, header>
|
||||
static std::recursive_mutex s_chd_hash_cache_mutex;
|
||||
|
||||
// Provides an implementation of core_file which allows us to control if the underlying FILE handle is freed.
|
||||
// The lifetime of ChdCoreFileWrapper will be equal to that of the relevant chd_file,
|
||||
// ChdCoreFileWrapper will also get destroyed if chd_open_core_file fails.
|
||||
class ChdCoreFileWrapper
|
||||
{
|
||||
DeclareNoncopyableObject(ChdCoreFileWrapper);
|
||||
|
||||
private:
|
||||
core_file m_core;
|
||||
std::FILE* m_file;
|
||||
bool m_free_file = false;
|
||||
|
||||
public:
|
||||
ChdCoreFileWrapper(std::FILE* file)
|
||||
: m_file{file}
|
||||
{
|
||||
m_core.argp = this;
|
||||
m_core.fsize = FSize;
|
||||
m_core.fread = FRead;
|
||||
m_core.fclose = FClose;
|
||||
m_core.fseek = FSeek;
|
||||
}
|
||||
|
||||
~ChdCoreFileWrapper()
|
||||
{
|
||||
if (m_free_file)
|
||||
std::fclose(m_file);
|
||||
}
|
||||
|
||||
core_file* GetCoreFile()
|
||||
{
|
||||
return &m_core;
|
||||
}
|
||||
|
||||
static ChdCoreFileWrapper* FromCoreFile(core_file* file)
|
||||
{
|
||||
return reinterpret_cast<ChdCoreFileWrapper*>(file->argp);
|
||||
}
|
||||
|
||||
void SetFileOwner(bool isOwner)
|
||||
{
|
||||
m_free_file = isOwner;
|
||||
}
|
||||
|
||||
private:
|
||||
static u64 FSize(core_file* file)
|
||||
{
|
||||
return static_cast<u64>(FileSystem::FSize64(FromCoreFile(file)->m_file));
|
||||
}
|
||||
|
||||
static size_t FRead(void* buffer, size_t elmSize, size_t elmCount, core_file* file)
|
||||
{
|
||||
return std::fread(buffer, elmSize, elmCount, FromCoreFile(file)->m_file);
|
||||
}
|
||||
|
||||
static int FClose(core_file* file)
|
||||
{
|
||||
// Destructor handles freeing the FILE handle.
|
||||
delete FromCoreFile(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FSeek(core_file* file, int64_t offset, int whence)
|
||||
{
|
||||
return FileSystem::FSeek64(FromCoreFile(file)->m_file, offset, whence);
|
||||
}
|
||||
};
|
||||
|
||||
ChdFileReader::ChdFileReader() = default;
|
||||
|
||||
ChdFileReader::~ChdFileReader()
|
||||
@@ -30,10 +98,13 @@ ChdFileReader::~ChdFileReader()
|
||||
static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePtr fp, Error* error, u32 recursion_level)
|
||||
{
|
||||
chd_file* chd;
|
||||
chd_error err = chd_open_file(fp.get(), CHD_OPEN_READ | CHD_OPEN_TRANSFER_FILE, nullptr, &chd);
|
||||
ChdCoreFileWrapper* core_wrapper = new ChdCoreFileWrapper(fp.get());
|
||||
// libchdr will take ownership of core_wrapper, and will close/free it on failure.
|
||||
chd_error err = chd_open_core_file(core_wrapper->GetCoreFile(), CHD_OPEN_READ, nullptr, &chd);
|
||||
if (err == CHDERR_NONE)
|
||||
{
|
||||
// fp is now managed by libchdr
|
||||
// core_wrapper should manage fp.
|
||||
core_wrapper->SetFileOwner(true);
|
||||
fp.release();
|
||||
return chd;
|
||||
}
|
||||
@@ -105,7 +176,7 @@ static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePt
|
||||
parent_dir.c_str(), "*.*", FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES | FILESYSTEM_FIND_KEEP_ARRAY, &parent_files);
|
||||
for (FILESYSTEM_FIND_DATA& fd : parent_files)
|
||||
{
|
||||
if (StringUtil::EndsWithNoCase(Path::GetExtension(fd.FileName), ".chd"))
|
||||
if (!StringUtil::EndsWithNoCase(Path::GetExtension(fd.FileName), "chd"))
|
||||
continue;
|
||||
|
||||
// Re-check the header, it might have changed since we last opened.
|
||||
@@ -140,8 +211,10 @@ static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePt
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Our last core file wrapper got freed, so make a new one.
|
||||
core_wrapper = new ChdCoreFileWrapper(fp.get());
|
||||
// Now try re-opening with the parent.
|
||||
err = chd_open_file(fp.get(), CHD_OPEN_READ | CHD_OPEN_TRANSFER_FILE, parent_chd, &chd);
|
||||
err = chd_open_core_file(core_wrapper->GetCoreFile(), CHD_OPEN_READ, parent_chd, &chd);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
Console.Error(fmt::format("Failed to open CHD '{}': {}", filename, chd_error_string(err)));
|
||||
@@ -149,7 +222,8 @@ static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePt
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// fp now owned by libchdr
|
||||
// core_wrapper should manage fp.
|
||||
core_wrapper->SetFileOwner(true);
|
||||
fp.release();
|
||||
return chd;
|
||||
}
|
||||
|
||||
@@ -1268,8 +1268,6 @@ struct Pcsx2Config
|
||||
EnablePatches : 1, // enables patch detection and application
|
||||
EnableCheats : 1, // enables cheat detection and application
|
||||
EnablePINE : 1, // enables inter-process communication
|
||||
EnableWideScreenPatches : 1,
|
||||
EnableNoInterlacingPatches : 1,
|
||||
EnableFastBoot : 1,
|
||||
EnableFastBootFastForward : 1,
|
||||
EnableThreadPinning : 1,
|
||||
|
||||
@@ -1012,7 +1012,8 @@ bool GSRendererHW::NextDrawMatchesShuffle() const
|
||||
{
|
||||
// Make sure nothing unexpected has changed.
|
||||
// Twinsanity seems to screw with ZBUF here despite it being irrelevant.
|
||||
const GSDrawingContext& next_ctx = m_env.CTXT[m_backed_up_ctx];
|
||||
const int get_next_ctx = (m_state_flush_reason == CONTEXTCHANGE) ? m_env.PRIM.CTXT : m_backed_up_ctx;
|
||||
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
|
||||
if (((m_context->TEX0.U64 ^ next_ctx.TEX0.U64) & (~0x3FFF)) != 0 ||
|
||||
m_context->TEX1.U64 != next_ctx.TEX1.U64 ||
|
||||
m_context->CLAMP.U64 != next_ctx.CLAMP.U64 ||
|
||||
@@ -4553,7 +4554,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
// Disable dithering on blend mix if needed.
|
||||
if (m_conf.ps.dither)
|
||||
{
|
||||
const bool can_dither = (m_conf.ps.blend_a == 0 && m_conf.ps.blend_b == 1 && alpha_eq_less_one);
|
||||
// TODO: Either exclude BMIX1_ALPHA_HIGH_ONE case or allow alpha > 1.0 on dither adjust, case is currently disabled.
|
||||
const bool can_dither = (m_conf.ps.blend_a == 0 && m_conf.ps.blend_b == 1) || (m_conf.ps.blend_a == 1 && m_conf.ps.blend_b == 0);
|
||||
m_conf.ps.dither = can_dither;
|
||||
m_conf.ps.dither_adjust = can_dither;
|
||||
}
|
||||
|
||||
@@ -1742,9 +1742,12 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
TEX0.TBP0, psm_s.pal > 0 ? TEX0.CBP : 0,
|
||||
psm_str(TEX0.PSM));
|
||||
|
||||
// If it's from a target, we need to make sure the alpha information is up to date, especially in 16/24 bit formats where it can change draw to draw.
|
||||
// If it's an old source made from target make sure it isn't a palette,
|
||||
// alphas need to be used from the palette then.
|
||||
// If it's from a target, we need to make sure the alpha information is up to date,
|
||||
// especially in 16/24 bit formats where it can change draw to draw.
|
||||
// Guard against merged targets which don't actually link.
|
||||
if (src->m_target && src->m_from_target)
|
||||
if (!src->m_palette && src->m_target && src->m_from_target)
|
||||
{
|
||||
src->m_valid_alpha_minmax = true;
|
||||
if (src->m_target_direct)
|
||||
|
||||
@@ -3705,15 +3705,6 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
|
||||
"EmuCore/GS", "StretchY", 100, 10, 300, FSUI_CSTR("%d%%"));
|
||||
DrawIntRectSetting(bsi, FSUI_CSTR("Crop"), FSUI_CSTR("Crops the image, while respecting aspect ratio."), "EmuCore/GS", "CropLeft", 0,
|
||||
"CropTop", 0, "CropRight", 0, "CropBottom", 0, 0, 720, 1, FSUI_CSTR("%dpx"));
|
||||
|
||||
if (!IsEditingGameSettings(bsi))
|
||||
{
|
||||
DrawToggleSetting(bsi, FSUI_CSTR("Enable Widescreen Patches"), FSUI_CSTR("Enables loading widescreen patches from pnach files."),
|
||||
"EmuCore", "EnableWideScreenPatches", false);
|
||||
DrawToggleSetting(bsi, FSUI_CSTR("Enable No-Interlacing Patches"),
|
||||
FSUI_CSTR("Enables loading no-interlacing patches from pnach files."), "EmuCore", "EnableNoInterlacingPatches", false);
|
||||
}
|
||||
|
||||
DrawIntListSetting(bsi, FSUI_CSTR("Bilinear Upscaling"), FSUI_CSTR("Smooths out the image when upscaling the console to the screen."),
|
||||
"EmuCore/GS", "linear_present_mode", static_cast<int>(GSPostBilinearMode::BilinearSharp), s_bilinear_present_options,
|
||||
std::size(s_bilinear_present_options), true);
|
||||
|
||||
@@ -397,10 +397,9 @@ __ri void ImGuiManager::DrawSettingsOverlay(float scale, float margin, float spa
|
||||
EmuConfig.Cpu.Recompiler.GetEEClampMode(), static_cast<unsigned>(EmuConfig.Cpu.VU0FPCR.GetRoundMode()),
|
||||
EmuConfig.Cpu.Recompiler.GetVUClampMode(), EmuConfig.GS.VsyncQueueSize);
|
||||
|
||||
if (EmuConfig.EnableCheats || EmuConfig.EnableWideScreenPatches || EmuConfig.EnableNoInterlacingPatches)
|
||||
if (EmuConfig.EnableCheats)
|
||||
{
|
||||
APPEND("C={}{}{} ", EmuConfig.EnableCheats ? "C" : "", EmuConfig.EnableWideScreenPatches ? "W" : "",
|
||||
EmuConfig.EnableNoInterlacingPatches ? "N" : "");
|
||||
APPEND("CHT ");
|
||||
}
|
||||
|
||||
if (GSIsHardwareRenderer())
|
||||
|
||||
@@ -163,9 +163,6 @@ namespace Patch
|
||||
static void writeCheat();
|
||||
static void handle_extended_t(const PatchCommand* p);
|
||||
|
||||
// Name of patches which will be auto-enabled based on global options.
|
||||
static constexpr std::string_view WS_PATCH_NAME = "Widescreen 16:9";
|
||||
static constexpr std::string_view NI_PATCH_NAME = "No-Interlacing";
|
||||
static constexpr std::string_view PATCHES_ZIP_NAME = "patches.zip";
|
||||
|
||||
const char* PATCHES_CONFIG_SECTION = "Patches";
|
||||
@@ -588,24 +585,6 @@ void Patch::ReloadEnabledLists()
|
||||
s_enabled_cheats = {};
|
||||
|
||||
s_enabled_patches = Host::GetStringListSetting(PATCHES_CONFIG_SECTION, PATCH_ENABLE_CONFIG_KEY);
|
||||
|
||||
// Name based matching for widescreen/NI settings.
|
||||
if (EmuConfig.EnableWideScreenPatches)
|
||||
{
|
||||
if (std::none_of(s_enabled_patches.begin(), s_enabled_patches.end(),
|
||||
[](const std::string& it) { return (it == WS_PATCH_NAME); }))
|
||||
{
|
||||
s_enabled_patches.emplace_back(WS_PATCH_NAME);
|
||||
}
|
||||
}
|
||||
if (EmuConfig.EnableNoInterlacingPatches)
|
||||
{
|
||||
if (std::none_of(s_enabled_patches.begin(), s_enabled_patches.end(),
|
||||
[](const std::string& it) { return (it == NI_PATCH_NAME); }))
|
||||
{
|
||||
s_enabled_patches.emplace_back(NI_PATCH_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable_list)
|
||||
|
||||
@@ -4,18 +4,16 @@
|
||||
#pragma once
|
||||
|
||||
// Note about terminology:
|
||||
// "patch" in pcsx2 terminology is a single pnach style patch line, e.g. patch=1,EE,001110e0,word,00000000
|
||||
// "Patch" in PCSX2 terminology refers to a single pnach style patch line, e.g. `patch=1,EE,001110e0,word,00000000`
|
||||
// Such patches can appear in several places:
|
||||
// - At <CRC>.pnach files where each file could have several such patches:
|
||||
// - At the "cheats" folder
|
||||
// - UI name: "Cheats", controlled via system -> enable cheats
|
||||
// - At the "cheats_ws" folder or inside "cheats_ws.zip" (the zip also called "widescreen cheats DB")
|
||||
// - the latter is searched if the former is not found for a CRC
|
||||
// - UI name: "Widescreen hacks/patches", controlled via system -> enable widescreen patches
|
||||
// - At GameIndex.yaml inside a [patches] section
|
||||
// - UI name: "Patches", controlled via system -> enable automatic game fixes
|
||||
// - note that automatic game fixes also controls automatic config changes from GameIndex.dbf (UI name: "fixes")
|
||||
//
|
||||
// - At the "patches" folder or on the "patches.zip file inside the 'resources' folder
|
||||
// - UI name: "Patch", Controlled via Per-Game Settings -> Patches
|
||||
// - At the "cheats" folder
|
||||
// - UI name: "Cheats", Controlled via Per-Game Settings -> Cheats -> Enable Cheat
|
||||
// - At GameIndex.yaml inside a [patches] section
|
||||
// - UI name: "Enable Compatibility Patches", controlled via Advanced section -> Enable compatability settings
|
||||
// Note: The file name has to be exactly "<Serial>_<CRC>.pnach" (For example "SLPS-25399_CD62245A.pnach")
|
||||
// Note #2: the old sytle of cheats are also supported but arent supported by the UI
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
|
||||
@@ -1922,8 +1922,6 @@ void Pcsx2Config::LoadSaveCore(SettingsWrapper& wrap)
|
||||
SettingsWrapBitBool(EnablePatches);
|
||||
SettingsWrapBitBool(EnableCheats);
|
||||
SettingsWrapBitBool(EnablePINE);
|
||||
SettingsWrapBitBool(EnableWideScreenPatches);
|
||||
SettingsWrapBitBool(EnableNoInterlacingPatches);
|
||||
SettingsWrapBitBool(EnableFastBoot);
|
||||
SettingsWrapBitBool(EnableFastBootFastForward);
|
||||
SettingsWrapBitBool(EnableThreadPinning);
|
||||
|
||||
@@ -315,7 +315,7 @@ memLoadingState::memLoadingState(const VmStateBuffer& load_from)
|
||||
// Loading of state data from a memory buffer...
|
||||
void memLoadingState::FreezeMem( void* data, int size )
|
||||
{
|
||||
if (m_idx + size > m_memory.size())
|
||||
if (static_cast<u32>(m_idx + size) > m_memory.size())
|
||||
m_error = true;
|
||||
|
||||
if (m_error)
|
||||
|
||||
@@ -2885,8 +2885,6 @@ void VMManager::CheckForEmulationSpeedConfigChanges(const Pcsx2Config& old_confi
|
||||
void VMManager::CheckForPatchConfigChanges(const Pcsx2Config& old_config)
|
||||
{
|
||||
if (EmuConfig.EnableCheats == old_config.EnableCheats &&
|
||||
EmuConfig.EnableWideScreenPatches == old_config.EnableWideScreenPatches &&
|
||||
EmuConfig.EnableNoInterlacingPatches == old_config.EnableNoInterlacingPatches &&
|
||||
EmuConfig.EnablePatches == old_config.EnablePatches)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -226,7 +226,7 @@ static void LoadExtraRom(const char* ext, u32 offset, u32 size)
|
||||
|
||||
BiosRom.resize(offset + size);
|
||||
|
||||
auto fp = FileSystem::OpenManagedCFile(Bios1.c_str(), "rb");
|
||||
auto fp = FileSystem::OpenManagedCFileTryIgnoreCase(Bios1.c_str(), "rb");
|
||||
if (!fp || std::fread(&BiosRom[offset], static_cast<size_t>(std::min<s64>(size, filesize)), 1, fp.get()) != 1)
|
||||
{
|
||||
Console.Warning("BIOS Warning: %s could not be read (permission denied?)", ext);
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
static std::optional<std::string> create_test_directory()
|
||||
{
|
||||
for (u16 i = 0; i < UINT16_MAX; i++)
|
||||
@@ -42,13 +40,13 @@ TEST(FileSystem, RecursiveDeleteDirectoryDontFollowSymbolicLinks)
|
||||
std::string dir_to_delete = Path::Combine(*test_dir, "dir_to_delete");
|
||||
ASSERT_TRUE(FileSystem::CreateDirectoryPath(dir_to_delete.c_str(), false));
|
||||
std::string symlink_path = Path::Combine(dir_to_delete, "link");
|
||||
ASSERT_EQ(symlink(target_dir.c_str(), symlink_path.c_str()), 0);
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(symlink_path.c_str(), target_dir.c_str()));
|
||||
|
||||
// Delete the directory containing the symlink.
|
||||
ASSERT_TRUE(dir_to_delete.starts_with("/tmp/"));
|
||||
ASSERT_TRUE(dir_to_delete.starts_with("/tmp/pcsx2_filesystem_test_"));
|
||||
ASSERT_TRUE(FileSystem::RecursiveDeleteDirectory(dir_to_delete.c_str()));
|
||||
|
||||
// Make sure the target file didn't get deleted.
|
||||
// Make sure the file in the target directory didn't get deleted.
|
||||
ASSERT_TRUE(FileSystem::FileExists(file_path.c_str()));
|
||||
|
||||
// Clean up.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/Path.h"
|
||||
#include <gtest/gtest.h>
|
||||
@@ -238,16 +239,129 @@ TEST(Path, CreateFileURL)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if __linux__
|
||||
|
||||
// Relies on presence of files.
|
||||
TEST(Path, RealPath)
|
||||
static std::optional<std::string> create_test_directory()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::RealPath("C:\\Users\\Me\\Desktop\\foo\\baz"), "C:\\Users\\Me\\Desktop\\foo\\bar\\baz");
|
||||
#else
|
||||
ASSERT_EQ(Path::RealPath("/lib/foo/bar"), "/usr/lib/foo/bar");
|
||||
#endif
|
||||
for (u16 i = 0; i < UINT16_MAX; i++)
|
||||
{
|
||||
std::string path = std::string("/tmp/pcsx2_path_test_") + std::to_string(i);
|
||||
if (!FileSystem::DirectoryExists(path.c_str()))
|
||||
{
|
||||
if (!FileSystem::CreateDirectoryPath(path.c_str(), false))
|
||||
break;
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
TEST(Path, RealPathAbsoluteSymbolicLink)
|
||||
{
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a file to point at.
|
||||
std::string file_path = Path::Combine(*test_dir, "file");
|
||||
ASSERT_TRUE(FileSystem::WriteStringToFile(file_path.c_str(), "Hello, world!"));
|
||||
|
||||
// Create a symbolic link that points to said file.
|
||||
std::string link_path = Path::Combine(*test_dir, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(link_path.c_str(), file_path.c_str()));
|
||||
|
||||
// Make sure the symbolic link is resolved correctly.
|
||||
ASSERT_EQ(Path::RealPath(link_path), file_path);
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteSymbolicLink(link_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteFilePath(file_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
TEST(Path, RealPathRelativeSymbolicLink)
|
||||
{
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a file to point at.
|
||||
std::string file_path = Path::Combine(*test_dir, "file");
|
||||
ASSERT_TRUE(FileSystem::WriteStringToFile(file_path.c_str(), "Hello, world!"));
|
||||
|
||||
// Create a symbolic link that points to said file.
|
||||
std::string link_path = Path::Combine(*test_dir, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(link_path.c_str(), "file"));
|
||||
|
||||
// Make sure the symbolic link is resolved correctly.
|
||||
ASSERT_EQ(Path::RealPath(link_path), file_path);
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteSymbolicLink(link_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteFilePath(file_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
TEST(Path, RealPathDotDotSymbolicLink)
|
||||
{
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a file to point at.
|
||||
std::string file_path = Path::Combine(*test_dir, "file");
|
||||
ASSERT_TRUE(FileSystem::WriteStringToFile(file_path.c_str(), "Hello, world!"));
|
||||
|
||||
// Create a directory to put the link in.
|
||||
std::string link_dir = Path::Combine(*test_dir, "dir");
|
||||
ASSERT_TRUE(FileSystem::CreateDirectoryPath(link_dir.c_str(), false));
|
||||
|
||||
// Create a symbolic link that points to said file.
|
||||
std::string link_path = Path::Combine(link_dir, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(link_path.c_str(), "../file"));
|
||||
|
||||
// Make sure the symbolic link is resolved correctly.
|
||||
ASSERT_EQ(Path::RealPath(link_path), file_path);
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteSymbolicLink(link_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(link_dir.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteFilePath(file_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
TEST(Path, RealPathCircularSymbolicLink)
|
||||
{
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a circular symbolic link.
|
||||
std::string link_path = Path::Combine(*test_dir, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(link_path.c_str(), "."));
|
||||
|
||||
// Make sure the link gets resolved correctly.
|
||||
ASSERT_EQ(Path::RealPath(link_path), *test_dir);
|
||||
ASSERT_EQ(Path::RealPath(Path::Combine(link_path, "link")), *test_dir);
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteSymbolicLink(link_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
TEST(Path, RealPathLoopingSymbolicLink)
|
||||
{
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a symbolic link that points to itself.
|
||||
std::string link_path = Path::Combine(*test_dir, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(link_path.c_str(), "link"));
|
||||
|
||||
// Make sure this doesn't cause problems.
|
||||
ASSERT_EQ(Path::RealPath(link_path), link_path);
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteSymbolicLink(link_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user