Updated VMA library to newest stable 3.1.0 version
|
@ -4,4 +4,4 @@ cd ..
|
|||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DONATIVE=ON -DFFMPEG=OFF -DBINKDEC=ON -DUSE_PRECOMPILED_HEADERS=ON -DUSE_INTRINSICS_SSE=ON ../neo
|
||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DONATIVE=ON -DFFMPEG=OFF -DBINKDEC=ON -DUSE_PRECOMPILED_HEADERS=ON -DUSE_INTRINSICS_SSE=OFF ../neo
|
||||
|
|
|
@ -1,3 +1,29 @@
|
|||
# 3.1.0 (2024-05-27)
|
||||
|
||||
This release gathers fixes and improvements made during many months of continuous development on the main branch, mostly based on issues and pull requests on GitHub.
|
||||
|
||||
Additions to the library API:
|
||||
|
||||
- Added convenience functions `vmaCopyMemoryToAllocation`, `vmaCopyAllocationToMemory`.
|
||||
- Added functions `vmaCreateAliasingBuffer2`, `vmaCreateAliasingImage2` that offer creating a buffer/image in an existing allocation with additional `allocationLocalOffset`.
|
||||
- Added function `vmaGetAllocationInfo2`, structure `VmaAllocationInfo2` that return additional information about an allocation, useful for interop with other APIs (#383, #340).
|
||||
- Added callback `VmaDefragmentationInfo::pfnBreakCallback` that allows breaking long execution of `vmaBeginDefragmentation`.
|
||||
Also added `PFN_vmaCheckDefragmentationBreakFunction`, `VmaDefragmentationInfo::pBreakCallbackUserData`.
|
||||
- Added support for VK_KHR_maintenance4 extension - `VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT` flag (#397).
|
||||
- Added support for VK_KHR_maintenance5 extension - `VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT` flag (#411).
|
||||
|
||||
Other changes:
|
||||
|
||||
- Changes in debug and configuration macros:
|
||||
- Split macros into separate `VMA_DEBUG_LOG` and `VMA_DEBUG_LOG_FORMAT` (#297).
|
||||
- Added macros `VMA_ASSERT_LEAK`, `VMA_LEAK_LOG_FORMAT` separate from normal `VMA_ASSERT`, `VMA_DEBUG_LOG_FORMAT` (#379, #385).
|
||||
- Added macro `VMA_EXTENDS_VK_STRUCT` (#347).
|
||||
- Countless bug fixes and improvements in the code and documentation, mostly to improve compatibility with various compilers and GPUs, including:
|
||||
- Fixed missing `#include` that resulted in compilation error about `snprintf` not declared on some compilers (#312).
|
||||
- Fixed main memory type selection algorithm for GPUs that have no `HOST_CACHED` memory type, like Raspberry Pi (#362).
|
||||
- Major changes in Cmake script.
|
||||
- Fixes in GpuMemDumpVis.py script.
|
||||
|
||||
# 3.0.1 (2022-05-26)
|
||||
|
||||
- Fixes in defragmentation algorithm.
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.9)
|
||||
|
||||
project(VulkanMemoryAllocator LANGUAGES CXX)
|
||||
|
||||
# https://cmake.org/cmake/help/latest/variable/PROJECT_IS_TOP_LEVEL.html
|
||||
string(COMPARE EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} PROJECT_IS_TOP_LEVEL)
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
find_package(Vulkan REQUIRED)
|
||||
include_directories(${Vulkan_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
# VulkanMemoryAllocator contains an sample application which is not built by default
|
||||
option(VMA_BUILD_SAMPLE "Build VulkanMemoryAllocator sample application" OFF)
|
||||
option(VMA_BUILD_SAMPLE_SHADERS "Build VulkanMemoryAllocator sample application's shaders" OFF)
|
||||
|
||||
message(STATUS "VMA_BUILD_SAMPLE = ${VMA_BUILD_SAMPLE}")
|
||||
message(STATUS "VMA_BUILD_SAMPLE_SHADERS = ${VMA_BUILD_SAMPLE_SHADERS}")
|
||||
|
||||
option(VMA_STATIC_VULKAN_FUNCTIONS "Link statically with Vulkan API" ON)
|
||||
option(VMA_DYNAMIC_VULKAN_FUNCTIONS "Fetch pointers to Vulkan functions internally (no static linking)" OFF)
|
||||
option(VMA_DEBUG_ALWAYS_DEDICATED_MEMORY "Every allocation will have its own memory block" OFF)
|
||||
option(VMA_DEBUG_INITIALIZE_ALLOCATIONS "Automatically fill new allocations and destroyed allocations with some bit pattern" OFF)
|
||||
option(VMA_DEBUG_GLOBAL_MUTEX "Enable single mutex protecting all entry calls to the library" OFF)
|
||||
option(VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT "Never exceed VkPhysicalDeviceLimits::maxMemoryAllocationCount and return error" OFF)
|
||||
|
||||
message(STATUS "VMA_STATIC_VULKAN_FUNCTIONS = ${VMA_STATIC_VULKAN_FUNCTIONS}")
|
||||
message(STATUS "VMA_DYNAMIC_VULKAN_FUNCTIONS = ${VMA_DYNAMIC_VULKAN_FUNCTIONS}")
|
||||
message(STATUS "VMA_DEBUG_ALWAYS_DEDICATED_MEMORY = ${VMA_DEBUG_ALWAYS_DEDICATED_MEMORY}")
|
||||
message(STATUS "VMA_DEBUG_INITIALIZE_ALLOCATIONS = ${VMA_DEBUG_INITIALIZE_ALLOCATIONS}")
|
||||
message(STATUS "VMA_DEBUG_GLOBAL_MUTEX = ${VMA_DEBUG_GLOBAL_MUTEX}")
|
||||
message(STATUS "VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT = ${VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT}")
|
||||
|
||||
if(VMA_BUILD_SAMPLE)
|
||||
set(VMA_BUILD_SAMPLE_SHADERS ON)
|
||||
endif()
|
||||
|
||||
option(BUILD_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" OFF)
|
||||
|
||||
if(BUILD_DOCUMENTATION)
|
||||
find_package(Doxygen REQUIRED)
|
||||
# set input and output files
|
||||
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
|
||||
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||
# request to configure the file
|
||||
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
|
||||
# note the option ALL which allows to build the docs together with the application
|
||||
add_custom_target( doc_doxygen ALL
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating API documentation with Doxygen"
|
||||
VERBATIM )
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
|
@ -51,10 +51,13 @@ Additional features:
|
|||
- Support for Vulkan 1.0, 1.1, 1.2, 1.3.
|
||||
- Support for extensions (and equivalent functionality included in new Vulkan versions):
|
||||
- VK_KHR_dedicated_allocation: Just enable it and it will be used automatically by the library.
|
||||
- VK_KHR_buffer_device_address: Flag `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR` is automatically added to memory allocations where needed.
|
||||
- VK_KHR_bind_memory2.
|
||||
- VK_KHR_maintenance4.
|
||||
- VK_KHR_maintenance5, including `VkBufferUsageFlags2CreateInfoKHR`.
|
||||
- VK_EXT_memory_budget: Used internally if available to query for current usage and budget. If not available, it falls back to an estimation based on memory heap sizes.
|
||||
- VK_KHR_buffer_device_address: Flag `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR` is automatically added to memory allocations where needed.
|
||||
- VK_EXT_memory_priority: Set `priority` of allocations or custom pools and it will be set automatically using this extension.
|
||||
- VK_AMD_device_coherent_memory
|
||||
- VK_AMD_device_coherent_memory.
|
||||
- Defragmentation of GPU and CPU memory: 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 blocks, number of allocations etc. - globally, per memory heap, and per memory type.
|
||||
- Debug annotations: Associate custom `void* pUserData` and debug `char* pName` with each allocation.
|
||||
|
@ -99,38 +102,35 @@ With this one function call:
|
|||
|
||||
# How to build
|
||||
|
||||
On Windows it is recommended to use [CMake UI](https://cmake.org/runningcmake/). Alternatively you can generate a Visual Studio project map using CMake in command line: `cmake -B./build/ -DCMAKE_BUILD_TYPE=Debug -G "Visual Studio 16 2019" -A x64 ./`
|
||||
On Windows it is recommended to use [CMake GUI](https://cmake.org/runningcmake/).
|
||||
|
||||
Alternatively you can generate/open a Visual Studio from the command line:
|
||||
|
||||
```sh
|
||||
# By default CMake picks the newest version of Visual Studio it can use
|
||||
cmake -S . -B build -D VMA_BUILD_SAMPLES=ON
|
||||
cmake --open build
|
||||
```
|
||||
|
||||
On Linux:
|
||||
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```sh
|
||||
cmake -S . -B build
|
||||
# Since VMA has no source files, you can skip to installation immediately
|
||||
cmake --install build --prefix build/install
|
||||
```
|
||||
|
||||
The following targets are available
|
||||
## How to use
|
||||
|
||||
| Target | Description | CMake option | Default setting |
|
||||
| ------------- | ------------- | ------------- | ------------- |
|
||||
| VmaSample | VMA sample application | `VMA_BUILD_SAMPLE` | `OFF` |
|
||||
| VmaBuildSampleShaders | Shaders for VmaSample | `VMA_BUILD_SAMPLE_SHADERS` | `OFF` |
|
||||
After calling either `find_package` or `add_subdirectory` simply link the library.
|
||||
This automatically handles configuring the include directory. Example:
|
||||
|
||||
Please note that while VulkanMemoryAllocator library is supported on other platforms besides Windows, VmaSample is not.
|
||||
```cmake
|
||||
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
||||
target_link_libraries(YourGameEngine PRIVATE GPUOpen::VulkanMemoryAllocator)
|
||||
```
|
||||
|
||||
These CMake options are available
|
||||
|
||||
| CMake option | Description | Default setting |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| `VMA_RECORDING_ENABLED` | Enable VMA memory recording for debugging | `OFF` |
|
||||
| `VMA_USE_STL_CONTAINERS` | Use C++ STL containers instead of VMA's containers | `OFF` |
|
||||
| `VMA_STATIC_VULKAN_FUNCTIONS` | Link statically with Vulkan API | `OFF` |
|
||||
| `VMA_DYNAMIC_VULKAN_FUNCTIONS` | Fetch pointers to Vulkan functions internally (no static linking) | `ON` |
|
||||
| `VMA_DEBUG_ALWAYS_DEDICATED_MEMORY` | Every allocation will have its own memory block | `OFF` |
|
||||
| `VMA_DEBUG_INITIALIZE_ALLOCATIONS` | Automatically fill new allocations and destroyed allocations with some bit pattern | `OFF` |
|
||||
| `VMA_DEBUG_GLOBAL_MUTEX` | Enable single mutex protecting all entry calls to the library | `OFF` |
|
||||
| `VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT` | Never exceed [VkPhysicalDeviceLimits::maxMemoryAllocationCount](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#limits-maxMemoryAllocationCount) and return error | `OFF` |
|
||||
For more info on using CMake visit the official [CMake documentation](https://cmake.org/cmake/help/latest/index.html).
|
||||
|
||||
## Building using vcpkg
|
||||
|
||||
|
@ -146,7 +146,7 @@ The VulkanMemoryAllocator port in vcpkg is kept up to date by Microsoft team mem
|
|||
|
||||
# Binaries
|
||||
|
||||
The release comes with precompiled binary executable for "VulkanSample" application which contains test suite. It is compiled using Visual Studio 2019, so it requires appropriate libraries to work, including "MSVCP140.dll", "VCRUNTIME140.dll", "VCRUNTIME140_1.dll". If the launch fails with error message telling about those files missing, please download and install [Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads), "x64" version.
|
||||
The release comes with precompiled binary executable for "VulkanSample" application which contains test suite. It is compiled using Visual Studio 2022, so it requires appropriate libraries to work, including "MSVCP140.dll", "VCRUNTIME140.dll", "VCRUNTIME140_1.dll". If the launch fails with error message telling about those files missing, please download and install [Microsoft Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads), "X64" version.
|
||||
|
||||
# Read more
|
||||
|
||||
|
@ -154,24 +154,30 @@ See **[Documentation](https://gpuopen-librariesandsdks.github.io/VulkanMemoryAll
|
|||
|
||||
# Software using this library
|
||||
|
||||
- **[Blender](https://www.blender.org)**
|
||||
- **[Baldur's Gate III](https://www.mobygames.com/game/150689/baldurs-gate-iii/credits/windows/?autoplatform=true)**
|
||||
- **[Cyberpunk 2077](https://www.mobygames.com/game/128136/cyberpunk-2077/credits/windows/?autoplatform=true)**
|
||||
- **[X-Plane](https://x-plane.com/)**
|
||||
- **[Detroit: Become Human](https://gpuopen.com/learn/porting-detroit-3/)**
|
||||
- **[Vulkan Samples](https://github.com/LunarG/VulkanSamples)** - official Khronos Vulkan samples. License: Apache-style.
|
||||
- **[GFXReconstruct](https://github.com/LunarG/gfxreconstruct)** - a tools for the capture and replay of graphics API calls. License: MIT.
|
||||
- **[Anvil](https://github.com/GPUOpen-LibrariesAndSDKs/Anvil)** - cross-platform framework for Vulkan. License: MIT.
|
||||
- **[Filament](https://github.com/google/filament)** - physically based rendering engine for Android, Windows, Linux and macOS, from Google. Apache License 2.0.
|
||||
- **[Atypical Games - proprietary game engine](https://developer.samsung.com/galaxy-gamedev/gamedev-blog/infinitejet.html)**
|
||||
- **[Flax Engine](https://flaxengine.com/)**
|
||||
- **[Godot Engine](https://github.com/godotengine/godot/)** - multi-platform 2D and 3D game engine. License: MIT.
|
||||
- **[Lightweight Java Game Library (LWJGL)](https://www.lwjgl.org/)** - includes binding of the library for Java. License: BSD.
|
||||
- **[LightweightVK](https://github.com/corporateshark/lightweightvk)** - lightweight C++ bindless Vulkan 1.3 wrapper. License: MIT.
|
||||
- **[PowerVR SDK](https://github.com/powervr-graphics/Native_SDK)** - C++ cross-platform 3D graphics SDK, from Imagination. License: MIT.
|
||||
- **[Skia](https://github.com/google/skia)** - complete 2D graphic library for drawing Text, Geometries, and Images, from Google.
|
||||
- **[The Forge](https://github.com/ConfettiFX/The-Forge)** - cross-platform rendering framework. Apache License 2.0.
|
||||
- **[VK9](https://github.com/disks86/VK9)** - Direct3D 9 compatibility layer using Vulkan. Zlib lincese.
|
||||
- **[VK9](https://github.com/disks86/VK9)** - Direct3D 9 compatibility layer using Vulkan. Zlib license.
|
||||
- **[vkDOOM3](https://github.com/DustinHLand/vkDOOM3)** - Vulkan port of GPL DOOM 3 BFG Edition. License: GNU GPL.
|
||||
- **[vkQuake2](https://github.com/kondrak/vkQuake2)** - vanilla Quake 2 with Vulkan support. License: GNU GPL.
|
||||
- **[Vulkan Best Practice for Mobile Developers](https://github.com/ARM-software/vulkan_best_practice_for_mobile_developers)** from ARM. License: MIT.
|
||||
- **[RPCS3](https://github.com/RPCS3/rpcs3)** - PlayStation 3 emulator/debugger. License: GNU GPLv2.
|
||||
- **[PPSSPP](https://github.com/hrydgard/ppsspp)** - Playstation Portable emulator/debugger. License: GNU GPLv2+.
|
||||
- **[Wicked Engine](https://github.com/turanszkij/WickedEngine)** - 3D engine with modern graphics
|
||||
|
||||
[Many other projects on GitHub](https://github.com/search?q=AMD_VULKAN_MEMORY_ALLOCATOR_H&type=Code) and some game development studios that use Vulkan in their games.
|
||||
|
||||
|
@ -180,7 +186,7 @@ See **[Documentation](https://gpuopen-librariesandsdks.github.io/VulkanMemoryAll
|
|||
- **[D3D12 Memory Allocator](https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator)** - equivalent library for Direct3D 12. License: MIT.
|
||||
- **[Awesome Vulkan](https://github.com/vinjn/awesome-vulkan)** - a curated list of awesome Vulkan libraries, debuggers and resources.
|
||||
- **[vcpkg](https://github.com/Microsoft/vcpkg)** dependency manager from Microsoft also offers a port of this library.
|
||||
- **[VulkanMemoryAllocator-Hpp](https://github.com/malte-v/VulkanMemoryAllocator-Hpp)** - C++ binding for this library. License: CC0-1.0.
|
||||
- **[VulkanMemoryAllocator-Hpp](https://github.com/YaaZ/VulkanMemoryAllocator-Hpp)** - C++ binding for this library. License: CC0-1.0.
|
||||
- **[PyVMA](https://github.com/realitix/pyvma)** - Python wrapper for this library. Author: Jean-Sébastien B. (@realitix). License: Apache 2.0.
|
||||
- **[vk-mem](https://github.com/gwihlidal/vk-mem-rs)** - Rust binding for this library. Author: Graham Wihlidal. License: Apache 2.0 or MIT.
|
||||
- **[Haskell bindings](https://hackage.haskell.org/package/VulkanMemoryAllocator)**, **[github](https://github.com/expipiplus1/vulkan/tree/master/VulkanMemoryAllocator)** - Haskell bindings for this library. Author: Ellie Hermaszewska (@expipiplus1). License BSD-3-Clause.
|
||||
|
|
Before Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 268 B |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 22 KiB |
|
@ -1,6 +0,0 @@
|
|||
root = true
|
||||
|
||||
[**.{cpp,h}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
|
@ -1,107 +0,0 @@
|
|||
set(CMAKE_DEBUG_POSTFIX d)
|
||||
set(CMAKE_RELWITHDEBINFO_POSTFIX rd)
|
||||
set(CMAKE_MINSIZEREL_POSTFIX s)
|
||||
|
||||
add_library(VulkanMemoryAllocator
|
||||
VmaUsage.cpp
|
||||
VmaUsage.h
|
||||
${PROJECT_SOURCE_DIR}/include/vk_mem_alloc.h
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
# Provides MSVC users nicer debugging support
|
||||
target_sources(VulkanMemoryAllocator PRIVATE ${CMAKE_CURRENT_LIST_DIR}/vk_mem_alloc.natvis)
|
||||
endif()
|
||||
|
||||
set_target_properties(
|
||||
VulkanMemoryAllocator PROPERTIES
|
||||
|
||||
CXX_EXTENSIONS OFF
|
||||
# Use C++14
|
||||
CXX_STANDARD 14
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
)
|
||||
|
||||
target_include_directories(VulkanMemoryAllocator PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
)
|
||||
|
||||
# Only link to Vulkan if static linking is used
|
||||
if(${VMA_STATIC_VULKAN_FUNCTIONS})
|
||||
target_link_libraries(VulkanMemoryAllocator PUBLIC Vulkan::Vulkan)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(
|
||||
VulkanMemoryAllocator
|
||||
|
||||
PUBLIC
|
||||
VMA_STATIC_VULKAN_FUNCTIONS=$<BOOL:${VMA_STATIC_VULKAN_FUNCTIONS}>
|
||||
VMA_DYNAMIC_VULKAN_FUNCTIONS=$<BOOL:${VMA_DYNAMIC_VULKAN_FUNCTIONS}>
|
||||
VMA_DEBUG_ALWAYS_DEDICATED_MEMORY=$<BOOL:${VMA_DEBUG_ALWAYS_DEDICATED_MEMORY}>
|
||||
VMA_DEBUG_INITIALIZE_ALLOCATIONS=$<BOOL:${VMA_DEBUG_INITIALIZE_ALLOCATIONS}>
|
||||
VMA_DEBUG_GLOBAL_MUTEX=$<BOOL:${VMA_DEBUG_GLOBAL_MUTEX}>
|
||||
VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT=$<BOOL:${VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT}>
|
||||
VMA_RECORDING_ENABLED=$<BOOL:${VMA_RECORDING_ENABLED}>
|
||||
)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/install_target.cmake)
|
||||
|
||||
if(VMA_BUILD_SAMPLE)
|
||||
if(WIN32)
|
||||
set(VMA_SAMPLE_SOURCE_FILES
|
||||
Common.cpp
|
||||
Common.h
|
||||
SparseBindingTest.cpp
|
||||
SparseBindingTest.h
|
||||
Tests.cpp
|
||||
Tests.h
|
||||
VulkanSample.cpp
|
||||
)
|
||||
|
||||
add_executable(VmaSample ${VMA_SAMPLE_SOURCE_FILES})
|
||||
add_dependencies(VmaSample VulkanMemoryAllocator VmaSampleShaders)
|
||||
|
||||
if(MSVC)
|
||||
# Use Unicode instead of multibyte set
|
||||
add_compile_definitions(UNICODE _UNICODE)
|
||||
|
||||
# Add C++ warnings and security checks
|
||||
add_compile_options(/permissive- /sdl /W3)
|
||||
|
||||
# Enable multithreaded compiling
|
||||
target_compile_options(VmaSample PRIVATE "/MP")
|
||||
|
||||
# Set VmaSample as startup project
|
||||
set_property(DIRECTORY "${PROJECT_SOURCE_DIR}" PROPERTY VS_STARTUP_PROJECT "VmaSample")
|
||||
|
||||
# Set working directory for Visual Studio debugger
|
||||
set_target_properties(
|
||||
VmaSample
|
||||
PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/bin"
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(
|
||||
VmaSample PROPERTIES
|
||||
|
||||
CXX_EXTENSIONS OFF
|
||||
# Use C++14
|
||||
CXX_STANDARD 14
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
VmaSample
|
||||
PRIVATE
|
||||
|
||||
VulkanMemoryAllocator
|
||||
Vulkan::Vulkan
|
||||
)
|
||||
else()
|
||||
message(STATUS "VmaSample application is not supported to Linux")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(VMA_BUILD_SAMPLE_SHADERS)
|
||||
add_subdirectory(Shaders)
|
||||
endif()
|
|
@ -1,328 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017-2022 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
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void ReadFile(std::vector<char>& out, const char* fileName)
|
||||
{
|
||||
std::ifstream file(fileName, std::ios::ate | std::ios::binary);
|
||||
assert(file.is_open());
|
||||
size_t fileSize = (size_t)file.tellg();
|
||||
if(fileSize > 0)
|
||||
{
|
||||
out.resize(fileSize);
|
||||
file.seekg(0);
|
||||
file.read(out.data(), fileSize);
|
||||
}
|
||||
else
|
||||
out.clear();
|
||||
}
|
||||
|
||||
void SetConsoleColor(CONSOLE_COLOR color)
|
||||
{
|
||||
WORD attr = 0;
|
||||
switch(color)
|
||||
{
|
||||
case CONSOLE_COLOR::INFO:
|
||||
attr = FOREGROUND_INTENSITY;
|
||||
break;
|
||||
case CONSOLE_COLOR::NORMAL:
|
||||
attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||
break;
|
||||
case CONSOLE_COLOR::WARNING:
|
||||
attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
|
||||
break;
|
||||
case CONSOLE_COLOR::ERROR_:
|
||||
attr = FOREGROUND_RED | FOREGROUND_INTENSITY;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(out, attr);
|
||||
}
|
||||
|
||||
void PrintMessage(CONSOLE_COLOR color, const char* msg)
|
||||
{
|
||||
if(color != CONSOLE_COLOR::NORMAL)
|
||||
SetConsoleColor(color);
|
||||
|
||||
printf("%s\n", msg);
|
||||
|
||||
if (color != CONSOLE_COLOR::NORMAL)
|
||||
SetConsoleColor(CONSOLE_COLOR::NORMAL);
|
||||
}
|
||||
|
||||
void PrintMessage(CONSOLE_COLOR color, const wchar_t* msg)
|
||||
{
|
||||
if(color != CONSOLE_COLOR::NORMAL)
|
||||
SetConsoleColor(color);
|
||||
|
||||
wprintf(L"%s\n", msg);
|
||||
|
||||
if (color != CONSOLE_COLOR::NORMAL)
|
||||
SetConsoleColor(CONSOLE_COLOR::NORMAL);
|
||||
}
|
||||
|
||||
static const size_t CONSOLE_SMALL_BUF_SIZE = 256;
|
||||
|
||||
void PrintMessageV(CONSOLE_COLOR color, const char* format, va_list argList)
|
||||
{
|
||||
size_t dstLen = (size_t)::_vscprintf(format, argList);
|
||||
if(dstLen)
|
||||
{
|
||||
bool useSmallBuf = dstLen < CONSOLE_SMALL_BUF_SIZE;
|
||||
char smallBuf[CONSOLE_SMALL_BUF_SIZE];
|
||||
std::vector<char> bigBuf(useSmallBuf ? 0 : dstLen + 1);
|
||||
char* bufPtr = useSmallBuf ? smallBuf : bigBuf.data();
|
||||
::vsprintf_s(bufPtr, dstLen + 1, format, argList);
|
||||
PrintMessage(color, bufPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintMessageV(CONSOLE_COLOR color, const wchar_t* format, va_list argList)
|
||||
{
|
||||
size_t dstLen = (size_t)::_vcwprintf(format, argList);
|
||||
if(dstLen)
|
||||
{
|
||||
bool useSmallBuf = dstLen < CONSOLE_SMALL_BUF_SIZE;
|
||||
wchar_t smallBuf[CONSOLE_SMALL_BUF_SIZE];
|
||||
std::vector<wchar_t> bigBuf(useSmallBuf ? 0 : dstLen + 1);
|
||||
wchar_t* bufPtr = useSmallBuf ? smallBuf : bigBuf.data();
|
||||
::vswprintf_s(bufPtr, dstLen + 1, format, argList);
|
||||
PrintMessage(color, bufPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintMessageF(CONSOLE_COLOR color, const char* format, ...)
|
||||
{
|
||||
va_list argList;
|
||||
va_start(argList, format);
|
||||
PrintMessageV(color, format, argList);
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
void PrintMessageF(CONSOLE_COLOR color, const wchar_t* format, ...)
|
||||
{
|
||||
va_list argList;
|
||||
va_start(argList, format);
|
||||
PrintMessageV(color, format, argList);
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
void PrintWarningF(const char* format, ...)
|
||||
{
|
||||
va_list argList;
|
||||
va_start(argList, format);
|
||||
PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
void PrintWarningF(const wchar_t* format, ...)
|
||||
{
|
||||
va_list argList;
|
||||
va_start(argList, format);
|
||||
PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
void PrintErrorF(const char* format, ...)
|
||||
{
|
||||
va_list argList;
|
||||
va_start(argList, format);
|
||||
PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
void PrintErrorF(const wchar_t* format, ...)
|
||||
{
|
||||
va_list argList;
|
||||
va_start(argList, format);
|
||||
PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
void SaveFile(const wchar_t* filePath, const void* data, size_t dataSize)
|
||||
{
|
||||
FILE* f = nullptr;
|
||||
_wfopen_s(&f, filePath, L"wb");
|
||||
if(f)
|
||||
{
|
||||
fwrite(data, 1, dataSize, f);
|
||||
fclose(f);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
std::wstring SizeToStr(size_t size)
|
||||
{
|
||||
if(size == 0)
|
||||
return L"0";
|
||||
wchar_t result[32];
|
||||
double size2 = (double)size;
|
||||
if (size2 >= 1024.0*1024.0*1024.0*1024.0)
|
||||
{
|
||||
swprintf_s(result, L"%.2f TB", size2 / (1024.0*1024.0*1024.0*1024.0));
|
||||
}
|
||||
else if (size2 >= 1024.0*1024.0*1024.0)
|
||||
{
|
||||
swprintf_s(result, L"%.2f GB", size2 / (1024.0*1024.0*1024.0));
|
||||
}
|
||||
else if (size2 >= 1024.0*1024.0)
|
||||
{
|
||||
swprintf_s(result, L"%.2f MB", size2 / (1024.0*1024.0));
|
||||
}
|
||||
else if (size2 >= 1024.0)
|
||||
{
|
||||
swprintf_s(result, L"%.2f KB", size2 / 1024.0);
|
||||
}
|
||||
else
|
||||
swprintf_s(result, L"%llu B", size);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ConvertCharsToUnicode(std::wstring *outStr, const std::string &s, unsigned codePage)
|
||||
{
|
||||
if (s.empty())
|
||||
{
|
||||
outStr->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Phase 1 - Get buffer size.
|
||||
const int size = MultiByteToWideChar(codePage, 0, s.data(), (int)s.length(), NULL, 0);
|
||||
if (size == 0)
|
||||
{
|
||||
outStr->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Phase 2 - Do conversion.
|
||||
std::unique_ptr<wchar_t[]> buf(new wchar_t[(size_t)size]);
|
||||
int result = MultiByteToWideChar(codePage, 0, s.data(), (int)s.length(), buf.get(), size);
|
||||
if (result == 0)
|
||||
{
|
||||
outStr->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
outStr->assign(buf.get(), (size_t)size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConvertCharsToUnicode(std::wstring *outStr, const char *s, size_t sCharCount, unsigned codePage)
|
||||
{
|
||||
if (sCharCount == 0)
|
||||
{
|
||||
outStr->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(sCharCount <= (size_t)INT_MAX);
|
||||
|
||||
// Phase 1 - Get buffer size.
|
||||
int size = MultiByteToWideChar(codePage, 0, s, (int)sCharCount, NULL, 0);
|
||||
if (size == 0)
|
||||
{
|
||||
outStr->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Phase 2 - Do conversion.
|
||||
std::unique_ptr<wchar_t[]> buf(new wchar_t[(size_t)size]);
|
||||
int result = MultiByteToWideChar(codePage, 0, s, (int)sCharCount, buf.get(), size);
|
||||
if (result == 0)
|
||||
{
|
||||
outStr->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
outStr->assign(buf.get(), (size_t)size);
|
||||
return true;
|
||||
}
|
||||
|
||||
const wchar_t* PhysicalDeviceTypeToStr(VkPhysicalDeviceType type)
|
||||
{
|
||||
// Skipping common prefix VK_PHYSICAL_DEVICE_TYPE_
|
||||
static const wchar_t* const VALUES[] = {
|
||||
L"OTHER",
|
||||
L"INTEGRATED_GPU",
|
||||
L"DISCRETE_GPU",
|
||||
L"VIRTUAL_GPU",
|
||||
L"CPU",
|
||||
};
|
||||
return (uint32_t)type < _countof(VALUES) ? VALUES[(uint32_t)type] : L"";
|
||||
}
|
||||
|
||||
const wchar_t* VendorIDToStr(uint32_t vendorID)
|
||||
{
|
||||
switch(vendorID)
|
||||
{
|
||||
// Skipping common prefix VK_VENDOR_ID_ for these:
|
||||
case 0x10001: return L"VIV";
|
||||
case 0x10002: return L"VSI";
|
||||
case 0x10003: return L"KAZAN";
|
||||
case 0x10004: return L"CODEPLAY";
|
||||
case 0x10005: return L"MESA";
|
||||
case 0x10006: return L"POCL";
|
||||
// Others...
|
||||
case VENDOR_ID_AMD: return L"AMD";
|
||||
case VENDOR_ID_NVIDIA: return L"NVIDIA";
|
||||
case VENDOR_ID_INTEL: return L"Intel";
|
||||
case 0x1010: return L"ImgTec";
|
||||
case 0x13B5: return L"ARM";
|
||||
case 0x5143: return L"Qualcomm";
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
|
||||
#if VMA_VULKAN_VERSION >= 1002000
|
||||
const wchar_t* DriverIDToStr(VkDriverId driverID)
|
||||
{
|
||||
// Skipping common prefix VK_DRIVER_ID_
|
||||
static const wchar_t* const VALUES[] = {
|
||||
L"",
|
||||
L"AMD_PROPRIETARY",
|
||||
L"AMD_OPEN_SOURCE",
|
||||
L"MESA_RADV",
|
||||
L"NVIDIA_PROPRIETARY",
|
||||
L"INTEL_PROPRIETARY_WINDOWS",
|
||||
L"INTEL_OPEN_SOURCE_MESA",
|
||||
L"IMAGINATION_PROPRIETARY",
|
||||
L"QUALCOMM_PROPRIETARY",
|
||||
L"ARM_PROPRIETARY",
|
||||
L"GOOGLE_SWIFTSHADER",
|
||||
L"GGP_PROPRIETARY",
|
||||
L"BROADCOM_PROPRIETARY",
|
||||
L"MESA_LLVMPIPE",
|
||||
L"MOLTENVK",
|
||||
};
|
||||
return (uint32_t)driverID < _countof(VALUES) ? VALUES[(uint32_t)driverID] : L"";
|
||||
}
|
||||
#endif // #if VMA_VULKAN_VERSION >= 1002000
|
||||
|
||||
|
||||
#endif // #ifdef _WIN32
|
|
@ -1,339 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017-2022 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
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef COMMON_H_
|
||||
#define COMMON_H_
|
||||
|
||||
#include "VmaUsage.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
typedef std::chrono::high_resolution_clock::time_point time_point;
|
||||
typedef std::chrono::high_resolution_clock::duration duration;
|
||||
|
||||
#define STRINGIZE(x) STRINGIZE2(x)
|
||||
#define STRINGIZE2(x) #x
|
||||
#define LINE_STRING STRINGIZE(__LINE__)
|
||||
#define TEST(expr) do { if(!(expr)) { \
|
||||
assert(0 && #expr); \
|
||||
throw std::runtime_error(__FILE__ "(" LINE_STRING "): ( " #expr " ) == false"); \
|
||||
} } while(false)
|
||||
#define ERR_GUARD_VULKAN(expr) do { if((expr) < 0) { \
|
||||
assert(0 && #expr); \
|
||||
throw std::runtime_error(__FILE__ "(" LINE_STRING "): VkResult( " #expr " ) < 0"); \
|
||||
} } while(false)
|
||||
|
||||
static const uint32_t VENDOR_ID_AMD = 0x1002;
|
||||
static const uint32_t VENDOR_ID_NVIDIA = 0x10DE;
|
||||
static const uint32_t VENDOR_ID_INTEL = 0x8086;
|
||||
|
||||
extern VkInstance g_hVulkanInstance;
|
||||
extern VkPhysicalDevice g_hPhysicalDevice;
|
||||
extern VkDevice g_hDevice;
|
||||
extern VkInstance g_hVulkanInstance;
|
||||
extern VmaAllocator g_hAllocator;
|
||||
extern bool VK_AMD_device_coherent_memory_enabled;
|
||||
|
||||
void SetAllocatorCreateInfo(VmaAllocatorCreateInfo& outInfo);
|
||||
|
||||
inline float ToFloatSeconds(duration d)
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::duration<float>>(d).count();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T ceil_div(T x, T y)
|
||||
{
|
||||
return (x+y-1) / y;
|
||||
}
|
||||
template <typename T>
|
||||
inline T round_div(T x, T y)
|
||||
{
|
||||
return (x+y/(T)2) / y;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T align_up(T val, T align)
|
||||
{
|
||||
return (val + align - 1) / align * align;
|
||||
}
|
||||
|
||||
static const float PI = 3.14159265358979323846264338327950288419716939937510582f;
|
||||
|
||||
template<typename MainT, typename NewT>
|
||||
inline void PnextChainPushFront(MainT* mainStruct, NewT* newStruct)
|
||||
{
|
||||
newStruct->pNext = mainStruct->pNext;
|
||||
mainStruct->pNext = newStruct;
|
||||
}
|
||||
template<typename MainT, typename NewT>
|
||||
inline void PnextChainPushBack(MainT* mainStruct, NewT* newStruct)
|
||||
{
|
||||
struct VkAnyStruct
|
||||
{
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
};
|
||||
VkAnyStruct* lastStruct = (VkAnyStruct*)mainStruct;
|
||||
while(lastStruct->pNext != nullptr)
|
||||
{
|
||||
lastStruct = (VkAnyStruct*)lastStruct->pNext;
|
||||
}
|
||||
newStruct->pNext = nullptr;
|
||||
lastStruct->pNext = newStruct;
|
||||
}
|
||||
|
||||
struct vec3
|
||||
{
|
||||
float x, y, z;
|
||||
|
||||
vec3() { }
|
||||
vec3(float x, float y, float z) : x(x), y(y), z(z) { }
|
||||
|
||||
float& operator[](uint32_t index) { return *(&x + index); }
|
||||
const float& operator[](uint32_t index) const { return *(&x + index); }
|
||||
|
||||
vec3 operator+(const vec3& rhs) const { return vec3(x + rhs.x, y + rhs.y, z + rhs.z); }
|
||||
vec3 operator-(const vec3& rhs) const { return vec3(x - rhs.x, y - rhs.y, z - rhs.z); }
|
||||
vec3 operator*(float s) const { return vec3(x * s, y * s, z * s); }
|
||||
|
||||
vec3 Normalized() const
|
||||
{
|
||||
return (*this) * (1.f / sqrt(x * x + y * y + z * z));
|
||||
}
|
||||
};
|
||||
|
||||
inline float Dot(const vec3& lhs, const vec3& rhs)
|
||||
{
|
||||
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
|
||||
}
|
||||
inline vec3 Cross(const vec3& lhs, const vec3& rhs)
|
||||
{
|
||||
return vec3(
|
||||
lhs.y * rhs.z - lhs.z * rhs.y,
|
||||
lhs.z * rhs.x - lhs.x * rhs.z,
|
||||
lhs.x * rhs.y - lhs.y * rhs.x);
|
||||
}
|
||||
|
||||
struct vec4
|
||||
{
|
||||
float x, y, z, w;
|
||||
|
||||
vec4() { }
|
||||
vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { }
|
||||
vec4(const vec3& v, float w) : x(v.x), y(v.y), z(v.z), w(w) { }
|
||||
|
||||
float& operator[](uint32_t index) { return *(&x + index); }
|
||||
const float& operator[](uint32_t index) const { return *(&x + index); }
|
||||
};
|
||||
|
||||
struct mat4
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
float _11, _12, _13, _14;
|
||||
float _21, _22, _23, _24;
|
||||
float _31, _32, _33, _34;
|
||||
float _41, _42, _43, _44;
|
||||
};
|
||||
float m[4][4]; // [row][column]
|
||||
};
|
||||
|
||||
mat4() { }
|
||||
|
||||
mat4(
|
||||
float _11, float _12, float _13, float _14,
|
||||
float _21, float _22, float _23, float _24,
|
||||
float _31, float _32, float _33, float _34,
|
||||
float _41, float _42, float _43, float _44) :
|
||||
_11(_11), _12(_12), _13(_13), _14(_14),
|
||||
_21(_21), _22(_22), _23(_23), _24(_24),
|
||||
_31(_31), _32(_32), _33(_33), _34(_34),
|
||||
_41(_41), _42(_42), _43(_43), _44(_44)
|
||||
{
|
||||
}
|
||||
|
||||
mat4(
|
||||
const vec4& row1,
|
||||
const vec4& row2,
|
||||
const vec4& row3,
|
||||
const vec4& row4) :
|
||||
_11(row1.x), _12(row1.y), _13(row1.z), _14(row1.w),
|
||||
_21(row2.x), _22(row2.y), _23(row2.z), _24(row2.w),
|
||||
_31(row3.x), _32(row3.y), _33(row3.z), _34(row3.w),
|
||||
_41(row4.x), _42(row4.y), _43(row4.z), _44(row4.w)
|
||||
{
|
||||
}
|
||||
|
||||
mat4 operator*(const mat4 &rhs) const
|
||||
{
|
||||
return mat4(
|
||||
_11 * rhs._11 + _12 * rhs._21 + _13 * rhs._31 + _14 * rhs._41,
|
||||
_11 * rhs._12 + _12 * rhs._22 + _13 * rhs._32 + _14 * rhs._42,
|
||||
_11 * rhs._13 + _12 * rhs._23 + _13 * rhs._33 + _14 * rhs._43,
|
||||
_11 * rhs._14 + _12 * rhs._24 + _13 * rhs._34 + _14 * rhs._44,
|
||||
|
||||
_21 * rhs._11 + _22 * rhs._21 + _23 * rhs._31 + _24 * rhs._41,
|
||||
_21 * rhs._12 + _22 * rhs._22 + _23 * rhs._32 + _24 * rhs._42,
|
||||
_21 * rhs._13 + _22 * rhs._23 + _23 * rhs._33 + _24 * rhs._43,
|
||||
_21 * rhs._14 + _22 * rhs._24 + _23 * rhs._34 + _24 * rhs._44,
|
||||
|
||||
_31 * rhs._11 + _32 * rhs._21 + _33 * rhs._31 + _34 * rhs._41,
|
||||
_31 * rhs._12 + _32 * rhs._22 + _33 * rhs._32 + _34 * rhs._42,
|
||||
_31 * rhs._13 + _32 * rhs._23 + _33 * rhs._33 + _34 * rhs._43,
|
||||
_31 * rhs._14 + _32 * rhs._24 + _33 * rhs._34 + _34 * rhs._44,
|
||||
|
||||
_41 * rhs._11 + _42 * rhs._21 + _43 * rhs._31 + _44 * rhs._41,
|
||||
_41 * rhs._12 + _42 * rhs._22 + _43 * rhs._32 + _44 * rhs._42,
|
||||
_41 * rhs._13 + _42 * rhs._23 + _43 * rhs._33 + _44 * rhs._43,
|
||||
_41 * rhs._14 + _42 * rhs._24 + _43 * rhs._34 + _44 * rhs._44);
|
||||
}
|
||||
|
||||
static mat4 RotationY(float angle)
|
||||
{
|
||||
const float s = sin(angle), c = cos(angle);
|
||||
return mat4(
|
||||
c, 0.f, -s, 0.f,
|
||||
0.f, 1.f, 0.f, 0.f,
|
||||
s, 0.f, c, 0.f,
|
||||
0.f, 0.f, 0.f, 1.f);
|
||||
}
|
||||
|
||||
static mat4 Perspective(float fovY, float aspectRatio, float zNear, float zFar)
|
||||
{
|
||||
float yScale = 1.0f / tan(fovY * 0.5f);
|
||||
float xScale = yScale / aspectRatio;
|
||||
return mat4(
|
||||
xScale, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, yScale, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, zFar / (zFar - zNear), 1.0f,
|
||||
0.0f, 0.0f, -zNear * zFar / (zFar - zNear), 0.0f);
|
||||
}
|
||||
|
||||
static mat4 LookAt(vec3 at, vec3 eye, vec3 up)
|
||||
{
|
||||
vec3 zAxis = (at - eye).Normalized();
|
||||
vec3 xAxis = Cross(up, zAxis).Normalized();
|
||||
vec3 yAxis = Cross(zAxis, xAxis);
|
||||
return mat4(
|
||||
xAxis.x, yAxis.x, zAxis.x, 0.0f,
|
||||
xAxis.y, yAxis.y, zAxis.y, 0.0f,
|
||||
xAxis.z, yAxis.z, zAxis.z, 0.0f,
|
||||
-Dot(xAxis, eye), -Dot(yAxis, eye), -Dot(zAxis, eye), 1.0f);
|
||||
}
|
||||
};
|
||||
|
||||
class RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
RandomNumberGenerator() : m_Value{GetTickCount()} {}
|
||||
RandomNumberGenerator(uint32_t seed) : m_Value{seed} { }
|
||||
void Seed(uint32_t seed) { m_Value = seed; }
|
||||
uint32_t Generate() { return GenerateFast() ^ (GenerateFast() >> 7); }
|
||||
|
||||
private:
|
||||
uint32_t m_Value;
|
||||
uint32_t GenerateFast() { return m_Value = (m_Value * 196314165 + 907633515); }
|
||||
};
|
||||
|
||||
// Wrapper for RandomNumberGenerator compatible with STL "UniformRandomNumberGenerator" idea.
|
||||
struct MyUniformRandomNumberGenerator
|
||||
{
|
||||
typedef uint32_t result_type;
|
||||
MyUniformRandomNumberGenerator(RandomNumberGenerator& gen) : m_Gen(gen) { }
|
||||
static uint32_t min() { return 0; }
|
||||
static uint32_t max() { return UINT32_MAX; }
|
||||
uint32_t operator()() { return m_Gen.Generate(); }
|
||||
|
||||
private:
|
||||
RandomNumberGenerator& m_Gen;
|
||||
};
|
||||
|
||||
void ReadFile(std::vector<char>& out, const char* fileName);
|
||||
|
||||
enum class CONSOLE_COLOR
|
||||
{
|
||||
INFO,
|
||||
NORMAL,
|
||||
WARNING,
|
||||
ERROR_,
|
||||
COUNT
|
||||
};
|
||||
|
||||
void SetConsoleColor(CONSOLE_COLOR color);
|
||||
|
||||
void PrintMessage(CONSOLE_COLOR color, const char* msg);
|
||||
void PrintMessage(CONSOLE_COLOR color, const wchar_t* msg);
|
||||
|
||||
inline void Print(const char* msg) { PrintMessage(CONSOLE_COLOR::NORMAL, msg); }
|
||||
inline void Print(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::NORMAL, msg); }
|
||||
inline void PrintWarning(const char* msg) { PrintMessage(CONSOLE_COLOR::WARNING, msg); }
|
||||
inline void PrintWarning(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::WARNING, msg); }
|
||||
inline void PrintError(const char* msg) { PrintMessage(CONSOLE_COLOR::ERROR_, msg); }
|
||||
inline void PrintError(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::ERROR_, msg); }
|
||||
|
||||
void PrintMessageV(CONSOLE_COLOR color, const char* format, va_list argList);
|
||||
void PrintMessageV(CONSOLE_COLOR color, const wchar_t* format, va_list argList);
|
||||
void PrintMessageF(CONSOLE_COLOR color, const char* format, ...);
|
||||
void PrintMessageF(CONSOLE_COLOR color, const wchar_t* format, ...);
|
||||
void PrintWarningF(const char* format, ...);
|
||||
void PrintWarningF(const wchar_t* format, ...);
|
||||
void PrintErrorF(const char* format, ...);
|
||||
void PrintErrorF(const wchar_t* format, ...);
|
||||
|
||||
void SaveFile(const wchar_t* filePath, const void* data, size_t dataSize);
|
||||
|
||||
std::wstring SizeToStr(size_t size);
|
||||
// As codePage use e.g. CP_ACP for native Windows 1-byte codepage or CP_UTF8.
|
||||
bool ConvertCharsToUnicode(std::wstring *outStr, const std::string &s, unsigned codePage);
|
||||
bool ConvertCharsToUnicode(std::wstring *outStr, const char *s, size_t sCharCount, unsigned codePage);
|
||||
|
||||
const wchar_t* PhysicalDeviceTypeToStr(VkPhysicalDeviceType type);
|
||||
const wchar_t* VendorIDToStr(uint32_t vendorID);
|
||||
|
||||
#if VMA_VULKAN_VERSION >= 1002000
|
||||
const wchar_t* DriverIDToStr(VkDriverId driverID);
|
||||
#endif
|
||||
|
||||
#endif // #ifdef _WIN32
|
||||
|
||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||
# This file will only be executed if VMA_BUILD_SAMPLE_SHADERS is set to ON
|
||||
|
||||
find_program(GLSL_VALIDATOR glslangValidator REQUIRED)
|
||||
|
||||
if(NOT GLSL_VALIDATOR)
|
||||
message(FATAL_ERROR "glslangValidator not found!")
|
||||
endif()
|
||||
|
||||
set(SHADERS
|
||||
Shader.vert
|
||||
Shader.frag
|
||||
SparseBindingTest.comp
|
||||
)
|
||||
|
||||
# Compile each shader using glslangValidator
|
||||
foreach(SHADER ${SHADERS})
|
||||
get_filename_component(FILE_NAME ${SHADER} NAME)
|
||||
|
||||
# Put the .spv files into the bin folder
|
||||
set(SPIRV ${PROJECT_SOURCE_DIR}/bin/${FILE_NAME}.spv)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${SPIRV}
|
||||
# Use the same file name and append .spv to the compiled shader
|
||||
COMMAND ${GLSL_VALIDATOR} -V ${CMAKE_CURRENT_SOURCE_DIR}/${SHADER} -o ${SPIRV}
|
||||
DEPENDS ${SHADER}
|
||||
)
|
||||
|
||||
list(APPEND SPIRV_FILES ${SPIRV})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(VmaSampleShaders ALL DEPENDS ${SPIRV_FILES})
|
|
@ -1,4 +0,0 @@
|
|||
%VULKAN_SDK%/Bin32/glslangValidator.exe -V -o ../../bin/Shader.vert.spv Shader.vert
|
||||
%VULKAN_SDK%/Bin32/glslangValidator.exe -V -o ../../bin/Shader.frag.spv Shader.frag
|
||||
%VULKAN_SDK%/Bin32/glslangValidator.exe -V -o ../../bin/SparseBindingTest.comp.spv SparseBindingTest.comp
|
||||
pause
|
|
@ -1,37 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017-2022 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
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(location = 0) in vec3 inColor;
|
||||
layout(location = 1) in vec2 inTexCoord;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
layout(binding = 1) uniform sampler2D texSampler;
|
||||
|
||||
void main()
|
||||
{
|
||||
outColor = texture(texSampler, inTexCoord);
|
||||
outColor.rgb *= inColor;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017-2022 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
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(push_constant) uniform UniformBufferObject
|
||||
{
|
||||
mat4 ModelViewProj;
|
||||
} ubo;
|
||||
|
||||
layout(location = 0) in vec3 inPosition;
|
||||
layout(location = 1) in vec3 inColor;
|
||||
layout(location = 2) in vec2 inTexCoord;
|
||||
|
||||
layout(location = 0) out vec3 outColor;
|
||||
layout(location = 1) out vec2 outTexCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = ubo.ModelViewProj * vec4(inPosition, 1.0);
|
||||
outColor = inColor;
|
||||
outTexCoord = inTexCoord;
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2018-2022 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
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
|
||||
|
||||
layout(binding=0) uniform sampler2D img;
|
||||
layout(binding=1) buffer buf
|
||||
{
|
||||
uint bufValues[];
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 xy = ivec2(bufValues[gl_GlobalInvocationID.x * 3],
|
||||
bufValues[gl_GlobalInvocationID.x * 3 + 1]);
|
||||
vec4 color = texture(img, xy);
|
||||
bufValues[gl_GlobalInvocationID.x * 3 + 2] =
|
||||
uint(color.r * 255.0) << 24 |
|
||||
uint(color.g * 255.0) << 16 |
|
||||
uint(color.b * 255.0) << 8 |
|
||||
uint(color.a * 255.0);
|
||||
}
|
|
@ -1,597 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017-2022 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
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#include "Common.h"
|
||||
#include "SparseBindingTest.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// External imports
|
||||
|
||||
extern VkDevice g_hDevice;
|
||||
extern VmaAllocator g_hAllocator;
|
||||
extern uint32_t g_FrameIndex;
|
||||
extern bool g_SparseBindingEnabled;
|
||||
extern VkQueue g_hSparseBindingQueue;
|
||||
extern VkFence g_ImmediateFence;
|
||||
extern VkCommandBuffer g_hTemporaryCommandBuffer;
|
||||
|
||||
void BeginSingleTimeCommands();
|
||||
void EndSingleTimeCommands();
|
||||
void SaveAllocatorStatsToFile(const wchar_t* filePath, bool detailed = true);
|
||||
void LoadShader(std::vector<char>& out, const char* fileName);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Class definitions
|
||||
|
||||
static uint32_t CalculateMipMapCount(uint32_t width, uint32_t height, uint32_t depth)
|
||||
{
|
||||
uint32_t mipMapCount = 1;
|
||||
while(width > 1 || height > 1 || depth > 1)
|
||||
{
|
||||
++mipMapCount;
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
depth /= 2;
|
||||
}
|
||||
return mipMapCount;
|
||||
}
|
||||
|
||||
class BaseImage
|
||||
{
|
||||
public:
|
||||
virtual void Init(RandomNumberGenerator& rand) = 0;
|
||||
virtual ~BaseImage();
|
||||
|
||||
const VkImageCreateInfo& GetCreateInfo() const { return m_CreateInfo; }
|
||||
|
||||
void TestContent(RandomNumberGenerator& rand);
|
||||
|
||||
protected:
|
||||
VkImageCreateInfo m_CreateInfo = {};
|
||||
VkImage m_Image = VK_NULL_HANDLE;
|
||||
|
||||
void FillImageCreateInfo(RandomNumberGenerator& rand);
|
||||
void UploadContent();
|
||||
void ValidateContent(RandomNumberGenerator& rand);
|
||||
};
|
||||
|
||||
class TraditionalImage : public BaseImage
|
||||
{
|
||||
public:
|
||||
virtual void Init(RandomNumberGenerator& rand);
|
||||
virtual ~TraditionalImage();
|
||||
|
||||
private:
|
||||
VmaAllocation m_Allocation = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
class SparseBindingImage : public BaseImage
|
||||
{
|
||||
public:
|
||||
virtual void Init(RandomNumberGenerator& rand);
|
||||
virtual ~SparseBindingImage();
|
||||
|
||||
private:
|
||||
std::vector<VmaAllocation> m_Allocations;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class BaseImage
|
||||
|
||||
BaseImage::~BaseImage()
|
||||
{
|
||||
if(m_Image)
|
||||
{
|
||||
vkDestroyImage(g_hDevice, m_Image, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseImage::TestContent(RandomNumberGenerator& rand)
|
||||
{
|
||||
printf("Validating content of %u x %u texture...\n",
|
||||
m_CreateInfo.extent.width, m_CreateInfo.extent.height);
|
||||
UploadContent();
|
||||
ValidateContent(rand);
|
||||
}
|
||||
|
||||
void BaseImage::FillImageCreateInfo(RandomNumberGenerator& rand)
|
||||
{
|
||||
constexpr uint32_t imageSizeMin = 8;
|
||||
constexpr uint32_t imageSizeMax = 2048;
|
||||
|
||||
const bool useMipMaps = rand.Generate() % 2 != 0;
|
||||
|
||||
ZeroMemory(&m_CreateInfo, sizeof(m_CreateInfo));
|
||||
m_CreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
m_CreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
m_CreateInfo.extent.width = rand.Generate() % (imageSizeMax - imageSizeMin) + imageSizeMin;
|
||||
m_CreateInfo.extent.height = rand.Generate() % (imageSizeMax - imageSizeMin) + imageSizeMin;
|
||||
m_CreateInfo.extent.depth = 1;
|
||||
m_CreateInfo.mipLevels = useMipMaps ?
|
||||
CalculateMipMapCount(m_CreateInfo.extent.width, m_CreateInfo.extent.height, m_CreateInfo.extent.depth) : 1;
|
||||
m_CreateInfo.arrayLayers = 1;
|
||||
m_CreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
m_CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
m_CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
m_CreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
m_CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
m_CreateInfo.flags = 0;
|
||||
}
|
||||
|
||||
void BaseImage::UploadContent()
|
||||
{
|
||||
VkBufferCreateInfo srcBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
srcBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
srcBufCreateInfo.size = 4 * m_CreateInfo.extent.width * m_CreateInfo.extent.height;
|
||||
|
||||
VmaAllocationCreateInfo srcBufAllocCreateInfo = {};
|
||||
srcBufAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||
srcBufAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||
|
||||
VkBuffer srcBuf = nullptr;
|
||||
VmaAllocation srcBufAlloc = nullptr;
|
||||
VmaAllocationInfo srcAllocInfo = {};
|
||||
TEST( vmaCreateBuffer(g_hAllocator, &srcBufCreateInfo, &srcBufAllocCreateInfo, &srcBuf, &srcBufAlloc, &srcAllocInfo) == VK_SUCCESS );
|
||||
|
||||
// Fill texels with: r = x % 255, g = u % 255, b = 13, a = 25
|
||||
uint32_t* srcBufPtr = (uint32_t*)srcAllocInfo.pMappedData;
|
||||
for(uint32_t y = 0, sizeY = m_CreateInfo.extent.height; y < sizeY; ++y)
|
||||
{
|
||||
for(uint32_t x = 0, sizeX = m_CreateInfo.extent.width; x < sizeX; ++x, ++srcBufPtr)
|
||||
{
|
||||
const uint8_t r = (uint8_t)x;
|
||||
const uint8_t g = (uint8_t)y;
|
||||
const uint8_t b = 13;
|
||||
const uint8_t a = 25;
|
||||
*srcBufPtr = (uint32_t)r << 24 | (uint32_t)g << 16 |
|
||||
(uint32_t)b << 8 | (uint32_t)a;
|
||||
}
|
||||
}
|
||||
|
||||
BeginSingleTimeCommands();
|
||||
|
||||
// Barrier undefined to transfer dst.
|
||||
{
|
||||
VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
barrier.srcAccessMask = 0;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = m_Image;
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barrier.subresourceRange.baseArrayLayer = 0;
|
||||
barrier.subresourceRange.baseMipLevel = 0;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
barrier.subresourceRange.levelCount = 1;
|
||||
|
||||
vkCmdPipelineBarrier(g_hTemporaryCommandBuffer,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // srcStageMask
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, // dstStageMask
|
||||
0, // dependencyFlags
|
||||
0, nullptr, // memoryBarriers
|
||||
0, nullptr, // bufferMemoryBarriers
|
||||
1, &barrier); // imageMemoryBarriers
|
||||
}
|
||||
|
||||
// CopyBufferToImage
|
||||
{
|
||||
VkBufferImageCopy region = {};
|
||||
region.bufferOffset = 0;
|
||||
region.bufferRowLength = 0; // Zeros mean tightly packed.
|
||||
region.bufferImageHeight = 0; // Zeros mean tightly packed.
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.mipLevel = 0;
|
||||
region.imageSubresource.baseArrayLayer = 0;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageOffset = { 0, 0, 0 };
|
||||
region.imageExtent = m_CreateInfo.extent;
|
||||
vkCmdCopyBufferToImage(g_hTemporaryCommandBuffer, srcBuf, m_Image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
}
|
||||
|
||||
// Barrier transfer dst to fragment shader read only.
|
||||
{
|
||||
VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = m_Image;
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barrier.subresourceRange.baseArrayLayer = 0;
|
||||
barrier.subresourceRange.baseMipLevel = 0;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
barrier.subresourceRange.levelCount = 1;
|
||||
|
||||
vkCmdPipelineBarrier(g_hTemporaryCommandBuffer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // dstStageMask
|
||||
0, // dependencyFlags
|
||||
0, nullptr, // memoryBarriers
|
||||
0, nullptr, // bufferMemoryBarriers
|
||||
1, &barrier); // imageMemoryBarriers
|
||||
}
|
||||
|
||||
EndSingleTimeCommands();
|
||||
|
||||
vmaDestroyBuffer(g_hAllocator, srcBuf, srcBufAlloc);
|
||||
}
|
||||
|
||||
void BaseImage::ValidateContent(RandomNumberGenerator& rand)
|
||||
{
|
||||
/*
|
||||
dstBuf has following layout:
|
||||
For each of texels to be sampled, [0..valueCount):
|
||||
struct {
|
||||
in uint32_t pixelX;
|
||||
in uint32_t pixelY;
|
||||
out uint32_t pixelColor;
|
||||
}
|
||||
*/
|
||||
|
||||
const uint32_t valueCount = 128;
|
||||
|
||||
VkBufferCreateInfo dstBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
dstBufCreateInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
dstBufCreateInfo.size = valueCount * sizeof(uint32_t) * 3;
|
||||
|
||||
VmaAllocationCreateInfo dstBufAllocCreateInfo = {};
|
||||
dstBufAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||
dstBufAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||
|
||||
VkBuffer dstBuf = nullptr;
|
||||
VmaAllocation dstBufAlloc = nullptr;
|
||||
VmaAllocationInfo dstBufAllocInfo = {};
|
||||
TEST( vmaCreateBuffer(g_hAllocator, &dstBufCreateInfo, &dstBufAllocCreateInfo, &dstBuf, &dstBufAlloc, &dstBufAllocInfo) == VK_SUCCESS );
|
||||
|
||||
// Fill dstBuf input data.
|
||||
{
|
||||
uint32_t* dstBufContent = (uint32_t*)dstBufAllocInfo.pMappedData;
|
||||
for(uint32_t i = 0; i < valueCount; ++i)
|
||||
{
|
||||
const uint32_t x = rand.Generate() % m_CreateInfo.extent.width;
|
||||
const uint32_t y = rand.Generate() % m_CreateInfo.extent.height;
|
||||
dstBufContent[i * 3 ] = x;
|
||||
dstBufContent[i * 3 + 1] = y;
|
||||
dstBufContent[i * 3 + 2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VkSamplerCreateInfo samplerCreateInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
|
||||
samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
|
||||
samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
|
||||
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerCreateInfo.unnormalizedCoordinates = VK_TRUE;
|
||||
|
||||
VkSampler sampler = nullptr;
|
||||
TEST( vkCreateSampler( g_hDevice, &samplerCreateInfo, nullptr, &sampler) == VK_SUCCESS );
|
||||
|
||||
VkDescriptorSetLayoutBinding bindings[2] = {};
|
||||
bindings[0].binding = 0;
|
||||
bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[0].descriptorCount = 1;
|
||||
bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
bindings[0].pImmutableSamplers = &sampler;
|
||||
bindings[1].binding = 1;
|
||||
bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[1].descriptorCount = 1;
|
||||
bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo descSetLayoutCreateInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||
descSetLayoutCreateInfo.bindingCount = 2;
|
||||
descSetLayoutCreateInfo.pBindings = bindings;
|
||||
|
||||
VkDescriptorSetLayout descSetLayout = nullptr;
|
||||
TEST( vkCreateDescriptorSetLayout(g_hDevice, &descSetLayoutCreateInfo, nullptr, &descSetLayout) == VK_SUCCESS );
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
pipelineLayoutCreateInfo.setLayoutCount = 1;
|
||||
pipelineLayoutCreateInfo.pSetLayouts = &descSetLayout;
|
||||
|
||||
VkPipelineLayout pipelineLayout = nullptr;
|
||||
TEST( vkCreatePipelineLayout(g_hDevice, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout) == VK_SUCCESS );
|
||||
|
||||
std::vector<char> shaderCode;
|
||||
LoadShader(shaderCode, "SparseBindingTest.comp.spv");
|
||||
|
||||
VkShaderModuleCreateInfo shaderModuleCreateInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
|
||||
shaderModuleCreateInfo.codeSize = shaderCode.size();
|
||||
shaderModuleCreateInfo.pCode = (const uint32_t*)shaderCode.data();
|
||||
|
||||
VkShaderModule shaderModule = nullptr;
|
||||
TEST( vkCreateShaderModule(g_hDevice, &shaderModuleCreateInfo, nullptr, &shaderModule) == VK_SUCCESS );
|
||||
|
||||
VkComputePipelineCreateInfo pipelineCreateInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
|
||||
pipelineCreateInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
pipelineCreateInfo.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
pipelineCreateInfo.stage.module = shaderModule;
|
||||
pipelineCreateInfo.stage.pName = "main";
|
||||
pipelineCreateInfo.layout = pipelineLayout;
|
||||
|
||||
VkPipeline pipeline = nullptr;
|
||||
TEST( vkCreateComputePipelines(g_hDevice, nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline) == VK_SUCCESS );
|
||||
|
||||
VkDescriptorPoolSize poolSizes[2] = {};
|
||||
poolSizes[0].type = bindings[0].descriptorType;
|
||||
poolSizes[0].descriptorCount = bindings[0].descriptorCount;
|
||||
poolSizes[1].type = bindings[1].descriptorType;
|
||||
poolSizes[1].descriptorCount = bindings[1].descriptorCount;
|
||||
|
||||
VkDescriptorPoolCreateInfo descPoolCreateInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||
descPoolCreateInfo.maxSets = 1;
|
||||
descPoolCreateInfo.poolSizeCount = 2;
|
||||
descPoolCreateInfo.pPoolSizes = poolSizes;
|
||||
|
||||
VkDescriptorPool descPool = nullptr;
|
||||
TEST( vkCreateDescriptorPool(g_hDevice, &descPoolCreateInfo, nullptr, &descPool) == VK_SUCCESS );
|
||||
|
||||
VkDescriptorSetAllocateInfo descSetAllocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
|
||||
descSetAllocInfo.descriptorPool = descPool;
|
||||
descSetAllocInfo.descriptorSetCount = 1;
|
||||
descSetAllocInfo.pSetLayouts = &descSetLayout;
|
||||
|
||||
VkDescriptorSet descSet = nullptr;
|
||||
TEST( vkAllocateDescriptorSets(g_hDevice, &descSetAllocInfo, &descSet) == VK_SUCCESS );
|
||||
|
||||
VkImageViewCreateInfo imageViewCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
imageViewCreateInfo.image = m_Image;
|
||||
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
imageViewCreateInfo.format = m_CreateInfo.format;
|
||||
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageViewCreateInfo.subresourceRange.layerCount = 1;
|
||||
imageViewCreateInfo.subresourceRange.levelCount = 1;
|
||||
|
||||
VkImageView imageView = nullptr;
|
||||
TEST( vkCreateImageView(g_hDevice, &imageViewCreateInfo, nullptr, &imageView) == VK_SUCCESS );
|
||||
|
||||
VkDescriptorImageInfo descImageInfo = {};
|
||||
descImageInfo.imageView = imageView;
|
||||
descImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
VkDescriptorBufferInfo descBufferInfo = {};
|
||||
descBufferInfo.buffer = dstBuf;
|
||||
descBufferInfo.offset = 0;
|
||||
descBufferInfo.range = VK_WHOLE_SIZE;
|
||||
|
||||
VkWriteDescriptorSet descWrites[2] = {};
|
||||
descWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descWrites[0].dstSet = descSet;
|
||||
descWrites[0].dstBinding = bindings[0].binding;
|
||||
descWrites[0].dstArrayElement = 0;
|
||||
descWrites[0].descriptorCount = 1;
|
||||
descWrites[0].descriptorType = bindings[0].descriptorType;
|
||||
descWrites[0].pImageInfo = &descImageInfo;
|
||||
descWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descWrites[1].dstSet = descSet;
|
||||
descWrites[1].dstBinding = bindings[1].binding;
|
||||
descWrites[1].dstArrayElement = 0;
|
||||
descWrites[1].descriptorCount = 1;
|
||||
descWrites[1].descriptorType = bindings[1].descriptorType;
|
||||
descWrites[1].pBufferInfo = &descBufferInfo;
|
||||
vkUpdateDescriptorSets(g_hDevice, 2, descWrites, 0, nullptr);
|
||||
|
||||
BeginSingleTimeCommands();
|
||||
vkCmdBindPipeline(g_hTemporaryCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
|
||||
vkCmdBindDescriptorSets(g_hTemporaryCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 1, &descSet, 0, nullptr);
|
||||
vkCmdDispatch(g_hTemporaryCommandBuffer, valueCount, 1, 1);
|
||||
EndSingleTimeCommands();
|
||||
|
||||
// Validate dstBuf output data.
|
||||
{
|
||||
const uint32_t* dstBufContent = (const uint32_t*)dstBufAllocInfo.pMappedData;
|
||||
for(uint32_t i = 0; i < valueCount; ++i)
|
||||
{
|
||||
const uint32_t x = dstBufContent[i * 3 ];
|
||||
const uint32_t y = dstBufContent[i * 3 + 1];
|
||||
const uint32_t color = dstBufContent[i * 3 + 2];
|
||||
const uint8_t a = (uint8_t)(color >> 24);
|
||||
const uint8_t b = (uint8_t)(color >> 16);
|
||||
const uint8_t g = (uint8_t)(color >> 8);
|
||||
const uint8_t r = (uint8_t)color;
|
||||
TEST(r == (uint8_t)x && g == (uint8_t)y && b == 13 && a == 25);
|
||||
}
|
||||
}
|
||||
|
||||
vkDestroyImageView(g_hDevice, imageView, nullptr);
|
||||
vkDestroyDescriptorPool(g_hDevice, descPool, nullptr);
|
||||
vmaDestroyBuffer(g_hAllocator, dstBuf, dstBufAlloc);
|
||||
vkDestroyPipeline(g_hDevice, pipeline, nullptr);
|
||||
vkDestroyShaderModule(g_hDevice, shaderModule, nullptr);
|
||||
vkDestroyPipelineLayout(g_hDevice, pipelineLayout, nullptr);
|
||||
vkDestroyDescriptorSetLayout(g_hDevice, descSetLayout, nullptr);
|
||||
vkDestroySampler(g_hDevice, sampler, nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class TraditionalImage
|
||||
|
||||
void TraditionalImage::Init(RandomNumberGenerator& rand)
|
||||
{
|
||||
FillImageCreateInfo(rand);
|
||||
|
||||
VmaAllocationCreateInfo allocCreateInfo = {};
|
||||
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||
// Default BEST_FIT is clearly better.
|
||||
//allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT;
|
||||
|
||||
ERR_GUARD_VULKAN( vmaCreateImage(g_hAllocator, &m_CreateInfo, &allocCreateInfo,
|
||||
&m_Image, &m_Allocation, nullptr) );
|
||||
}
|
||||
|
||||
TraditionalImage::~TraditionalImage()
|
||||
{
|
||||
if(m_Allocation)
|
||||
{
|
||||
vmaFreeMemory(g_hAllocator, m_Allocation);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class SparseBindingImage
|
||||
|
||||
void SparseBindingImage::Init(RandomNumberGenerator& rand)
|
||||
{
|
||||
assert(g_SparseBindingEnabled && g_hSparseBindingQueue);
|
||||
|
||||
// Create image.
|
||||
FillImageCreateInfo(rand);
|
||||
m_CreateInfo.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
|
||||
ERR_GUARD_VULKAN( vkCreateImage(g_hDevice, &m_CreateInfo, nullptr, &m_Image) );
|
||||
|
||||
// Get memory requirements.
|
||||
VkMemoryRequirements imageMemReq;
|
||||
vkGetImageMemoryRequirements(g_hDevice, m_Image, &imageMemReq);
|
||||
|
||||
// This is just to silence validation layer warning.
|
||||
// But it doesn't help. Looks like a bug in Vulkan validation layers.
|
||||
// See: https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/364
|
||||
uint32_t sparseMemReqCount = 0;
|
||||
vkGetImageSparseMemoryRequirements(g_hDevice, m_Image, &sparseMemReqCount, nullptr);
|
||||
TEST(sparseMemReqCount <= 8);
|
||||
VkSparseImageMemoryRequirements sparseMemReq[8];
|
||||
vkGetImageSparseMemoryRequirements(g_hDevice, m_Image, &sparseMemReqCount, sparseMemReq);
|
||||
|
||||
// According to Vulkan specification, for sparse resources memReq.alignment is also page size.
|
||||
const VkDeviceSize pageSize = imageMemReq.alignment;
|
||||
const uint32_t pageCount = (uint32_t)ceil_div<VkDeviceSize>(imageMemReq.size, pageSize);
|
||||
|
||||
VmaAllocationCreateInfo allocCreateInfo = {};
|
||||
allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
|
||||
VkMemoryRequirements pageMemReq = imageMemReq;
|
||||
pageMemReq.size = pageSize;
|
||||
|
||||
// Allocate and bind memory pages.
|
||||
m_Allocations.resize(pageCount);
|
||||
std::fill(m_Allocations.begin(), m_Allocations.end(), nullptr);
|
||||
std::vector<VkSparseMemoryBind> binds{pageCount};
|
||||
std::vector<VmaAllocationInfo> allocInfo{pageCount};
|
||||
ERR_GUARD_VULKAN( vmaAllocateMemoryPages(g_hAllocator, &pageMemReq, &allocCreateInfo, pageCount, m_Allocations.data(), allocInfo.data()) );
|
||||
|
||||
for(uint32_t i = 0; i < pageCount; ++i)
|
||||
{
|
||||
binds[i] = {};
|
||||
binds[i].resourceOffset = pageSize * i;
|
||||
binds[i].size = pageSize;
|
||||
binds[i].memory = allocInfo[i].deviceMemory;
|
||||
binds[i].memoryOffset = allocInfo[i].offset;
|
||||
}
|
||||
|
||||
VkSparseImageOpaqueMemoryBindInfo imageBindInfo;
|
||||
imageBindInfo.image = m_Image;
|
||||
imageBindInfo.bindCount = pageCount;
|
||||
imageBindInfo.pBinds = binds.data();
|
||||
|
||||
VkBindSparseInfo bindSparseInfo = { VK_STRUCTURE_TYPE_BIND_SPARSE_INFO };
|
||||
bindSparseInfo.pImageOpaqueBinds = &imageBindInfo;
|
||||
bindSparseInfo.imageOpaqueBindCount = 1;
|
||||
|
||||
ERR_GUARD_VULKAN( vkResetFences(g_hDevice, 1, &g_ImmediateFence) );
|
||||
ERR_GUARD_VULKAN( vkQueueBindSparse(g_hSparseBindingQueue, 1, &bindSparseInfo, g_ImmediateFence) );
|
||||
ERR_GUARD_VULKAN( vkWaitForFences(g_hDevice, 1, &g_ImmediateFence, VK_TRUE, UINT64_MAX) );
|
||||
}
|
||||
|
||||
SparseBindingImage::~SparseBindingImage()
|
||||
{
|
||||
vmaFreeMemoryPages(g_hAllocator, m_Allocations.size(), m_Allocations.data());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Private functions
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Public functions
|
||||
|
||||
void TestSparseBinding()
|
||||
{
|
||||
wprintf(L"TESTING SPARSE BINDING:\n");
|
||||
|
||||
struct ImageInfo
|
||||
{
|
||||
std::unique_ptr<BaseImage> image;
|
||||
uint32_t endFrame;
|
||||
};
|
||||
std::vector<ImageInfo> images;
|
||||
|
||||
constexpr uint32_t frameCount = 1000;
|
||||
constexpr uint32_t imageLifeFramesMin = 1;
|
||||
constexpr uint32_t imageLifeFramesMax = 400;
|
||||
|
||||
RandomNumberGenerator rand(4652467);
|
||||
|
||||
for(uint32_t frameIndex = 0; frameIndex < frameCount; ++frameIndex)
|
||||
{
|
||||
// Bump frame index.
|
||||
++g_FrameIndex;
|
||||
vmaSetCurrentFrameIndex(g_hAllocator, g_FrameIndex);
|
||||
|
||||
// Create one new, random image.
|
||||
ImageInfo imageInfo;
|
||||
//imageInfo.image = std::make_unique<TraditionalImage>();
|
||||
imageInfo.image = std::make_unique<SparseBindingImage>();
|
||||
imageInfo.image->Init(rand);
|
||||
imageInfo.endFrame = g_FrameIndex + rand.Generate() % (imageLifeFramesMax - imageLifeFramesMin) + imageLifeFramesMin;
|
||||
images.push_back(std::move(imageInfo));
|
||||
|
||||
// Delete all images that expired.
|
||||
for(size_t imageIndex = images.size(); imageIndex--; )
|
||||
{
|
||||
if(g_FrameIndex >= images[imageIndex].endFrame)
|
||||
{
|
||||
images.erase(images.begin() + imageIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SaveAllocatorStatsToFile(L"SparseBindingTest.json");
|
||||
|
||||
// Choose biggest image. Test uploading and sampling.
|
||||
BaseImage* biggestImage = nullptr;
|
||||
for(size_t i = 0, count = images.size(); i < count; ++i)
|
||||
{
|
||||
if(!biggestImage ||
|
||||
images[i].image->GetCreateInfo().extent.width * images[i].image->GetCreateInfo().extent.height >
|
||||
biggestImage->GetCreateInfo().extent.width * biggestImage->GetCreateInfo().extent.height)
|
||||
{
|
||||
biggestImage = images[i].image.get();
|
||||
}
|
||||
}
|
||||
assert(biggestImage);
|
||||
|
||||
biggestImage->TestContent(rand);
|
||||
|
||||
// Free remaining images.
|
||||
images.clear();
|
||||
|
||||
wprintf(L"Done.\n");
|
||||
}
|
||||
|
||||
#endif // #ifdef _WIN32
|
|
@ -1,29 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017-2022 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
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void TestSparseBinding();
|
||||
|
||||
#endif // #ifdef _WIN32
|
|
@ -1,32 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017-2022 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
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef TESTS_H_
|
||||
#define TESTS_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void Test();
|
||||
|
||||
#endif // #ifdef _WIN32
|
||||
|
||||
#endif
|
|
@ -1,30 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017-2022 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
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
/*
|
||||
In exactly one CPP file define macro VMA_IMPLEMENTATION and then include
|
||||
vk_mem_alloc.h to include definitions of its internal implementation
|
||||
*/
|
||||
|
||||
#define VMA_IMPLEMENTATION
|
||||
|
||||
#include "VmaUsage.h"
|
|
@ -1,107 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017-2022 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
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef VMA_USAGE_H_
|
||||
#define VMA_USAGE_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#if !defined(NOMINMAX)
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#if !defined(WIN32_LEAN_AND_MEAN)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#if !defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
#endif // #if !defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||
|
||||
#else // #ifdef _WIN32
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#endif // #ifdef _WIN32
|
||||
|
||||
#ifdef _MSVC_LANG
|
||||
|
||||
// Uncomment to test including `vulkan.h` on your own before including VMA.
|
||||
//#include <vulkan/vulkan.h>
|
||||
|
||||
/*
|
||||
In every place where you want to use Vulkan Memory Allocator, define appropriate
|
||||
macros if you want to configure the library and then include its header to
|
||||
include all public interface declarations. Example:
|
||||
*/
|
||||
|
||||
//#define VMA_HEAVY_ASSERT(expr) assert(expr)
|
||||
//#define VMA_DEDICATED_ALLOCATION 0
|
||||
//#define VMA_DEBUG_MARGIN 16
|
||||
//#define VMA_DEBUG_DETECT_CORRUPTION 1
|
||||
//#define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY 256
|
||||
//#define VMA_USE_STL_SHARED_MUTEX 0
|
||||
//#define VMA_MEMORY_BUDGET 0
|
||||
//#define VMA_STATS_STRING_ENABLED 0
|
||||
//#define VMA_MAPPING_HYSTERESIS_ENABLED 0
|
||||
|
||||
//#define VMA_VULKAN_VERSION 1003000 // Vulkan 1.3
|
||||
//#define VMA_VULKAN_VERSION 1002000 // Vulkan 1.2
|
||||
//#define VMA_VULKAN_VERSION 1001000 // Vulkan 1.1
|
||||
//#define VMA_VULKAN_VERSION 1000000 // Vulkan 1.0
|
||||
|
||||
/*
|
||||
#define VMA_DEBUG_LOG(format, ...) do { \
|
||||
printf(format, __VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} while(false)
|
||||
*/
|
||||
|
||||
#pragma warning(push, 4)
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#pragma warning(disable: 4100) // unreferenced formal parameter
|
||||
#pragma warning(disable: 4189) // local variable is initialized but not referenced
|
||||
#pragma warning(disable: 4324) // structure was padded due to alignment specifier
|
||||
|
||||
#endif // #ifdef _MSVC_LANG
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wtautological-compare" // comparison of unsigned expression < 0 is always false
|
||||
#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
|
||||
#pragma clang diagnostic ignored "-Wnullability-completeness"
|
||||
#endif
|
||||
|
||||
#include "../include/vk_mem_alloc.h"
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef _MSVC_LANG
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,10 +0,0 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
find_package(Vulkan REQUIRED)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/VulkanMemoryAllocatorTargets.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
||||
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
include(GNUInstallDirs)
|
||||
target_include_directories(VulkanMemoryAllocator PUBLIC
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDE_DIRS}>
|
||||
)
|
||||
install(TARGETS VulkanMemoryAllocator
|
||||
EXPORT VulkanMemoryAllocatorTargets
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
# install(FILES "${PROJECT_SOURCE_DIR}/include/vk_mem_alloc.h" DESTINATION "include")
|
||||
install(FILES "${PROJECT_SOURCE_DIR}/include/vk_mem_alloc.h"
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
install(EXPORT VulkanMemoryAllocatorTargets
|
||||
FILE VulkanMemoryAllocatorTargets.cmake
|
||||
NAMESPACE VulkanMemoryAllocator::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanMemoryAllocator
|
||||
)
|
||||
include(CMakePackageConfigHelpers)
|
||||
configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/Config.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/VulkanMemoryAllocatorConfig.cmake"
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanMemoryAllocator
|
||||
)
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/VulkanMemoryAllocatorConfig.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanMemoryAllocator
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
<Type Name="VmaRawList<*>">
|
||||
<DisplayString>{{ Count={m_Count} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[Count]">m_Count</Item>
|
||||
<LinkedListItems>
|
||||
<Size>m_Count</Size>
|
||||
<HeadPointer>m_pFront</HeadPointer>
|
||||
<NextPointer>pNext</NextPointer>
|
||||
<ValueNode>Value</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="VmaList<*>">
|
||||
<DisplayString>{{ Count={m_RawList.m_Count} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[Count]">m_RawList.m_Count</Item>
|
||||
<LinkedListItems>
|
||||
<Size>m_RawList.m_Count</Size>
|
||||
<HeadPointer>m_RawList.m_pFront</HeadPointer>
|
||||
<NextPointer>pNext</NextPointer>
|
||||
<ValueNode>Value</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="VmaVector<*>">
|
||||
<DisplayString>{{ Count={m_Count} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[Count]">m_Count</Item>
|
||||
<Item Name="[Capacity]">m_Capacity</Item>
|
||||
<ArrayItems>
|
||||
<Size>m_Count</Size>
|
||||
<ValuePointer>m_pArray</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<!--
|
||||
Due to custom way of accesing next items in
|
||||
VmaIntrusiveLinkedList via methods in provided type traits,
|
||||
every specialization must be manually added with
|
||||
custom <NextPointer> field describing proper way of iterating the list.
|
||||
-->
|
||||
<Type Name="VmaIntrusiveLinkedList<VmaDedicatedAllocationListItemTraits>">
|
||||
<DisplayString>{{ Count={m_Count} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[Count]">m_Count</Item>
|
||||
<LinkedListItems>
|
||||
<Size>m_Count</Size>
|
||||
<HeadPointer>m_Front</HeadPointer>
|
||||
<NextPointer>m_DedicatedAllocation.m_Next</NextPointer>
|
||||
<ValueNode>*this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="VmaIntrusiveLinkedList<VmaPoolListItemTraits>">
|
||||
<DisplayString>{{ Count={m_Count} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[Count]">m_Count</Item>
|
||||
<LinkedListItems>
|
||||
<Size>m_Count</Size>
|
||||
<HeadPointer>m_Front</HeadPointer>
|
||||
<NextPointer>m_NextPool</NextPointer>
|
||||
<ValueNode>*this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
</AutoVisualizer>
|
|
@ -1,163 +0,0 @@
|
|||
{
|
||||
"$id": "https://gpuopen.com/vulkan-memory-allocator/schemas/GpuMemDump",
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"General": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"API": {"type": "string", "enum": ["Vulkan", "Direct3D 12"]},
|
||||
"GPU": {"type": "string"}
|
||||
},
|
||||
"required": ["API", "GPU"]
|
||||
},
|
||||
"Total": {"$ref": "#/$defs/Stats"},
|
||||
"MemoryInfo": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Flags": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"Size": {"type": "integer"},
|
||||
"Budget": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"BudgetBytes": {"type": "integer"},
|
||||
"UsageBytes": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Stats": {"$ref": "#/$defs/Stats"},
|
||||
"MemoryPools": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Flags": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"Stats": {"$ref": "#/$defs/Stats"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["Budget", "Stats"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"DefaultPools": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"PreferredBlockSize": {"type": "integer"},
|
||||
"Blocks": {
|
||||
"type": "object",
|
||||
"propertyNames": {"pattern": "[0-9]+"},
|
||||
"additionalProperties": {"$ref": "#/$defs/Block"}
|
||||
},
|
||||
"DedicatedAllocations": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/DedicatedAllocation"}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CustomPools": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Name": {"type": "string"},
|
||||
"Flags": {"type": "array"},
|
||||
"PreferredBlockSize": {"type": "integer"},
|
||||
"Blocks": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"$ref": "#/$defs/Block"}
|
||||
},
|
||||
"DedicatedAllocations": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/DedicatedAllocation"}
|
||||
}
|
||||
},
|
||||
"required": ["PreferredBlockSize"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["General", "Total", "MemoryInfo"],
|
||||
"additionalProperties": false,
|
||||
"$defs": {
|
||||
"CustomData": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9a-zA-Z]+$"
|
||||
},
|
||||
"Stats": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"BlockCount": {"type": "integer"},
|
||||
"BlockBytes": {"type": "integer"},
|
||||
"AllocationCount": {"type": "integer"},
|
||||
"AllocationBytes": {"type": "integer"},
|
||||
"UnusedRangeCount": {"type": "integer"},
|
||||
"AllocationSizeMin": {"type": "integer"},
|
||||
"AllocationSizeMax": {"type": "integer"},
|
||||
"UnusedRangeSizeMin": {"type": "integer"},
|
||||
"UnusedRangeSizeMax": {"type": "integer"}
|
||||
},
|
||||
"required": [
|
||||
"BlockCount", "BlockBytes",
|
||||
"AllocationCount", "AllocationBytes",
|
||||
"UnusedRangeCount"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Block": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"MapRefCount": {"type": "integer"},
|
||||
"TotalBytes": {"type": "integer"},
|
||||
"UnusedBytes": {"type": "integer"},
|
||||
"Allocations": {"type": "integer"},
|
||||
"UnusedRanges": {"type": "integer"},
|
||||
"Suballocations": {"type": "array", "items": {"$ref": "#/$defs/Suballocation"}}
|
||||
},
|
||||
"required": ["TotalBytes", "UnusedBytes", "Allocations", "UnusedRanges"]
|
||||
},
|
||||
"DedicatedAllocation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Type": {"type": "string"},
|
||||
"Size": {"type": "integer"},
|
||||
"Usage": {"type": "integer"},
|
||||
"CustomData": {"$ref": "#/$defs/CustomData"},
|
||||
"Name": {"type": "string"},
|
||||
"Layout": {"type": "integer"}
|
||||
},
|
||||
"required": ["Type", "Size"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Suballocation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Offset": {"type": "integer"},
|
||||
"Type": {"type": "string"},
|
||||
"Size": {"type": "integer"},
|
||||
"Usage": {"type": "integer"},
|
||||
"CustomData": {"$ref": "#/$defs/CustomData"},
|
||||
"Name": {"type": "string"},
|
||||
"Layout": {"type": "integer"}
|
||||
},
|
||||
"required": ["Offset", "Type", "Size"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,333 +0,0 @@
|
|||
#
|
||||
# Copyright (c) 2018-2022 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
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
|
||||
PROGRAM_VERSION = 'Vulkan/D3D12 Memory Allocator Dump Visualization 3.0.1'
|
||||
IMG_WIDTH = 1200
|
||||
IMG_MARGIN = 8
|
||||
TEXT_MARGIN = 4
|
||||
FONT_SIZE = 10
|
||||
MAP_SIZE = 24
|
||||
COLOR_TEXT_H1 = (0, 0, 0, 255)
|
||||
COLOR_TEXT_H2 = (150, 150, 150, 255)
|
||||
COLOR_OUTLINE = (155, 155, 155, 255)
|
||||
COLOR_OUTLINE_HARD = (0, 0, 0, 255)
|
||||
COLOR_GRID_LINE = (224, 224, 224, 255)
|
||||
|
||||
currentApi = ""
|
||||
data = {}
|
||||
|
||||
|
||||
def ParseArgs():
|
||||
argParser = argparse.ArgumentParser(description='Visualization of Vulkan/D3D12 Memory Allocator JSON dump.')
|
||||
argParser.add_argument('DumpFile', help='Path to source JSON file with memory dump created by Vulkan/D3D12 Memory Allocator library')
|
||||
argParser.add_argument('-v', '--version', action='version', version=PROGRAM_VERSION)
|
||||
argParser.add_argument('-o', '--output', required=True, help='Path to destination image file (e.g. PNG)')
|
||||
return argParser.parse_args()
|
||||
|
||||
def GetDataForMemoryPool(poolTypeName):
|
||||
global data
|
||||
if poolTypeName in data:
|
||||
return data[poolTypeName]
|
||||
else:
|
||||
newPoolData = {'DedicatedAllocations':[], 'Blocks':[], 'CustomPools':{}}
|
||||
data[poolTypeName] = newPoolData
|
||||
return newPoolData
|
||||
|
||||
def ProcessBlock(poolData, block):
|
||||
blockInfo = {'ID': block[0], 'Size': int(block[1]['TotalBytes']), 'Suballocations':[]}
|
||||
for alloc in block[1]['Suballocations']:
|
||||
allocData = {'Type': alloc['Type'], 'Size': int(alloc['Size']), 'Usage': int(alloc['Usage']) if 'Usage' in alloc else 0 }
|
||||
blockInfo['Suballocations'].append(allocData)
|
||||
poolData['Blocks'].append(blockInfo)
|
||||
|
||||
def IsDataEmpty():
|
||||
global data
|
||||
for poolData in data.values():
|
||||
if len(poolData['DedicatedAllocations']) > 0:
|
||||
return False
|
||||
if len(poolData['Blocks']) > 0:
|
||||
return False
|
||||
for customPool in poolData['CustomPools'].values():
|
||||
if len(customPool['Blocks']) > 0:
|
||||
return False
|
||||
if len(customPool['DedicatedAllocations']) > 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
def RemoveEmptyType():
|
||||
global data
|
||||
for poolType in list(data.keys()):
|
||||
if len(data[poolType]['DedicatedAllocations']) > 0:
|
||||
continue
|
||||
if len(data[poolType]['Blocks']) > 0:
|
||||
continue
|
||||
empty = True
|
||||
for customPool in data[poolType]['CustomPools'].values():
|
||||
if len(data[poolType]['Blocks']) > 0:
|
||||
empty = False
|
||||
break
|
||||
if len(data[poolType]['DedicatedAllocations']) > 0:
|
||||
empty = False
|
||||
break
|
||||
if empty:
|
||||
del data[poolType]
|
||||
|
||||
# Returns tuple:
|
||||
# [0] image height : integer
|
||||
# [1] pixels per byte : float
|
||||
def CalcParams():
|
||||
global data
|
||||
height = IMG_MARGIN
|
||||
height += FONT_SIZE + IMG_MARGIN # Grid lines legend - sizes
|
||||
maxBlockSize = 0
|
||||
# Get height occupied by every memory pool
|
||||
for poolData in data.values():
|
||||
height += FONT_SIZE + IMG_MARGIN # Memory pool title
|
||||
height += len(poolData['Blocks']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
|
||||
height += len(poolData['DedicatedAllocations']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
|
||||
# Get longest block size
|
||||
for dedicatedAlloc in poolData['DedicatedAllocations']:
|
||||
maxBlockSize = max(maxBlockSize, dedicatedAlloc['Size'])
|
||||
for block in poolData['Blocks']:
|
||||
maxBlockSize = max(maxBlockSize, block['Size'])
|
||||
# Same for custom pools
|
||||
for customPoolData in poolData['CustomPools'].values():
|
||||
height += len(customPoolData['Blocks']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
|
||||
height += len(customPoolData['DedicatedAllocations']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
|
||||
# Get longest block size
|
||||
for dedicatedAlloc in customPoolData['DedicatedAllocations']:
|
||||
maxBlockSize = max(maxBlockSize, dedicatedAlloc['Size'])
|
||||
for block in customPoolData['Blocks']:
|
||||
maxBlockSize = max(maxBlockSize, block['Size'])
|
||||
|
||||
return height, (IMG_WIDTH - IMG_MARGIN * 2) / float(maxBlockSize)
|
||||
|
||||
def BytesToStr(bytes):
|
||||
if bytes < 1024:
|
||||
return "%d B" % bytes
|
||||
bytes /= 1024
|
||||
if bytes < 1024:
|
||||
return "%d KiB" % bytes
|
||||
bytes /= 1024
|
||||
if bytes < 1024:
|
||||
return "%d MiB" % bytes
|
||||
bytes /= 1024
|
||||
return "%d GiB" % bytes
|
||||
|
||||
def TypeToColor(type, usage):
|
||||
global currentApi
|
||||
if type == 'FREE':
|
||||
return 220, 220, 220, 255
|
||||
elif type == 'UNKNOWN':
|
||||
return 175, 175, 175, 255 # Gray
|
||||
|
||||
if currentApi == 'Vulkan':
|
||||
if type == 'BUFFER':
|
||||
if (usage & 0x1C0) != 0: # INDIRECT_BUFFER | VERTEX_BUFFER | INDEX_BUFFER
|
||||
return 255, 148, 148, 255 # Red
|
||||
elif (usage & 0x28) != 0: # STORAGE_BUFFER | STORAGE_TEXEL_BUFFER
|
||||
return 255, 187, 121, 255 # Orange
|
||||
elif (usage & 0x14) != 0: # UNIFORM_BUFFER | UNIFORM_TEXEL_BUFFER
|
||||
return 255, 255, 0, 255 # Yellow
|
||||
else:
|
||||
return 255, 255, 165, 255 # Light yellow
|
||||
elif type == 'IMAGE_OPTIMAL':
|
||||
if (usage & 0x20) != 0: # DEPTH_STENCIL_ATTACHMENT
|
||||
return 246, 128, 255, 255 # Pink
|
||||
elif (usage & 0xD0) != 0: # INPUT_ATTACHMENT | TRANSIENT_ATTACHMENT | COLOR_ATTACHMENT
|
||||
return 179, 179, 255, 255 # Blue
|
||||
elif (usage & 0x4) != 0: # SAMPLED
|
||||
return 0, 255, 255, 255 # Aqua
|
||||
else:
|
||||
return 183, 255, 255, 255 # Light aqua
|
||||
elif type == 'IMAGE_LINEAR' :
|
||||
return 0, 255, 0, 255 # Green
|
||||
elif type == 'IMAGE_UNKNOWN':
|
||||
return 0, 255, 164, 255 # Green/aqua
|
||||
elif currentApi == 'Direct3D 12':
|
||||
if type == 'BUFFER':
|
||||
return 255, 255, 165, 255 # Light yellow
|
||||
elif type == 'TEXTURE1D' or type == 'TEXTURE2D' or type == 'TEXTURE3D':
|
||||
if (usage & 0x2) != 0: # D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL
|
||||
return 246, 128, 255, 255 # Pink
|
||||
elif (usage & 0x5) != 0: # D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS
|
||||
return 179, 179, 255, 255 # Blue
|
||||
elif (usage & 0x8) == 0: # Not having D3D12_RESOURCE_FLAG_DENY_SHARED_RESOURCE
|
||||
return 0, 255, 255, 255 # Aqua
|
||||
else:
|
||||
return 183, 255, 255, 255 # Light aqua
|
||||
else:
|
||||
print("Unknown graphics API!")
|
||||
exit(1)
|
||||
assert False
|
||||
return 0, 0, 0, 255
|
||||
|
||||
def DrawBlock(draw, y, block, pixelsPerByte):
|
||||
sizePixels = int(block['Size'] * pixelsPerByte)
|
||||
draw.rectangle([IMG_MARGIN, y, IMG_MARGIN + sizePixels, y + MAP_SIZE], fill=TypeToColor('FREE', 0), outline=None)
|
||||
byte = 0
|
||||
x = 0
|
||||
lastHardLineX = -1
|
||||
for alloc in block['Suballocations']:
|
||||
byteEnd = byte + alloc['Size']
|
||||
xEnd = int(byteEnd * pixelsPerByte)
|
||||
if alloc['Type'] != 'FREE':
|
||||
if xEnd > x + 1:
|
||||
draw.rectangle([IMG_MARGIN + x, y, IMG_MARGIN + xEnd, y + MAP_SIZE], fill=TypeToColor(alloc['Type'], alloc['Usage']), outline=COLOR_OUTLINE)
|
||||
# Hard line was been overwritten by rectangle outline: redraw it.
|
||||
if lastHardLineX == x:
|
||||
draw.line([IMG_MARGIN + x, y, IMG_MARGIN + x, y + MAP_SIZE], fill=COLOR_OUTLINE_HARD)
|
||||
else:
|
||||
draw.line([IMG_MARGIN + x, y, IMG_MARGIN + x, y + MAP_SIZE], fill=COLOR_OUTLINE_HARD)
|
||||
lastHardLineX = x
|
||||
byte = byteEnd
|
||||
x = xEnd
|
||||
|
||||
def DrawDedicatedAllocationBlock(draw, y, dedicatedAlloc, pixelsPerByte):
|
||||
sizePixels = int(dedicatedAlloc['Size'] * pixelsPerByte)
|
||||
draw.rectangle([IMG_MARGIN, y, IMG_MARGIN + sizePixels, y + MAP_SIZE], fill=TypeToColor(dedicatedAlloc['Type'], dedicatedAlloc['Usage']), outline=COLOR_OUTLINE)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = ParseArgs()
|
||||
jsonSrc = json.load(open(args.DumpFile, 'rb'))
|
||||
|
||||
if 'General' in jsonSrc:
|
||||
currentApi = jsonSrc['General']['API']
|
||||
else:
|
||||
print("Wrong JSON format, cannot determine graphics API!")
|
||||
exit(1)
|
||||
|
||||
# Process default pools
|
||||
if 'DefaultPools' in jsonSrc:
|
||||
for memoryPool in jsonSrc['DefaultPools'].items():
|
||||
poolData = GetDataForMemoryPool(memoryPool[0])
|
||||
# Get dedicated allocations
|
||||
for dedicatedAlloc in memoryPool[1]['DedicatedAllocations']:
|
||||
allocData = {'Type': dedicatedAlloc['Type'], 'Size': int(dedicatedAlloc['Size']), 'Usage': int(dedicatedAlloc['Usage'])}
|
||||
poolData['DedicatedAllocations'].append(allocData)
|
||||
# Get allocations in block vectors
|
||||
for block in memoryPool[1]['Blocks'].items():
|
||||
ProcessBlock(poolData, block)
|
||||
# Process custom pools
|
||||
if 'CustomPools' in jsonSrc:
|
||||
for memoryPool in jsonSrc['CustomPools'].items():
|
||||
poolData = GetDataForMemoryPool(memoryPool[0])
|
||||
for pool in memoryPool[1]:
|
||||
poolName = pool['Name']
|
||||
poolData['CustomPools'][poolName] = {'DedicatedAllocations':[], 'Blocks':[]}
|
||||
# Get dedicated allocations
|
||||
for dedicatedAlloc in pool['DedicatedAllocations']:
|
||||
allocData = {'Type': dedicatedAlloc['Type'], 'Size': int(dedicatedAlloc['Size']), 'Usage': int(dedicatedAlloc['Usage'])}
|
||||
poolData['CustomPools'][poolName]['DedicatedAllocations'].append(allocData)
|
||||
# Get allocations in block vectors
|
||||
for block in pool['Blocks'].items():
|
||||
ProcessBlock(poolData['CustomPools'][poolName], block)
|
||||
|
||||
if IsDataEmpty():
|
||||
print("There is nothing to put on the image. Please make sure you generated the stats string with detailed map enabled.")
|
||||
exit(1)
|
||||
RemoveEmptyType()
|
||||
# Calculate dimmensions and create data image
|
||||
imgHeight, pixelsPerByte = CalcParams()
|
||||
img = Image.new('RGB', (IMG_WIDTH, imgHeight), 'white')
|
||||
draw = ImageDraw.Draw(img)
|
||||
try:
|
||||
font = ImageFont.truetype('segoeuib.ttf')
|
||||
except:
|
||||
font = ImageFont.load_default()
|
||||
|
||||
# Draw grid lines
|
||||
bytesBetweenGridLines = 32
|
||||
while bytesBetweenGridLines * pixelsPerByte < 64:
|
||||
bytesBetweenGridLines *= 2
|
||||
byte = 0
|
||||
y = IMG_MARGIN
|
||||
while True:
|
||||
x = int(byte * pixelsPerByte)
|
||||
if x > IMG_WIDTH - 2 * IMG_MARGIN:
|
||||
break
|
||||
draw.line([x + IMG_MARGIN, 0, x + IMG_MARGIN, imgHeight], fill=COLOR_GRID_LINE)
|
||||
if byte == 0:
|
||||
draw.text((x + IMG_MARGIN + TEXT_MARGIN, y), "0", fill=COLOR_TEXT_H2, font=font)
|
||||
else:
|
||||
text = BytesToStr(byte)
|
||||
textSize = draw.textsize(text, font=font)
|
||||
draw.text((x + IMG_MARGIN - textSize[0] - TEXT_MARGIN, y), text, fill=COLOR_TEXT_H2, font=font)
|
||||
byte += bytesBetweenGridLines
|
||||
y += FONT_SIZE + IMG_MARGIN
|
||||
|
||||
# Draw main content
|
||||
for memType in sorted(data.keys()):
|
||||
memPoolData = data[memType]
|
||||
draw.text((IMG_MARGIN, y), "Memory pool %s" % memType, fill=COLOR_TEXT_H1, font=font)
|
||||
y += FONT_SIZE + IMG_MARGIN
|
||||
# Draw block vectors
|
||||
for block in memPoolData['Blocks']:
|
||||
draw.text((IMG_MARGIN, y), "Default pool block %s" % block['ID'], fill=COLOR_TEXT_H2, font=font)
|
||||
y += FONT_SIZE + IMG_MARGIN
|
||||
DrawBlock(draw, y, block, pixelsPerByte)
|
||||
y += MAP_SIZE + IMG_MARGIN
|
||||
index = 0
|
||||
# Draw dedicated allocations
|
||||
for dedicatedAlloc in memPoolData['DedicatedAllocations']:
|
||||
draw.text((IMG_MARGIN, y), "Dedicated allocation %d" % index, fill=COLOR_TEXT_H2, font=font)
|
||||
y += FONT_SIZE + IMG_MARGIN
|
||||
DrawDedicatedAllocationBlock(draw, y, dedicatedAlloc, pixelsPerByte)
|
||||
y += MAP_SIZE + IMG_MARGIN
|
||||
index += 1
|
||||
for poolName, pool in memPoolData['CustomPools'].items():
|
||||
for block in pool['Blocks']:
|
||||
draw.text((IMG_MARGIN, y), "Custom pool %s block %s" % (poolName, block['ID']), fill=COLOR_TEXT_H2, font=font)
|
||||
y += FONT_SIZE + IMG_MARGIN
|
||||
DrawBlock(draw, y, block, pixelsPerByte)
|
||||
y += MAP_SIZE + IMG_MARGIN
|
||||
index = 0
|
||||
for dedicatedAlloc in pool['DedicatedAllocations']:
|
||||
draw.text((IMG_MARGIN, y), "Custom pool %s dedicated allocation %d" % (poolName, index), fill=COLOR_TEXT_H2, font=font)
|
||||
y += FONT_SIZE + IMG_MARGIN
|
||||
DrawDedicatedAllocationBlock(draw, y, dedicatedAlloc, pixelsPerByte)
|
||||
y += MAP_SIZE + IMG_MARGIN
|
||||
index += 1
|
||||
del draw
|
||||
img.save(args.output)
|
||||
|
||||
"""
|
||||
Main data structure - variable `data` - is a dictionary. Key is string - memory type name. Value is dictionary of:
|
||||
- Fixed key 'DedicatedAllocations'. Value is list of objects, each containing dictionary with:
|
||||
- Fixed key 'Type'. Value is string.
|
||||
- Fixed key 'Size'. Value is int.
|
||||
- Fixed key 'Usage'. Value is int.
|
||||
- Fixed key 'Blocks'. Value is list of objects, each containing dictionary with:
|
||||
- Fixed key 'ID'. Value is int.
|
||||
- Fixed key 'Size'. Value is int.
|
||||
- Fixed key 'Suballocations'. Value is list of objects as above.
|
||||
- Fixed key 'CustomPools'. Value is dictionary.
|
||||
- Key is string with pool ID/name. Value is a dictionary with:
|
||||
- Fixed key 'DedicatedAllocations'. Value is list of objects as above.
|
||||
- Fixed key 'Blocks'. Value is a list of objects representing memory blocks as above.
|
||||
"""
|
|
@ -1,45 +0,0 @@
|
|||
# GpuMemDumpVis
|
||||
|
||||
Vulkan/D3D12 Memory Allocator Dump Visualization.
|
||||
It is an auxiliary tool that can visualize internal state of [Vulkan Memory Allocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) and
|
||||
[D3D12 Memory Allocator](https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator) libraries on a picture.
|
||||
It is a Python script that must be launched from command line with appropriate parameters.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3 installed
|
||||
- [Pillow](http://python-pillow.org/) - Python Imaging Library (Fork) installed
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
python GpuMemDumpVis.py -o OUTPUT_FILE INPUT_FILE
|
||||
```
|
||||
|
||||
* `INPUT_FILE` - path to source file to be read, containing dump of internal state of the VMA/D3D12MA library in JSON format (encoding: UTF-8/UTF-16), generated using `vmaBuildStatsString()` and `D3D12MA::Allocator::BuildStatsString()` functions.
|
||||
* `OUTPUT_FILE` - path to destination file to be written that will contain generated image. Image format is automatically recognized based on file extension. List of supported formats can be found [here](http://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html) and includes: BMP, GIF, JPEG, PNG, TGA.
|
||||
|
||||
You can also use typical options:
|
||||
|
||||
* `-h` - to see help on command line syntax
|
||||
* `-v` - to see program version number
|
||||
|
||||
## Example output
|
||||
|
||||

|
||||
|
||||
## Legend
|
||||
|
||||
*  Light gray without border - a space in Vulkan device memory block unused by any allocation.
|
||||
*  Buffer with usage containing INDIRECT_BUFFER, VERTEX_BUFFER, or INDEX_BUFFER (Vulkan).
|
||||
*  Buffer with usage containing STORAGE_BUFFER or STORAGE_TEXEL_BUFFER (Vulkan).
|
||||
*  Buffer with usage containing UNIFORM_BUFFER or UNIFORM_TEXEL_BUFFER (Vulkan).
|
||||
*  Other buffer.
|
||||
*  Image with OPTIMAL tiling and usage containing DEPTH_STENCIL_ATTACHMENT (Vulkan) or a texture with usage containing D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL (D3D12).
|
||||
*  Image with OPTIMAL tiling and usage containing INPUT_ATTACHMENT, TRANSIENT_ATTACHMENT or COLOR_ATTACHMENT (Vulkan), or a texture with usage containing D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET or D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS (D3D12).
|
||||
*  Image with OPTIMAL tiling and usage containing SAMPLED (Vulkan) or a texture with usage not containing D3D12_RESOURCE_FLAG_DENY_SHARED_RESOURCE (D3D12).
|
||||
*  Other image with OPTIMAL tiling (Vulkan) or a texture (D3D12).
|
||||
*  Image with LINEAR tiling (Vulkan).
|
||||
*  Image with tiling unknown to the allocator (Vulkan).
|
||||
*  Allocation of unknown type.
|
||||
*  Black bar - one or more allocations of any kind too small to be visualized as filled rectangles.
|
Before Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 196 B |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 964 B |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB |
|
@ -1,426 +0,0 @@
|
|||
{
|
||||
"General": {
|
||||
"API": "Vulkan",
|
||||
"apiVersion": "1.3.203",
|
||||
"GPU": "AMD Radeon RX 6600 XT",
|
||||
"deviceType": 2,
|
||||
"maxMemoryAllocationCount": 4096,
|
||||
"bufferImageGranularity": 1,
|
||||
"nonCoherentAtomSize": 128,
|
||||
"memoryHeapCount": 2,
|
||||
"memoryTypeCount": 8
|
||||
},
|
||||
"Total": {
|
||||
"BlockCount": 69,
|
||||
"BlockBytes": 201392128,
|
||||
"AllocationCount": 132,
|
||||
"AllocationBytes": 73401500,
|
||||
"UnusedRangeCount": 11,
|
||||
"AllocationSizeMin": 60,
|
||||
"AllocationSizeMax": 6095200,
|
||||
"UnusedRangeSizeMin": 196,
|
||||
"UnusedRangeSizeMax": 33550336
|
||||
},
|
||||
"MemoryInfo": {
|
||||
"Heap 0": {
|
||||
"Flags": [],
|
||||
"Size": 16862150656,
|
||||
"Budget": {
|
||||
"BudgetBytes": 16325847040,
|
||||
"UsageBytes": 122392576
|
||||
},
|
||||
"Stats": {
|
||||
"BlockCount": 35,
|
||||
"BlockBytes": 117473280,
|
||||
"AllocationCount": 64,
|
||||
"AllocationBytes": 33619968,
|
||||
"UnusedRangeCount": 5,
|
||||
"AllocationSizeMin": 1024,
|
||||
"AllocationSizeMax": 2097152,
|
||||
"UnusedRangeSizeMin": 49152,
|
||||
"UnusedRangeSizeMax": 33550336
|
||||
},
|
||||
"MemoryPools": {
|
||||
"Type 1": {
|
||||
"Flags": ["HOST_VISIBLE", "HOST_COHERENT"],
|
||||
"Stats": {
|
||||
"BlockCount": 5,
|
||||
"BlockBytes": 33558528,
|
||||
"AllocationCount": 8,
|
||||
"AllocationBytes": 8192,
|
||||
"UnusedRangeCount": 1,
|
||||
"AllocationSizeMin": 1024,
|
||||
"AllocationSizeMax": 1024
|
||||
}
|
||||
},
|
||||
"Type 3": {
|
||||
"Flags": ["HOST_VISIBLE", "HOST_COHERENT", "HOST_CACHED"],
|
||||
"Stats": {
|
||||
"BlockCount": 30,
|
||||
"BlockBytes": 83914752,
|
||||
"AllocationCount": 56,
|
||||
"AllocationBytes": 33611776,
|
||||
"UnusedRangeCount": 4,
|
||||
"AllocationSizeMin": 1024,
|
||||
"AllocationSizeMax": 2097152,
|
||||
"UnusedRangeSizeMin": 49152,
|
||||
"UnusedRangeSizeMax": 25100288
|
||||
}
|
||||
},
|
||||
"Type 5": {
|
||||
"Flags": ["HOST_VISIBLE", "HOST_COHERENT", "DEVICE_COHERENT_AMD", "DEVICE_UNCACHED_AMD"],
|
||||
"Stats": {
|
||||
"BlockCount": 0,
|
||||
"BlockBytes": 0,
|
||||
"AllocationCount": 0,
|
||||
"AllocationBytes": 0,
|
||||
"UnusedRangeCount": 0
|
||||
}
|
||||
},
|
||||
"Type 7": {
|
||||
"Flags": ["HOST_VISIBLE", "HOST_COHERENT", "HOST_CACHED", "DEVICE_COHERENT_AMD", "DEVICE_UNCACHED_AMD"],
|
||||
"Stats": {
|
||||
"BlockCount": 0,
|
||||
"BlockBytes": 0,
|
||||
"AllocationCount": 0,
|
||||
"AllocationBytes": 0,
|
||||
"UnusedRangeCount": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Heap 1": {
|
||||
"Flags": ["DEVICE_LOCAL", "MULTI_INSTANCE"],
|
||||
"Size": 8573157376,
|
||||
"Budget": {
|
||||
"BudgetBytes": 7737008128,
|
||||
"UsageBytes": 155025408
|
||||
},
|
||||
"Stats": {
|
||||
"BlockCount": 34,
|
||||
"BlockBytes": 83918848,
|
||||
"AllocationCount": 68,
|
||||
"AllocationBytes": 39781532,
|
||||
"UnusedRangeCount": 6,
|
||||
"AllocationSizeMin": 60,
|
||||
"AllocationSizeMax": 6095200,
|
||||
"UnusedRangeSizeMin": 196,
|
||||
"UnusedRangeSizeMax": 25100288
|
||||
},
|
||||
"MemoryPools": {
|
||||
"Type 0": {
|
||||
"Flags": ["DEVICE_LOCAL"],
|
||||
"Stats": {
|
||||
"BlockCount": 34,
|
||||
"BlockBytes": 83918848,
|
||||
"AllocationCount": 68,
|
||||
"AllocationBytes": 39781532,
|
||||
"UnusedRangeCount": 6,
|
||||
"AllocationSizeMin": 60,
|
||||
"AllocationSizeMax": 6095200,
|
||||
"UnusedRangeSizeMin": 196,
|
||||
"UnusedRangeSizeMax": 25100288
|
||||
}
|
||||
},
|
||||
"Type 2": {
|
||||
"Flags": ["DEVICE_LOCAL", "HOST_VISIBLE", "HOST_COHERENT"],
|
||||
"Stats": {
|
||||
"BlockCount": 0,
|
||||
"BlockBytes": 0,
|
||||
"AllocationCount": 0,
|
||||
"AllocationBytes": 0,
|
||||
"UnusedRangeCount": 0
|
||||
}
|
||||
},
|
||||
"Type 4": {
|
||||
"Flags": ["DEVICE_LOCAL", "DEVICE_COHERENT_AMD", "DEVICE_UNCACHED_AMD"],
|
||||
"Stats": {
|
||||
"BlockCount": 0,
|
||||
"BlockBytes": 0,
|
||||
"AllocationCount": 0,
|
||||
"AllocationBytes": 0,
|
||||
"UnusedRangeCount": 0
|
||||
}
|
||||
},
|
||||
"Type 6": {
|
||||
"Flags": ["DEVICE_LOCAL", "HOST_VISIBLE", "HOST_COHERENT", "DEVICE_COHERENT_AMD", "DEVICE_UNCACHED_AMD"],
|
||||
"Stats": {
|
||||
"BlockCount": 0,
|
||||
"BlockBytes": 0,
|
||||
"AllocationCount": 0,
|
||||
"AllocationBytes": 0,
|
||||
"UnusedRangeCount": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"DefaultPools": {
|
||||
"Type 0": {
|
||||
"PreferredBlockSize": 268435456,
|
||||
"Blocks": {
|
||||
"0": {
|
||||
"MapRefCount": 0,
|
||||
"TotalBytes": 33554432,
|
||||
"UnusedBytes": 18987876,
|
||||
"Allocations": 20,
|
||||
"UnusedRanges": 4,
|
||||
"Suballocations": [
|
||||
{"Offset": 0, "Type": "IMAGE_OPTIMAL", "Size": 65536, "Usage": 6},
|
||||
{"Offset": 65536, "Type": "BUFFER", "Size": 768, "Usage": 130},
|
||||
{"Offset": 66304, "Type": "BUFFER", "Size": 60, "Usage": 66},
|
||||
{"Offset": 66364, "Type": "UNKNOWN", "Size": 1024, "Usage": 0},
|
||||
{"Offset": 67388, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 68412, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "Name": "SHEPURD"},
|
||||
{"Offset": 69436, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 70460, "Type": "BUFFER", "Size": 1024, "Usage": 3},
|
||||
{"Offset": 71484, "Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 72508, "Type": "BUFFER", "Size": 1024, "Usage": 3, "Name": "SHEPURD"},
|
||||
{"Offset": 73532, "Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 74556, "Type": "FREE", "Size": 196},
|
||||
{"Offset": 74752, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7},
|
||||
{"Offset": 76800, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 78848, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Offset": 80896, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 82944, "Type": "FREE", "Size": 48128},
|
||||
{"Offset": 131072, "Type": "IMAGE_OPTIMAL", "Size": 6095200, "Usage": 32},
|
||||
{"Offset": 6226272, "Type": "FREE", "Size": 65184},
|
||||
{"Offset": 6291456, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7},
|
||||
{"Offset": 8388608, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 10485760, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Offset": 12582912, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 14680064, "Type": "FREE", "Size": 18874368}
|
||||
]
|
||||
}
|
||||
},
|
||||
"DedicatedAllocations": [
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "Name": "SHEPURD"},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "Name": "SHEPURD"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"}
|
||||
]
|
||||
},
|
||||
"Type 1": {
|
||||
"PreferredBlockSize": 268435456,
|
||||
"Blocks": {
|
||||
"0": {
|
||||
"MapRefCount": 0,
|
||||
"TotalBytes": 33554432,
|
||||
"UnusedBytes": 33550336,
|
||||
"Allocations": 4,
|
||||
"UnusedRanges": 1,
|
||||
"Suballocations": [
|
||||
{"Offset": 0, "Type": "UNKNOWN", "Size": 1024, "Usage": 0},
|
||||
{"Offset": 1024, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 2048, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "Name": "SHEPURD"},
|
||||
{"Offset": 3072, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 4096, "Type": "FREE", "Size": 33550336}
|
||||
]
|
||||
}
|
||||
},
|
||||
"DedicatedAllocations": [
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "Name": "SHEPURD"},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "00000000018CE96A", "Name": "JOKER"}
|
||||
]
|
||||
},
|
||||
"Type 2": {
|
||||
"PreferredBlockSize": 268435456,
|
||||
"Blocks": {
|
||||
},
|
||||
"DedicatedAllocations": [
|
||||
]
|
||||
},
|
||||
"Type 3": {
|
||||
"PreferredBlockSize": 268435456,
|
||||
"Blocks": {
|
||||
"0": {
|
||||
"MapRefCount": 0,
|
||||
"TotalBytes": 33554432,
|
||||
"UnusedBytes": 25153536,
|
||||
"Allocations": 12,
|
||||
"UnusedRanges": 2,
|
||||
"Suballocations": [
|
||||
{"Offset": 0, "Type": "BUFFER", "Size": 1024, "Usage": 3},
|
||||
{"Offset": 1024, "Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 2048, "Type": "BUFFER", "Size": 1024, "Usage": 3, "Name": "SHEPURD"},
|
||||
{"Offset": 3072, "Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 4096, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7},
|
||||
{"Offset": 6144, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 8192, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Offset": 10240, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 12288, "Type": "FREE", "Size": 53248},
|
||||
{"Offset": 65536, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7},
|
||||
{"Offset": 2162688, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 4259840, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Offset": 6356992, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 8454144, "Type": "FREE", "Size": 25100288}
|
||||
]
|
||||
}
|
||||
},
|
||||
"DedicatedAllocations": [
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "Name": "SHEPURD"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"}
|
||||
]
|
||||
},
|
||||
"Type 4": {
|
||||
"PreferredBlockSize": 268435456,
|
||||
"Blocks": {
|
||||
},
|
||||
"DedicatedAllocations": [
|
||||
]
|
||||
},
|
||||
"Type 5": {
|
||||
"PreferredBlockSize": 268435456,
|
||||
"Blocks": {
|
||||
},
|
||||
"DedicatedAllocations": [
|
||||
]
|
||||
},
|
||||
"Type 6": {
|
||||
"PreferredBlockSize": 268435456,
|
||||
"Blocks": {
|
||||
},
|
||||
"DedicatedAllocations": [
|
||||
]
|
||||
},
|
||||
"Type 7": {
|
||||
"PreferredBlockSize": 268435456,
|
||||
"Blocks": {
|
||||
},
|
||||
"DedicatedAllocations": [
|
||||
]
|
||||
}
|
||||
},
|
||||
"CustomPools": {
|
||||
"Type 0": [
|
||||
{
|
||||
"Name": "0",
|
||||
"PreferredBlockSize": 268435456,
|
||||
"Blocks": {
|
||||
"0": {
|
||||
"MapRefCount": 0,
|
||||
"TotalBytes": 33554432,
|
||||
"UnusedBytes": 25149440,
|
||||
"Allocations": 16,
|
||||
"UnusedRanges": 2,
|
||||
"Suballocations": [
|
||||
{"Offset": 0, "Type": "UNKNOWN", "Size": 1024, "Usage": 0},
|
||||
{"Offset": 1024, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 2048, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "Name": "SHEPURD"},
|
||||
{"Offset": 3072, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 4096, "Type": "BUFFER", "Size": 1024, "Usage": 3},
|
||||
{"Offset": 5120, "Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 6144, "Type": "BUFFER", "Size": 1024, "Usage": 3, "Name": "SHEPURD"},
|
||||
{"Offset": 7168, "Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 8192, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7},
|
||||
{"Offset": 10240, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 12288, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Offset": 14336, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 16384, "Type": "FREE", "Size": 49152},
|
||||
{"Offset": 65536, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7},
|
||||
{"Offset": 2162688, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 4259840, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Offset": 6356992, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 8454144, "Type": "FREE", "Size": 25100288}
|
||||
]
|
||||
}
|
||||
},
|
||||
"DedicatedAllocations": [
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "Name": "SHEPURD"},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "Name": "SHEPURD"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Type 3": [
|
||||
{
|
||||
"Name": "0",
|
||||
"PreferredBlockSize": 268435456,
|
||||
"Blocks": {
|
||||
"0": {
|
||||
"MapRefCount": 0,
|
||||
"TotalBytes": 33554432,
|
||||
"UnusedBytes": 25149440,
|
||||
"Allocations": 16,
|
||||
"UnusedRanges": 2,
|
||||
"Suballocations": [
|
||||
{"Offset": 0, "Type": "UNKNOWN", "Size": 1024, "Usage": 0},
|
||||
{"Offset": 1024, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 2048, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "Name": "SHEPURD"},
|
||||
{"Offset": 3072, "Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 4096, "Type": "BUFFER", "Size": 1024, "Usage": 3},
|
||||
{"Offset": 5120, "Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 6144, "Type": "BUFFER", "Size": 1024, "Usage": 3, "Name": "SHEPURD"},
|
||||
{"Offset": 7168, "Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 8192, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7},
|
||||
{"Offset": 10240, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 12288, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Offset": 14336, "Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 16384, "Type": "FREE", "Size": 49152},
|
||||
{"Offset": 65536, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7},
|
||||
{"Offset": 2162688, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Offset": 4259840, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Offset": 6356992, "Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Offset": 8454144, "Type": "FREE", "Size": 25100288}
|
||||
]
|
||||
}
|
||||
},
|
||||
"DedicatedAllocations": [
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "Name": "SHEPURD"},
|
||||
{"Type": "UNKNOWN", "Size": 1024, "Usage": 0, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "Name": "SHEPURD"},
|
||||
{"Type": "BUFFER", "Size": 1024, "Usage": 3, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Type": "IMAGE_LINEAR", "Size": 2048, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "0000000000F5D987"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "Name": "SHEPURD"},
|
||||
{"Type": "IMAGE_OPTIMAL", "Size": 2097152, "Usage": 7, "CustomData": "00000000018CE96A", "Name": "JOKER"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|