graphics: migrate Vulkan backend to Vulkan-Hpp

This commit is contained in:
nmzik committed 2026-07-18 12:33:21 +02:00
1 parent 587cb238f0
commit 7905f2d12f
64 files changed
+4842 -4518

No files matched your search

-24
View File
@@ -5,30 +5,6 @@ add_subdirectory(cpuinfo)
set(SDL_SHARED OFF CACHE BOOL "" FORCE) set(SDL_SHARED OFF CACHE BOOL "" FORCE)
add_subdirectory(SDL2) add_subdirectory(SDL2)
add_library(vulkan-1 UNKNOWN IMPORTED GLOBAL)
if(MINGW)
find_library(Vulkan_Lib NAMES libvulkan-1.dll.a vulkan-1
PATHS "$ENV{VULKAN_SDK}/Lib" "$ENV{VULKAN_SDK}/Lib32" NO_DEFAULT_PATH)
if(NOT Vulkan_Lib)
find_library(Vulkan_Lib NAMES libvulkan-1.dll.a vulkan-1)
endif()
elseif(WIN32)
find_library(Vulkan_Lib NAMES vulkan-1
PATHS "$ENV{VULKAN_SDK}/Lib" "$ENV{VULKAN_SDK}/Lib32" NO_DEFAULT_PATH)
if(NOT Vulkan_Lib)
find_library(Vulkan_Lib NAMES vulkan-1)
endif()
elseif(LINUX)
find_library(Vulkan_Lib vulkan)
endif()
if(NOT Vulkan_Lib OR Vulkan_Lib MATCHES "-NOTFOUND$")
message(FATAL_ERROR "Vulkan library was not found")
endif()
set_target_properties(vulkan-1 PROPERTIES IMPORTED_LOCATION "${Vulkan_Lib}")
set(SPIRV_SKIP_TESTS ON CACHE BOOL "" FORCE) set(SPIRV_SKIP_TESTS ON CACHE BOOL "" FORCE)
set(SPIRV_SKIP_EXECUTABLES ON CACHE BOOL "" FORCE) set(SPIRV_SKIP_EXECUTABLES ON CACHE BOOL "" FORCE)
set(SKIP_SPIRV_TOOLS_INSTALL ON CACHE BOOL "" FORCE) set(SKIP_SPIRV_TOOLS_INSTALL ON CACHE BOOL "" FORCE)
+1 -5
View File
@@ -180,7 +180,7 @@ if (KYTY_CLANG_CL)
set_source_files_properties(${kyty_emulator_src} PROPERTIES COMPILE_FLAGS "-Wno-pragma-pack -Wno-deprecated-declarations -D_TIMESPEC_DEFINED") set_source_files_properties(${kyty_emulator_src} PROPERTIES COMPILE_FLAGS "-Wno-pragma-pack -Wno-deprecated-declarations -D_TIMESPEC_DEFINED")
endif() endif()
set(kyty_emulator_link_libraries common vulkan-1 spirv-tools-opt spirv-tools SDL2-static xxhash FFmpeg::ffmpeg fmt::fmt nlohmann_json::nlohmann_json LibAtrac9) set(kyty_emulator_link_libraries common spirv-tools-opt spirv-tools SDL2-static xxhash FFmpeg::ffmpeg fmt::fmt nlohmann_json::nlohmann_json LibAtrac9)
set(inc_headers set(inc_headers
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
@@ -194,10 +194,6 @@ set(inc_headers
${KYTY_THIRD_PARTY_DIR}/stb ${KYTY_THIRD_PARTY_DIR}/stb
) )
if(DEFINED ENV{VULKAN_SDK})
list(APPEND inc_headers $ENV{VULKAN_SDK}/Include)
endif()
if (KYTY_CLANG_CL) if (KYTY_CLANG_CL)
list(APPEND kyty_emulator_link_libraries winpthread) list(APPEND kyty_emulator_link_libraries winpthread)
list(APPEND inc_headers list(APPEND inc_headers
+64 -63
View File
@@ -8,80 +8,81 @@ namespace Libs::Graphics::Prospero {
namespace { namespace {
constexpr FormatInfo kFormatInfo[] = { constexpr FormatInfo kFormatInfo[] = {
{GpuEnumValue(BufferFormat::k8UNorm), VK_FORMAT_R8_UNORM, 1, 0, 1, true, false}, {GpuEnumValue(BufferFormat::k8UNorm), vk::Format::eR8Unorm, 1, 0, 1, true, false},
{GpuEnumValue(BufferFormat::k8SNorm), VK_FORMAT_UNDEFINED, 0, 0, 1, false, false}, {GpuEnumValue(BufferFormat::k8SNorm), vk::Format::eUndefined, 0, 0, 1, false, false},
{GpuEnumValue(BufferFormat::k8UInt), VK_FORMAT_R8_UINT, 1, 0, 1, true, true}, {GpuEnumValue(BufferFormat::k8UInt), vk::Format::eR8Uint, 1, 0, 1, true, true},
{GpuEnumValue(BufferFormat::k16UNorm), VK_FORMAT_R16_UNORM, 2, 0, 2, true, false}, {GpuEnumValue(BufferFormat::k16UNorm), vk::Format::eR16Unorm, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k16SNorm), VK_FORMAT_R16_SNORM, 2, 0, 2, true, false}, {GpuEnumValue(BufferFormat::k16SNorm), vk::Format::eR16Snorm, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k16UInt), VK_FORMAT_R16_UINT, 2, 0, 2, true, true}, {GpuEnumValue(BufferFormat::k16UInt), vk::Format::eR16Uint, 2, 0, 2, true, true},
{GpuEnumValue(BufferFormat::k16SInt), VK_FORMAT_R16_SINT, 2, 0, 2, false, false}, {GpuEnumValue(BufferFormat::k16SInt), vk::Format::eR16Sint, 2, 0, 2, false, false},
{GpuEnumValue(BufferFormat::k16Float), VK_FORMAT_R16_SFLOAT, 2, 0, 2, true, false}, {GpuEnumValue(BufferFormat::k16Float), vk::Format::eR16Sfloat, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k8_8UNorm), VK_FORMAT_R8G8_UNORM, 2, 0, 2, true, false}, {GpuEnumValue(BufferFormat::k8_8UNorm), vk::Format::eR8G8Unorm, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k8_8SNorm), VK_FORMAT_R8G8_SNORM, 2, 0, 2, true, false}, {GpuEnumValue(BufferFormat::k8_8SNorm), vk::Format::eR8G8Snorm, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k8_8UInt), VK_FORMAT_R8G8_UINT, 2, 0, 2, true, true}, {GpuEnumValue(BufferFormat::k8_8UInt), vk::Format::eR8G8Uint, 2, 0, 2, true, true},
{GpuEnumValue(BufferFormat::k8_8SInt), VK_FORMAT_R8G8_SINT, 2, 0, 2, false, false}, {GpuEnumValue(BufferFormat::k8_8SInt), vk::Format::eR8G8Sint, 2, 0, 2, false, false},
{GpuEnumValue(BufferFormat::k32UInt), VK_FORMAT_R32_UINT, 4, 0, 4, true, true}, {GpuEnumValue(BufferFormat::k32UInt), vk::Format::eR32Uint, 4, 0, 4, true, true},
{GpuEnumValue(BufferFormat::k32SInt), VK_FORMAT_R32_SINT, 4, 0, 4, false, false}, {GpuEnumValue(BufferFormat::k32SInt), vk::Format::eR32Sint, 4, 0, 4, false, false},
{GpuEnumValue(BufferFormat::k32Float), VK_FORMAT_R32_SFLOAT, 4, 0, 4, true, false}, {GpuEnumValue(BufferFormat::k32Float), vk::Format::eR32Sfloat, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k16_16UNorm), VK_FORMAT_R16G16_UNORM, 4, 0, 4, true, false}, {GpuEnumValue(BufferFormat::k16_16UNorm), vk::Format::eR16G16Unorm, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k16_16SNorm), VK_FORMAT_R16G16_SNORM, 4, 0, 4, true, false}, {GpuEnumValue(BufferFormat::k16_16SNorm), vk::Format::eR16G16Snorm, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k16_16UInt), VK_FORMAT_R16G16_UINT, 4, 0, 4, true, true}, {GpuEnumValue(BufferFormat::k16_16UInt), vk::Format::eR16G16Uint, 4, 0, 4, true, true},
{GpuEnumValue(BufferFormat::k16_16SInt), VK_FORMAT_R16G16_SINT, 4, 0, 4, false, false}, {GpuEnumValue(BufferFormat::k16_16SInt), vk::Format::eR16G16Sint, 4, 0, 4, false, false},
{GpuEnumValue(BufferFormat::k16_16Float), VK_FORMAT_R16G16_SFLOAT, 4, 0, 4, true, false}, {GpuEnumValue(BufferFormat::k16_16Float), vk::Format::eR16G16Sfloat, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k11_11_10Float), VK_FORMAT_B10G11R11_UFLOAT_PACK32, 4, 0, 4, true, {GpuEnumValue(BufferFormat::k11_11_10Float), vk::Format::eB10G11R11UfloatPack32, 4, 0, 4, true,
false}, false},
{GpuEnumValue(BufferFormat::k10_10_10_2UNorm), VK_FORMAT_A2B10G10R10_UNORM_PACK32, 4, 0, 4, {GpuEnumValue(BufferFormat::k10_10_10_2UNorm), vk::Format::eA2B10G10R10UnormPack32, 4, 0, 4,
true, false}, true, false},
{GpuEnumValue(BufferFormat::k8_8_8_8UNorm), VK_FORMAT_R8G8B8A8_UNORM, 4, 0, 4, true, false}, {GpuEnumValue(BufferFormat::k8_8_8_8UNorm), vk::Format::eR8G8B8A8Unorm, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k8_8_8_8SNorm), VK_FORMAT_R8G8B8A8_SNORM, 4, 0, 4, true, false}, {GpuEnumValue(BufferFormat::k8_8_8_8SNorm), vk::Format::eR8G8B8A8Snorm, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k8_8_8_8UInt), VK_FORMAT_R8G8B8A8_UINT, 4, 0, 4, true, true}, {GpuEnumValue(BufferFormat::k8_8_8_8UInt), vk::Format::eR8G8B8A8Uint, 4, 0, 4, true, true},
{GpuEnumValue(BufferFormat::k8_8_8_8SInt), VK_FORMAT_R8G8B8A8_SINT, 4, 0, 4, false, false}, {GpuEnumValue(BufferFormat::k8_8_8_8SInt), vk::Format::eR8G8B8A8Sint, 4, 0, 4, false, false},
{GpuEnumValue(BufferFormat::k32_32UInt), VK_FORMAT_R32G32_UINT, 8, 0, 8, true, true}, {GpuEnumValue(BufferFormat::k32_32UInt), vk::Format::eR32G32Uint, 8, 0, 8, true, true},
{GpuEnumValue(BufferFormat::k32_32SInt), VK_FORMAT_R32G32_SINT, 8, 0, 8, false, false}, {GpuEnumValue(BufferFormat::k32_32SInt), vk::Format::eR32G32Sint, 8, 0, 8, false, false},
{GpuEnumValue(BufferFormat::k32_32Float), VK_FORMAT_R32G32_SFLOAT, 8, 0, 8, true, false}, {GpuEnumValue(BufferFormat::k32_32Float), vk::Format::eR32G32Sfloat, 8, 0, 8, true, false},
{GpuEnumValue(BufferFormat::k16_16_16_16UNorm), VK_FORMAT_R16G16B16A16_UNORM, 8, 0, 8, true, {GpuEnumValue(BufferFormat::k16_16_16_16UNorm), vk::Format::eR16G16B16A16Unorm, 8, 0, 8, true,
false}, false},
{GpuEnumValue(BufferFormat::k16_16_16_16SNorm), VK_FORMAT_R16G16B16A16_SNORM, 8, 0, 8, true, {GpuEnumValue(BufferFormat::k16_16_16_16SNorm), vk::Format::eR16G16B16A16Snorm, 8, 0, 8, true,
false}, false},
{GpuEnumValue(BufferFormat::k16_16_16_16UInt), VK_FORMAT_R16G16B16A16_UINT, 8, 0, 8, true, {GpuEnumValue(BufferFormat::k16_16_16_16UInt), vk::Format::eR16G16B16A16Uint, 8, 0, 8, true,
true}, true},
{GpuEnumValue(BufferFormat::k16_16_16_16SInt), VK_FORMAT_R16G16B16A16_SINT, 8, 0, 8, false, {GpuEnumValue(BufferFormat::k16_16_16_16SInt), vk::Format::eR16G16B16A16Sint, 8, 0, 8, false,
false}, false},
{GpuEnumValue(BufferFormat::k16_16_16_16Float), VK_FORMAT_R16G16B16A16_SFLOAT, 8, 0, 8, true, {GpuEnumValue(BufferFormat::k16_16_16_16Float), vk::Format::eR16G16B16A16Sfloat, 8, 0, 8, true,
false}, false},
{GpuEnumValue(BufferFormat::k32_32_32UInt), VK_FORMAT_R32G32B32_UINT, 12, 0, 12, true, true}, {GpuEnumValue(BufferFormat::k32_32_32UInt), vk::Format::eR32G32B32Uint, 12, 0, 12, true, true},
{GpuEnumValue(BufferFormat::k32_32_32SInt), VK_FORMAT_R32G32B32_SINT, 12, 0, 12, false, false}, {GpuEnumValue(BufferFormat::k32_32_32SInt), vk::Format::eR32G32B32Sint, 12, 0, 12, false,
{GpuEnumValue(BufferFormat::k32_32_32Float), VK_FORMAT_R32G32B32_SFLOAT, 12, 0, 12, true,
false}, false},
{GpuEnumValue(BufferFormat::k32_32_32_32UInt), VK_FORMAT_R32G32B32A32_UINT, 16, 0, 16, true, {GpuEnumValue(BufferFormat::k32_32_32Float), vk::Format::eR32G32B32Sfloat, 12, 0, 12, true,
false},
{GpuEnumValue(BufferFormat::k32_32_32_32UInt), vk::Format::eR32G32B32A32Uint, 16, 0, 16, true,
true}, true},
{GpuEnumValue(BufferFormat::k32_32_32_32SInt), VK_FORMAT_R32G32B32A32_SINT, 16, 0, 16, false, {GpuEnumValue(BufferFormat::k32_32_32_32SInt), vk::Format::eR32G32B32A32Sint, 16, 0, 16, false,
false}, false},
{GpuEnumValue(BufferFormat::k32_32_32_32Float), VK_FORMAT_R32G32B32A32_SFLOAT, 16, 0, 16, true, {GpuEnumValue(BufferFormat::k32_32_32_32Float), vk::Format::eR32G32B32A32Sfloat, 16, 0, 16,
true, false},
{GpuEnumValue(BufferFormat::k8_8_8_8Srgb), vk::Format::eR8G8B8A8Srgb, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k9_9_9_5Float), vk::Format::eE5B9G9R9UfloatPack32, 4, 0, 0, true,
false}, false},
{GpuEnumValue(BufferFormat::k8_8_8_8Srgb), VK_FORMAT_R8G8B8A8_SRGB, 4, 0, 4, true, false}, {GpuEnumValue(BufferFormat::k5_6_5UNorm), vk::Format::eB5G6R5UnormPack16, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k9_9_9_5Float), VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 4, 0, 0, true, {GpuEnumValue(BufferFormat::k5_5_5_1UNorm), vk::Format::eR5G5B5A1UnormPack16, 2, 0, 2, true,
false}, false},
{GpuEnumValue(BufferFormat::k5_6_5UNorm), VK_FORMAT_B5G6R5_UNORM_PACK16, 2, 0, 2, true, false}, {GpuEnumValue(BufferFormat::k4_4_4_4UNorm), vk::Format::eR4G4B4A4UnormPack16, 2, 0, 2, true,
{GpuEnumValue(BufferFormat::k5_5_5_1UNorm), VK_FORMAT_R5G5B5A1_UNORM_PACK16, 2, 0, 2, true,
false}, false},
{GpuEnumValue(BufferFormat::k4_4_4_4UNorm), VK_FORMAT_R4G4B4A4_UNORM_PACK16, 2, 0, 2, true, {GpuEnumValue(BufferFormat::kFmask8_S4_F4), vk::Format::eR32Sfloat, 1, 0, 1, true, false},
false}, {GpuEnumValue(BufferFormat::kBc1UNorm), vk::Format::eBc1RgbaUnormBlock, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kFmask8_S4_F4), VK_FORMAT_R32_SFLOAT, 1, 0, 1, true, false}, {GpuEnumValue(BufferFormat::kBc1Srgb), vk::Format::eBc1RgbaSrgbBlock, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc1UNorm), VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 0, 8, 0, true, false}, {GpuEnumValue(BufferFormat::kBc2UNorm), vk::Format::eBc2UnormBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc1Srgb), VK_FORMAT_BC1_RGBA_SRGB_BLOCK, 0, 8, 0, true, false}, {GpuEnumValue(BufferFormat::kBc2Srgb), vk::Format::eBc2SrgbBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc2UNorm), VK_FORMAT_BC2_UNORM_BLOCK, 0, 16, 0, true, false}, {GpuEnumValue(BufferFormat::kBc3UNorm), vk::Format::eBc3UnormBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc2Srgb), VK_FORMAT_BC2_SRGB_BLOCK, 0, 16, 0, true, false}, {GpuEnumValue(BufferFormat::kBc3Srgb), vk::Format::eBc3SrgbBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc3UNorm), VK_FORMAT_BC3_UNORM_BLOCK, 0, 16, 0, true, false}, {GpuEnumValue(BufferFormat::kBc4UNorm), vk::Format::eBc4UnormBlock, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc3Srgb), VK_FORMAT_BC3_SRGB_BLOCK, 0, 16, 0, true, false}, {GpuEnumValue(BufferFormat::kBc4SNorm), vk::Format::eBc4SnormBlock, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc4UNorm), VK_FORMAT_BC4_UNORM_BLOCK, 0, 8, 0, true, false}, {GpuEnumValue(BufferFormat::kBc5UNorm), vk::Format::eBc5UnormBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc4SNorm), VK_FORMAT_BC4_SNORM_BLOCK, 0, 8, 0, true, false}, {GpuEnumValue(BufferFormat::kBc5SNorm), vk::Format::eBc5SnormBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc5UNorm), VK_FORMAT_BC5_UNORM_BLOCK, 0, 16, 0, true, false}, {GpuEnumValue(BufferFormat::kBc6UFloat), vk::Format::eBc6HUfloatBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc5SNorm), VK_FORMAT_BC5_SNORM_BLOCK, 0, 16, 0, true, false}, {GpuEnumValue(BufferFormat::kBc6SFloat), vk::Format::eBc6HSfloatBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc6UFloat), VK_FORMAT_BC6H_UFLOAT_BLOCK, 0, 16, 0, true, false}, {GpuEnumValue(BufferFormat::kBc7UNorm), vk::Format::eBc7UnormBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc6SFloat), VK_FORMAT_BC6H_SFLOAT_BLOCK, 0, 16, 0, true, false}, {GpuEnumValue(BufferFormat::kBc7Srgb), vk::Format::eBc7SrgbBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc7UNorm), VK_FORMAT_BC7_UNORM_BLOCK, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc7Srgb), VK_FORMAT_BC7_SRGB_BLOCK, 0, 16, 0, true, false},
}; };
constexpr auto MakeFormatInfoLookup() { constexpr auto MakeFormatInfoLookup() {
@@ -105,9 +106,9 @@ const FormatInfo* FindFormatInfo(uint32_t format) {
return format < kFormatInfoLookup.size() ? kFormatInfoLookup[format] : nullptr; return format < kFormatInfoLookup.size() ? kFormatInfoLookup[format] : nullptr;
} }
VkFormat SurfaceFormat(uint32_t format) { vk::Format SurfaceFormat(uint32_t format) {
const auto* info = FindFormatInfo(format); const auto* info = FindFormatInfo(format);
return info != nullptr ? info->vk_format : VK_FORMAT_UNDEFINED; return info != nullptr ? info->vk_format : vk::Format::eUndefined;
} }
uint32_t NumBytesPerElement(uint32_t format) { uint32_t NumBytesPerElement(uint32_t format) {
+9 -9
View File
@@ -2,25 +2,25 @@
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GUEST_GPU_GPU_FORMAT_H_ #define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GUEST_GPU_GPU_FORMAT_H_
#include "common/common.h" #include "common/common.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <span> #include <span>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics::Prospero { namespace Libs::Graphics::Prospero {
struct FormatInfo { struct FormatInfo {
uint32_t format = 0; uint32_t format = 0;
VkFormat vk_format = VK_FORMAT_UNDEFINED; vk::Format vk_format = vk::Format::eUndefined;
uint32_t bytes_per_element = 0; uint32_t bytes_per_element = 0;
uint32_t block_compressed_bytes_per_block = 0; uint32_t block_compressed_bytes_per_block = 0;
uint32_t render_target_bytes_per_element = 0; uint32_t render_target_bytes_per_element = 0;
bool supported_sampled_texture_format = false; bool supported_sampled_texture_format = false;
bool unsigned_integer_texture_format = false; bool unsigned_integer_texture_format = false;
}; };
std::span<const FormatInfo> Formats(); std::span<const FormatInfo> Formats();
const FormatInfo* FindFormatInfo(uint32_t format); const FormatInfo* FindFormatInfo(uint32_t format);
VkFormat SurfaceFormat(uint32_t format); vk::Format SurfaceFormat(uint32_t format);
uint32_t NumBytesPerElement(uint32_t format); uint32_t NumBytesPerElement(uint32_t format);
uint32_t BlockCompressedBytesPerBlock(uint32_t format); uint32_t BlockCompressedBytesPerBlock(uint32_t format);
uint32_t RenderTargetBytesPerElement(uint32_t format); uint32_t RenderTargetBytesPerElement(uint32_t format);
+45 -45
View File
@@ -4,13 +4,13 @@
#include "common/abi.h" #include "common/abi.h"
#include "common/common.h" #include "common/common.h"
#include "common/threads.h" #include "common/threads.h"
#include "graphics/host_gpu/vulkanCommon.h" // IWYU pragma: export
#include "graphics/host_gpu/vulkanInstance.h" #include "graphics/host_gpu/vulkanInstance.h"
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <vector> #include <vector>
#include <vk_mem_alloc.h> #include <vk_mem_alloc.h>
#include <vulkan/vulkan_core.h> // IWYU pragma: export
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -19,26 +19,26 @@ class CommandBuffer;
struct VulkanSwapchain { struct VulkanSwapchain {
~VulkanSwapchain(); ~VulkanSwapchain();
VkSwapchainKHR swapchain = nullptr; vk::SwapchainKHR swapchain = nullptr;
VkFormat swapchain_format = VK_FORMAT_UNDEFINED; vk::Format swapchain_format = vk::Format::eUndefined;
VkExtent2D swapchain_extent = {}; vk::Extent2D swapchain_extent = {};
std::unique_ptr<VkImage[]> swapchain_images; std::unique_ptr<vk::Image[]> swapchain_images;
std::unique_ptr<VkImageView[]> swapchain_image_views; std::unique_ptr<vk::ImageView[]> swapchain_image_views;
uint32_t swapchain_images_count = 0; uint32_t swapchain_images_count = 0;
std::unique_ptr<VkSemaphore[]> image_acquired_semaphores; std::unique_ptr<vk::Semaphore[]> image_acquired_semaphores;
std::unique_ptr<VkSemaphore[]> render_complete_semaphores; std::unique_ptr<vk::Semaphore[]> render_complete_semaphores;
uint32_t current_index = 0; uint32_t current_index = 0;
uint32_t present_frame = 0; uint32_t present_frame = 0;
}; };
struct VulkanCommandPool { struct VulkanCommandPool {
Common::Mutex mutex; Common::Mutex mutex;
VkCommandPool pool = nullptr; vk::CommandPool pool = nullptr;
std::unique_ptr<VkCommandBuffer[]> buffers; std::unique_ptr<vk::CommandBuffer[]> buffers;
std::unique_ptr<VkFence[]> fences; std::unique_ptr<vk::Fence[]> fences;
std::unique_ptr<VkSemaphore[]> semaphores; std::unique_ptr<vk::Semaphore[]> semaphores;
std::unique_ptr<bool[]> busy; std::unique_ptr<bool[]> busy;
uint32_t buffers_count = 0; uint32_t buffers_count = 0;
}; };
struct GraphicContext: public VulkanInstance { struct GraphicContext: public VulkanInstance {
@@ -47,14 +47,14 @@ struct GraphicContext: public VulkanInstance {
}; };
struct VulkanMemory { struct VulkanMemory {
VkMemoryRequirements requirements = {}; vk::MemoryRequirements requirements = {};
VkMemoryPropertyFlags property = 0; vk::MemoryPropertyFlags property = {};
VkDeviceMemory memory = nullptr; vk::DeviceMemory memory = nullptr;
VmaAllocation allocation = nullptr; VmaAllocation allocation = nullptr;
VmaAllocationInfo allocation_info = {}; VmaAllocationInfo allocation_info = {};
VkDeviceSize offset = 0; vk::DeviceSize offset = 0;
uint32_t type = 0; uint32_t type = 0;
uint64_t unique_id = 0; uint64_t unique_id = 0;
}; };
enum class VulkanImageType { enum class VulkanImageType {
@@ -67,22 +67,22 @@ enum class VulkanImageType {
}; };
struct ImageViewInfo { struct ImageViewInfo {
VkFormat format = VK_FORMAT_UNDEFINED; vk::Format format = vk::Format::eUndefined;
VkImageViewType type = VK_IMAGE_VIEW_TYPE_2D; vk::ImageViewType type = vk::ImageViewType::e2D;
VkImageAspectFlags aspect = 0; vk::ImageAspectFlags aspect = {};
uint32_t base_level = 0; uint32_t base_level = 0;
uint32_t level_count = 0; uint32_t level_count = 0;
uint32_t base_layer = 0; uint32_t base_layer = 0;
uint32_t layer_count = 1; uint32_t layer_count = 1;
uint32_t swizzle = 0; uint32_t swizzle = 0;
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT; vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eSampled;
bool operator==(const ImageViewInfo&) const = default; bool operator==(const ImageViewInfo&) const = default;
}; };
struct CachedImageView { struct CachedImageView {
ImageViewInfo info; ImageViewInfo info;
VkImageView view = nullptr; vk::ImageView view = nullptr;
}; };
struct ImageViewCache { struct ImageViewCache {
@@ -104,14 +104,14 @@ struct VulkanImage {
KYTY_CLASS_NO_COPY(VulkanImage); KYTY_CLASS_NO_COPY(VulkanImage);
VulkanImageType type = VulkanImageType::Unknown; VulkanImageType type = VulkanImageType::Unknown;
VkFormat format = VK_FORMAT_UNDEFINED; vk::Format format = vk::Format::eUndefined;
VkExtent2D extent = {}; vk::Extent2D extent = {};
uint32_t guest_pitch = 0; uint32_t guest_pitch = 0;
uint32_t layers = 1; uint32_t layers = 1;
uint32_t mip_levels = 1; uint32_t mip_levels = 1;
VkImage image = nullptr; vk::Image image = nullptr;
VkImageView image_view[VIEW_MAX] = {}; vk::ImageView image_view[VIEW_MAX] = {};
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; vk::ImageLayout layout = vk::ImageLayout::eUndefined;
Graphics::VulkanMemory memory; Graphics::VulkanMemory memory;
ImageViewCache view_cache; ImageViewCache view_cache;
}; };
@@ -142,10 +142,10 @@ struct RenderTextureVulkanImage: public VulkanImage {
}; };
struct VulkanBuffer { struct VulkanBuffer {
VkBuffer buffer = nullptr; vk::Buffer buffer = nullptr;
VulkanMemory memory; VulkanMemory memory;
VkBufferUsageFlags usage = 0; vk::BufferUsageFlags usage = {};
uint64_t buffer_size = 0; uint64_t buffer_size = 0;
}; };
struct StorageVulkanBuffer: public VulkanBuffer {}; struct StorageVulkanBuffer: public VulkanBuffer {};
+14 -14
View File
@@ -25,12 +25,12 @@ struct LabelCallbacks {
}; };
struct LabelEvent final { struct LabelEvent final {
VkDevice device = nullptr; vk::Device device = nullptr;
VkEvent event = nullptr; vk::Event event = nullptr;
~LabelEvent() { ~LabelEvent() {
if (event != nullptr) { if (event != nullptr) {
vkDestroyEvent(device, event, nullptr); device.destroyEvent(event, nullptr);
} }
} }
}; };
@@ -41,7 +41,7 @@ struct LabelSubmission {
}; };
struct Label { struct Label {
VkDevice device = nullptr; vk::Device device = nullptr;
LabelStatus status = LabelStatus::New; LabelStatus status = LabelStatus::New;
LabelCallbacks callbacks; LabelCallbacks callbacks;
std::vector<LabelSubmission> submissions; std::vector<LabelSubmission> submissions;
@@ -115,14 +115,14 @@ void LabelManager::ThreadRun(void* data) {
it->completion->event == nullptr) { it->completion->event == nullptr) {
EXIT("GPU label submission has no completion event\n"); EXIT("GPU label submission has no completion event\n");
} }
const auto status = vkGetEventStatus(it->completion->device, it->completion->event); const auto status = it->completion->device.getEventStatus(it->completion->event);
switch (status) { switch (status) {
case VK_EVENT_SET: case vk::Result::eEventSet:
fired_labels.push_back(it->callbacks); fired_labels.push_back(it->callbacks);
finished_submissions.push_back(*it); finished_submissions.push_back(*it);
it = label->submissions.erase(it); it = label->submissions.erase(it);
break; break;
case VK_EVENT_RESET: ++it; break; case vk::Result::eEventReset: ++it; break;
default: EXIT("vkGetEventStatus returned an unexpected result\n"); default: EXIT("vkGetEventStatus returned an unexpected result\n");
} }
} }
@@ -270,24 +270,24 @@ void LabelManager::Set(CommandBuffer* buffer, Label* label) {
submission.completion = std::make_shared<LabelEvent>(); submission.completion = std::make_shared<LabelEvent>();
submission.completion->device = label->device; submission.completion->device = label->device;
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; auto vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
EXIT_NOT_IMPLEMENTED(vk_buffer == nullptr); EXIT_NOT_IMPLEMENTED(vk_buffer == nullptr);
VkEventCreateInfo create_info {}; vk::EventCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; create_info.sType = vk::StructureType::eEventCreateInfo;
create_info.pNext = nullptr; create_info.pNext = nullptr;
create_info.flags = 0; create_info.flags = {};
vkCreateEvent(label->device, &create_info, nullptr, &submission.completion->event); label->device.createEvent(&create_info, nullptr, &submission.completion->event);
EXIT_NOT_IMPLEMENTED(submission.completion->event == nullptr); EXIT_NOT_IMPLEMENTED(submission.completion->event == nullptr);
buffer->RetainResourceUntilFence(submission.completion); buffer->RetainResourceUntilFence(submission.completion);
// Labels can be reused before an earlier end-of-pipe event has been // Labels can be reused before an earlier end-of-pipe event has been
// observed by the polling thread. Capture a separate Vulkan event and // observed by the polling thread. Capture a separate Vulkan event and
// callback snapshot for each set so older writes are not lost. // callback snapshot for each set so older writes are not lost.
vkResetEvent(label->device, submission.completion->event); label->device.resetEvent(submission.completion->event);
vkCmdSetEvent(vk_buffer, submission.completion->event, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); vk_buffer.setEvent(submission.completion->event, vk::PipelineStageFlagBits::eBottomOfPipe);
label->submissions.push_back(submission); label->submissions.push_back(submission);
+135 -128
View File
@@ -28,115 +28,115 @@ RenderTargetFormatInfo TextureGetRenderTargetFormat(uint32_t raw_layout, uint32_
if (layout == Prospero::ChannelLayout::k8 && type == Prospero::ChannelType::kUNorm && if (layout == Prospero::ChannelLayout::k8 && type == Prospero::ChannelType::kUNorm &&
raw_order <= Prospero::GpuEnumValue(Prospero::ChannelOrder::kAltReversed)) { raw_order <= Prospero::GpuEnumValue(Prospero::ChannelOrder::kAltReversed)) {
return {VK_FORMAT_R8_UNORM, 1}; return {vk::Format::eR8Unorm, 1};
} }
if (is(Prospero::ChannelLayout::k8_8, Prospero::ChannelType::kUNorm, if (is(Prospero::ChannelLayout::k8_8, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R8G8_UNORM, 2}; return {vk::Format::eR8G8Unorm, 2};
} }
if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kUNorm, if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R8G8B8A8_UNORM, 4}; return {vk::Format::eR8G8B8A8Unorm, 4};
} }
if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kSNorm, if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kSNorm,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R8G8B8A8_SNORM, 4}; return {vk::Format::eR8G8B8A8Snorm, 4};
} }
if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kSrgb, if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kSrgb,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R8G8B8A8_SRGB, 4}; return {vk::Format::eR8G8B8A8Srgb, 4};
} }
if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kUNorm, if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kAlt)) { Prospero::ChannelOrder::kAlt)) {
return {VK_FORMAT_B8G8R8A8_UNORM, 4}; return {vk::Format::eB8G8R8A8Unorm, 4};
} }
if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kSNorm, if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kSNorm,
Prospero::ChannelOrder::kAlt)) { Prospero::ChannelOrder::kAlt)) {
return {VK_FORMAT_B8G8R8A8_SNORM, 4}; return {vk::Format::eB8G8R8A8Snorm, 4};
} }
if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kSrgb, if (is(Prospero::ChannelLayout::k8_8_8_8, Prospero::ChannelType::kSrgb,
Prospero::ChannelOrder::kAlt)) { Prospero::ChannelOrder::kAlt)) {
return {VK_FORMAT_B8G8R8A8_SRGB, 4}; return {vk::Format::eB8G8R8A8Srgb, 4};
} }
if (is(Prospero::ChannelLayout::k5_5_5_1, Prospero::ChannelType::kUNorm, if (is(Prospero::ChannelLayout::k5_5_5_1, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R5G5B5A1_UNORM_PACK16, 2}; return {vk::Format::eR5G5B5A1UnormPack16, 2};
} }
if (is(Prospero::ChannelLayout::k4_4_4_4, Prospero::ChannelType::kUNorm, if (is(Prospero::ChannelLayout::k4_4_4_4, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kReversed)) { Prospero::ChannelOrder::kReversed)) {
return {VK_FORMAT_B4G4R4A4_UNORM_PACK16, 2}; return {vk::Format::eB4G4R4A4UnormPack16, 2};
} }
if (is(Prospero::ChannelLayout::k10_10_10_2, Prospero::ChannelType::kUNorm, if (is(Prospero::ChannelLayout::k10_10_10_2, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_A2B10G10R10_UNORM_PACK32, 4}; return {vk::Format::eA2B10G10R10UnormPack32, 4};
} }
if (is(Prospero::ChannelLayout::k10_10_10_2, Prospero::ChannelType::kUNorm, if (is(Prospero::ChannelLayout::k10_10_10_2, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kAlt)) { Prospero::ChannelOrder::kAlt)) {
return {VK_FORMAT_A2R10G10B10_UNORM_PACK32, 4}; return {vk::Format::eA2R10G10B10UnormPack32, 4};
} }
if (is(Prospero::ChannelLayout::k11_11_10, Prospero::ChannelType::kFloat, if (is(Prospero::ChannelLayout::k11_11_10, Prospero::ChannelType::kFloat,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_B10G11R11_UFLOAT_PACK32, 4}; return {vk::Format::eB10G11R11UfloatPack32, 4};
} }
if (is(Prospero::ChannelLayout::k16, Prospero::ChannelType::kUNorm, if (is(Prospero::ChannelLayout::k16, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16_UNORM, 2}; return {vk::Format::eR16Unorm, 2};
} }
if (is(Prospero::ChannelLayout::k16, Prospero::ChannelType::kUInt, if (is(Prospero::ChannelLayout::k16, Prospero::ChannelType::kUInt,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16_UINT, 2}; return {vk::Format::eR16Uint, 2};
} }
if (is(Prospero::ChannelLayout::k16, Prospero::ChannelType::kFloat, if (is(Prospero::ChannelLayout::k16, Prospero::ChannelType::kFloat,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16_SFLOAT, 2}; return {vk::Format::eR16Sfloat, 2};
} }
if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kUNorm, if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16G16_UNORM, 4}; return {vk::Format::eR16G16Unorm, 4};
} }
if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kSNorm, if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kSNorm,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16G16_SNORM, 4}; return {vk::Format::eR16G16Snorm, 4};
} }
if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kUInt, if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kUInt,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16G16_UINT, 4}; return {vk::Format::eR16G16Uint, 4};
} }
if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kFloat, if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kFloat,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16G16_SFLOAT, 4}; return {vk::Format::eR16G16Sfloat, 4};
} }
if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kUNorm, if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16G16B16A16_UNORM, 8}; return {vk::Format::eR16G16B16A16Unorm, 8};
} }
if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kFloat, if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kFloat,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16G16B16A16_SFLOAT, 8}; return {vk::Format::eR16G16B16A16Sfloat, 8};
} }
if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kFloat, if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kFloat,
Prospero::ChannelOrder::kAlt)) { Prospero::ChannelOrder::kAlt)) {
return {VK_FORMAT_R16G16B16A16_SFLOAT, 8, Prospero::ColorMappingBgra}; return {vk::Format::eR16G16B16A16Sfloat, 8, Prospero::ColorMappingBgra};
} }
if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kFloat, if (is(Prospero::ChannelLayout::k16_16_16_16, Prospero::ChannelType::kFloat,
Prospero::ChannelOrder::kReversed)) { Prospero::ChannelOrder::kReversed)) {
return {VK_FORMAT_R16G16B16A16_SFLOAT, 8, Prospero::ColorMappingAbgr}; return {vk::Format::eR16G16B16A16Sfloat, 8, Prospero::ColorMappingAbgr};
} }
if (is(Prospero::ChannelLayout::k32, Prospero::ChannelType::kFloat, if (is(Prospero::ChannelLayout::k32, Prospero::ChannelType::kFloat,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R32_SFLOAT, 4}; return {vk::Format::eR32Sfloat, 4};
} }
if (is(Prospero::ChannelLayout::k32_32, Prospero::ChannelType::kUInt, if (is(Prospero::ChannelLayout::k32_32, Prospero::ChannelType::kUInt,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R32G32_UINT, 8}; return {vk::Format::eR32G32Uint, 8};
} }
if (is(Prospero::ChannelLayout::k32_32, Prospero::ChannelType::kFloat, if (is(Prospero::ChannelLayout::k32_32, Prospero::ChannelType::kFloat,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R32G32_SFLOAT, 8}; return {vk::Format::eR32G32Sfloat, 8};
} }
if (is(Prospero::ChannelLayout::k32_32_32_32, Prospero::ChannelType::kFloat, if (is(Prospero::ChannelLayout::k32_32_32_32, Prospero::ChannelType::kFloat,
Prospero::ChannelOrder::kStandard)) { Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R32G32B32A32_SFLOAT, 16}; return {vk::Format::eR32G32B32A32Sfloat, 16};
} }
EXIT("unsupported render-target format combination: layout=%u type=%u order=%u\n", raw_layout, EXIT("unsupported render-target format combination: layout=%u type=%u order=%u\n", raw_layout,
raw_type, raw_order); raw_type, raw_order);
@@ -209,7 +209,7 @@ void TextureCopyBufferBytes(GraphicContext* ctx, VulkanBuffer* src_buffer,
return; return;
} }
if ((src_buffer->memory.property & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) { if (src_buffer->memory.property & vk::MemoryPropertyFlagBits::eHostVisible) {
void* data = nullptr; void* data = nullptr;
VulkanMapMemory(ctx, &src_buffer->memory, &data); VulkanMapMemory(ctx, &src_buffer->memory, &data);
std::memcpy(dst->Data(), static_cast<const uint8_t*>(data) + src_buffer_offset, available); std::memcpy(dst->Data(), static_cast<const uint8_t*>(data) + src_buffer_offset, available);
@@ -218,10 +218,10 @@ void TextureCopyBufferBytes(GraphicContext* ctx, VulkanBuffer* src_buffer,
} }
VulkanBuffer readback {}; VulkanBuffer readback {};
readback.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; readback.usage = vk::BufferUsageFlagBits::eTransferDst;
readback.memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) | readback.memory.property = vk::MemoryPropertyFlagBits::eHostVisible |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | vk::MemoryPropertyFlagBits::eHostCoherent |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT; vk::MemoryPropertyFlagBits::eHostCached;
VulkanCreateBuffer(ctx, (src_buffer_offset + available + 3u) & ~uint64_t {3}, &readback); VulkanCreateBuffer(ctx, (src_buffer_offset + available + 3u) & ~uint64_t {3}, &readback);
UtilCopyBuffer(src_buffer, &readback, src_buffer_offset + available); UtilCopyBuffer(src_buffer, &readback, src_buffer_offset + available);
@@ -233,25 +233,25 @@ void TextureCopyBufferBytes(GraphicContext* ctx, VulkanBuffer* src_buffer,
VulkanDeleteBuffer(ctx, &readback); VulkanDeleteBuffer(ctx, &readback);
} }
VkComponentSwizzle TextureGetComponentSwizzle(uint8_t s) { vk::ComponentSwizzle TextureGetComponentSwizzle(uint8_t s) {
switch (static_cast<Prospero::CompSwizzle>(s)) { switch (static_cast<Prospero::CompSwizzle>(s)) {
case Prospero::CompSwizzle::kZero: return VK_COMPONENT_SWIZZLE_ZERO; case Prospero::CompSwizzle::kZero: return vk::ComponentSwizzle::eZero;
case Prospero::CompSwizzle::kOne: return VK_COMPONENT_SWIZZLE_ONE; case Prospero::CompSwizzle::kOne: return vk::ComponentSwizzle::eOne;
case Prospero::CompSwizzle::kRed: return VK_COMPONENT_SWIZZLE_R; case Prospero::CompSwizzle::kRed: return vk::ComponentSwizzle::eR;
case Prospero::CompSwizzle::kGreen: return VK_COMPONENT_SWIZZLE_G; case Prospero::CompSwizzle::kGreen: return vk::ComponentSwizzle::eG;
case Prospero::CompSwizzle::kBlue: return VK_COMPONENT_SWIZZLE_B; case Prospero::CompSwizzle::kBlue: return vk::ComponentSwizzle::eB;
case Prospero::CompSwizzle::kAlpha: return VK_COMPONENT_SWIZZLE_A; case Prospero::CompSwizzle::kAlpha: return vk::ComponentSwizzle::eA;
default: EXIT("unknown swizzle: %d\n", static_cast<int>(s)); default: EXIT("unknown swizzle: %d\n", static_cast<int>(s));
} }
return VK_COMPONENT_SWIZZLE_IDENTITY; return vk::ComponentSwizzle::eIdentity;
} }
static uint32_t TextureGetDstSel(uint32_t swizzle, uint32_t channel) { static uint32_t TextureGetDstSel(uint32_t swizzle, uint32_t channel) {
return (swizzle >> (channel * 3u)) & 0x7u; return (swizzle >> (channel * 3u)) & 0x7u;
} }
VkComponentMapping TextureGetComponentMapping(uint32_t swizzle) { vk::ComponentMapping TextureGetComponentMapping(uint32_t swizzle) {
VkComponentMapping components {}; vk::ComponentMapping components {};
components.r = TextureGetComponentSwizzle(static_cast<uint8_t>(TextureGetDstSel(swizzle, 0))); components.r = TextureGetComponentSwizzle(static_cast<uint8_t>(TextureGetDstSel(swizzle, 0)));
components.g = TextureGetComponentSwizzle(static_cast<uint8_t>(TextureGetDstSel(swizzle, 1))); components.g = TextureGetComponentSwizzle(static_cast<uint8_t>(TextureGetDstSel(swizzle, 1)));
components.b = TextureGetComponentSwizzle(static_cast<uint8_t>(TextureGetDstSel(swizzle, 2))); components.b = TextureGetComponentSwizzle(static_cast<uint8_t>(TextureGetDstSel(swizzle, 2)));
@@ -259,57 +259,63 @@ VkComponentMapping TextureGetComponentMapping(uint32_t swizzle) {
return components; return components;
} }
bool TextureCheckFormat(GraphicContext* ctx, VkImageCreateInfo* image_info) { bool TextureCheckFormat(GraphicContext* ctx, vk::ImageCreateInfo* image_info) {
VkImageFormatProperties props {}; vk::ImageFormatProperties props {};
if (ctx->GetImageFormatProperties(image_info->format, image_info->imageType, image_info->tiling, if (ctx->GetImageFormatProperties(image_info->format, image_info->imageType, image_info->tiling,
image_info->usage, image_info->flags, image_info->usage, image_info->flags,
&props) == VK_ERROR_FORMAT_NOT_SUPPORTED) { &props) == vk::Result::eErrorFormatNotSupported) {
auto apply_fallback = [&](VkFormat replacement, const char* message) { auto apply_fallback = [&](vk::Format replacement, const char* message) {
image_info->format = replacement; image_info->format = replacement;
const bool result = TextureCheckFormat(ctx, image_info); const bool result = TextureCheckFormat(ctx, image_info);
LOGF("%s [%s]\n", message, (!result ? "FAIL" : "SUCCESS")); LOGF("%s [%s]\n", message, (!result ? "FAIL" : "SUCCESS"));
return result; return result;
}; };
if (image_info->format == VK_FORMAT_R8G8B8A8_SRGB) { if (image_info->format == vk::Format::eR8G8B8A8Srgb) {
// TODO() convert SRGB -> LINEAR in shader // TODO() convert SRGB -> LINEAR in shader
return apply_fallback(VK_FORMAT_R8G8B8A8_UNORM, return apply_fallback(
"replace VK_FORMAT_R8G8B8A8_SRGB => VK_FORMAT_R8G8B8A8_UNORM"); vk::Format::eR8G8B8A8Unorm,
"replace vk::Format::eR8G8B8A8Srgb => vk::Format::eR8G8B8A8Unorm");
} }
if (image_info->format == VK_FORMAT_B8G8R8A8_SRGB) { if (image_info->format == vk::Format::eB8G8R8A8Srgb) {
// TODO() convert SRGB -> LINEAR in shader // TODO() convert SRGB -> LINEAR in shader
return apply_fallback(VK_FORMAT_B8G8R8A8_UNORM, return apply_fallback(
"replace VK_FORMAT_B8G8R8A8_SRGB => VK_FORMAT_B8G8R8A8_UNORM"); vk::Format::eB8G8R8A8Unorm,
"replace vk::Format::eB8G8R8A8Srgb => vk::Format::eB8G8R8A8Unorm");
} }
return false; return false;
} }
return true; return true;
} }
static bool TextureCheckFormatExact(GraphicContext* ctx, const VkImageCreateInfo& image_info) { static bool TextureCheckFormatExact(GraphicContext* ctx, const vk::ImageCreateInfo& image_info) {
VkImageFormatProperties props {}; vk::ImageFormatProperties props {};
return ctx->GetImageFormatProperties(image_info.format, image_info.imageType, image_info.tiling, return ctx->GetImageFormatProperties(image_info.format, image_info.imageType, image_info.tiling,
image_info.usage, image_info.flags, image_info.usage, image_info.flags,
&props) != VK_ERROR_FORMAT_NOT_SUPPORTED; &props) != vk::Result::eErrorFormatNotSupported;
} }
bool TextureCheckStorageSwizzle(VkImageCreateInfo* image_info, VkComponentMapping* components) { bool TextureCheckStorageSwizzle(vk::ImageCreateInfo* image_info, vk::ComponentMapping* components) {
if ((image_info->usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) { if (image_info->usage & vk::ImageUsageFlagBits::eStorage) {
if (components->r == VK_COMPONENT_SWIZZLE_R && components->g == VK_COMPONENT_SWIZZLE_G && if (components->r == vk::ComponentSwizzle::eR &&
components->b == VK_COMPONENT_SWIZZLE_B && components->a == VK_COMPONENT_SWIZZLE_A) { components->g == vk::ComponentSwizzle::eG &&
components->b == vk::ComponentSwizzle::eB &&
components->a == vk::ComponentSwizzle::eA) {
return true; return true;
} }
if (components->r == VK_COMPONENT_SWIZZLE_B && components->g == VK_COMPONENT_SWIZZLE_G && if (components->r == vk::ComponentSwizzle::eB &&
components->b == VK_COMPONENT_SWIZZLE_R && components->a == VK_COMPONENT_SWIZZLE_A && components->g == vk::ComponentSwizzle::eG &&
image_info->format == VK_FORMAT_R8G8B8A8_SRGB) { components->b == vk::ComponentSwizzle::eR &&
LOGF("replace VK_FORMAT_R8G8B8A8_SRGB => VK_FORMAT_B8G8R8A8_SRGB\n"); components->a == vk::ComponentSwizzle::eA &&
image_info->format == vk::Format::eR8G8B8A8Srgb) {
LOGF("replace vk::Format::eR8G8B8A8Srgb => vk::Format::eB8G8R8A8Srgb\n");
components->r = VK_COMPONENT_SWIZZLE_R; components->r = vk::ComponentSwizzle::eR;
components->g = VK_COMPONENT_SWIZZLE_G; components->g = vk::ComponentSwizzle::eG;
components->b = VK_COMPONENT_SWIZZLE_B; components->b = vk::ComponentSwizzle::eB;
components->a = VK_COMPONENT_SWIZZLE_A; components->a = vk::ComponentSwizzle::eA;
image_info->format = VK_FORMAT_B8G8R8A8_SRGB; image_info->format = vk::Format::eB8G8R8A8Srgb;
return true; return true;
} }
@@ -320,35 +326,36 @@ bool TextureCheckStorageSwizzle(VkImageCreateInfo* image_info, VkComponentMappin
return true; return true;
} }
VkImageUsageFlags TextureGetUsage(TextureFormatUsage usage) { vk::ImageUsageFlags TextureGetUsage(TextureFormatUsage usage) {
VkImageUsageFlags vk_usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; vk::ImageUsageFlags vk_usage =
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eTransferSrc;
if (TextureHasFormatUsage(usage, TextureFormatUsage::Sampled)) { if (TextureHasFormatUsage(usage, TextureFormatUsage::Sampled)) {
vk_usage |= VK_IMAGE_USAGE_SAMPLED_BIT; vk_usage |= vk::ImageUsageFlagBits::eSampled;
} }
if (TextureHasFormatUsage(usage, TextureFormatUsage::Storage)) { if (TextureHasFormatUsage(usage, TextureFormatUsage::Storage)) {
vk_usage |= VK_IMAGE_USAGE_STORAGE_BIT; vk_usage |= vk::ImageUsageFlagBits::eStorage;
} }
return vk_usage; return vk_usage;
} }
VkImageUsageFlags TextureGetViewUsage(TextureFormatUsage usage) { vk::ImageUsageFlags TextureGetViewUsage(TextureFormatUsage usage) {
VkImageUsageFlags vk_usage = 0; vk::ImageUsageFlags vk_usage = {};
if (TextureHasFormatUsage(usage, TextureFormatUsage::Sampled)) { if (TextureHasFormatUsage(usage, TextureFormatUsage::Sampled)) {
vk_usage |= VK_IMAGE_USAGE_SAMPLED_BIT; vk_usage |= vk::ImageUsageFlagBits::eSampled;
} }
if (TextureHasFormatUsage(usage, TextureFormatUsage::Storage)) { if (TextureHasFormatUsage(usage, TextureFormatUsage::Storage)) {
vk_usage |= VK_IMAGE_USAGE_STORAGE_BIT; vk_usage |= vk::ImageUsageFlagBits::eStorage;
} }
return vk_usage; return vk_usage;
} }
VkFormat TextureGetFormat(uint32_t fmt, [[maybe_unused]] TextureFormatUsage usage) { vk::Format TextureGetFormat(uint32_t fmt, [[maybe_unused]] TextureFormatUsage usage) {
const auto vk_format = Prospero::SurfaceFormat(fmt); const auto vk_format = Prospero::SurfaceFormat(fmt);
if (vk_format != VK_FORMAT_UNDEFINED) { if (vk_format != vk::Format::eUndefined) {
return vk_format; return vk_format;
} }
EXIT("unknown format: fmt = %u\n", fmt); EXIT("unknown format: fmt = %u\n", fmt);
return VK_FORMAT_UNDEFINED; return vk::Format::eUndefined;
} }
static uint32_t AlignUpU32(uint32_t value, uint32_t alignment) { static uint32_t AlignUpU32(uint32_t value, uint32_t alignment) {
@@ -426,13 +433,13 @@ static bool CalcStandard4kbVolumeMipLayout(uint32_t format, uint32_t pitch, uint
return out->block_slice_size != 0; return out->block_slice_size != 0;
} }
uint32_t TextureGetAtlasSliceYStride(VkFormat format, uint32_t mip_height, uint32_t depth, uint32_t TextureGetAtlasSliceYStride(vk::Format format, uint32_t mip_height, uint32_t depth,
uint64_t levels) { uint64_t levels) {
return (depth > 1 && levels > 1 && UtilIsBcFormat(format) ? AlignUpU32(mip_height, 4u) return (depth > 1 && levels > 1 && UtilIsBcFormat(format) ? AlignUpU32(mip_height, 4u)
: mip_height); : mip_height);
} }
uint32_t TextureCalcStackedImageHeight(VkFormat format, uint32_t height, uint32_t depth, uint32_t TextureCalcStackedImageHeight(vk::Format format, uint32_t height, uint32_t depth,
uint64_t levels) { uint64_t levels) {
auto image_height = height * depth; auto image_height = height * depth;
if (depth <= 1 || levels <= 1 || !UtilIsBcFormat(format)) { if (depth <= 1 || levels <= 1 || !UtilIsBcFormat(format)) {
@@ -452,7 +459,7 @@ uint32_t TextureCalcStackedImageHeight(VkFormat format, uint32_t height, uint32_
return image_height; return image_height;
} }
uint32_t TextureCalcMipmapAtlasImageHeight(VkFormat format, uint32_t width, uint32_t height, uint32_t TextureCalcMipmapAtlasImageHeight(vk::Format format, uint32_t width, uint32_t height,
uint32_t depth, uint64_t levels) { uint32_t depth, uint64_t levels) {
auto image_height = height * depth; auto image_height = height * depth;
if (levels <= 1) { if (levels <= 1) {
@@ -495,8 +502,8 @@ bool TextureCanCreateCubeView(uint64_t type, uint32_t base_array, uint32_t layer
layer_count % 6u == 0; layer_count % 6u == 0;
} }
VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj, VulkanMemory* mem, vk::ComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj, VulkanMemory* mem,
const TextureImageCreateParams& params) { const TextureImageCreateParams& params) {
EXIT_IF(ctx == nullptr); EXIT_IF(ctx == nullptr);
EXIT_IF(vk_obj == nullptr); EXIT_IF(vk_obj == nullptr);
EXIT_IF(mem == nullptr); EXIT_IF(mem == nullptr);
@@ -506,7 +513,7 @@ VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj,
const bool volume_texture = TextureIs3DTexture(params.type); const bool volume_texture = TextureIs3DTexture(params.type);
auto pixel_format = TextureGetFormat(params.fmt, params.format_usage); auto pixel_format = TextureGetFormat(params.fmt, params.format_usage);
EXIT_NOT_IMPLEMENTED(pixel_format == VK_FORMAT_UNDEFINED); EXIT_NOT_IMPLEMENTED(pixel_format == vk::Format::eUndefined);
EXIT_NOT_IMPLEMENTED(params.width == 0); EXIT_NOT_IMPLEMENTED(params.width == 0);
EXIT_NOT_IMPLEMENTED(params.height == 0); EXIT_NOT_IMPLEMENTED(params.height == 0);
EXIT_NOT_IMPLEMENTED(params.levels == 0 || params.levels > 16); EXIT_NOT_IMPLEMENTED(params.levels == 0 || params.levels > 16);
@@ -529,30 +536,31 @@ VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj,
image_mips = static_cast<uint32_t>(params.levels); image_mips = static_cast<uint32_t>(params.levels);
} }
VkComponentMapping components = vk::ComponentMapping components =
TextureGetComponentMapping(static_cast<uint32_t>(params.swizzle)); TextureGetComponentMapping(static_cast<uint32_t>(params.swizzle));
VkImageCreateInfo image_info {}; vk::ImageCreateInfo image_info {};
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; image_info.sType = vk::StructureType::eImageCreateInfo;
image_info.pNext = nullptr; image_info.pNext = nullptr;
image_info.flags = image_info.flags =
(params.allow_cube_view && TextureCanCreateCubeView(params.type, 0, params.depth) (params.allow_cube_view && TextureCanCreateCubeView(params.type, 0, params.depth)
? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT ? vk::ImageCreateFlagBits::eCubeCompatible
: 0) | : vk::ImageCreateFlags {}) |
(volume_texture ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT : 0) | (volume_texture ? vk::ImageCreateFlagBits::e2DArrayCompatible : vk::ImageCreateFlags {}) |
(params.compatible_format_views ? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT : 0); (params.compatible_format_views ? vk::ImageCreateFlagBits::eMutableFormat
image_info.imageType = (volume_texture ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D); : vk::ImageCreateFlags {});
image_info.imageType = (volume_texture ? vk::ImageType::e3D : vk::ImageType::e2D);
image_info.extent.width = static_cast<uint32_t>(params.width); image_info.extent.width = static_cast<uint32_t>(params.width);
image_info.extent.height = image_height; image_info.extent.height = image_height;
image_info.extent.depth = (volume_texture ? params.depth : 1); image_info.extent.depth = (volume_texture ? params.depth : 1);
image_info.mipLevels = image_mips; image_info.mipLevels = image_mips;
image_info.arrayLayers = (array_texture ? params.depth : 1); image_info.arrayLayers = (array_texture ? params.depth : 1);
image_info.format = pixel_format; image_info.format = pixel_format;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL; image_info.tiling = vk::ImageTiling::eOptimal;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; image_info.initialLayout = vk::ImageLayout::eUndefined;
image_info.usage = TextureGetUsage(params.format_usage); image_info.usage = TextureGetUsage(params.format_usage);
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; image_info.sharingMode = vk::SharingMode::eExclusive;
image_info.samples = VK_SAMPLE_COUNT_1_BIT; image_info.samples = vk::SampleCountFlagBits::e1;
const bool storage_view = TextureHasFormatUsage(params.view_usage, TextureFormatUsage::Storage); const bool storage_view = TextureHasFormatUsage(params.view_usage, TextureFormatUsage::Storage);
if (storage_view && !TextureCheckStorageSwizzle(&image_info, &components)) { if (storage_view && !TextureCheckStorageSwizzle(&image_info, &components)) {
@@ -565,10 +573,10 @@ VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj,
LOGF("\t %s swizzle 0x%08" PRIx64 " is not supported, using identity mapping\n", LOGF("\t %s swizzle 0x%08" PRIx64 " is not supported, using identity mapping\n",
params.owner, params.swizzle); params.owner, params.swizzle);
} }
components.r = VK_COMPONENT_SWIZZLE_R; components.r = vk::ComponentSwizzle::eR;
components.g = VK_COMPONENT_SWIZZLE_G; components.g = vk::ComponentSwizzle::eG;
components.b = VK_COMPONENT_SWIZZLE_B; components.b = vk::ComponentSwizzle::eB;
components.a = VK_COMPONENT_SWIZZLE_A; components.a = vk::ComponentSwizzle::eA;
} }
const auto view_checked_format = image_info.format; const auto view_checked_format = image_info.format;
@@ -612,7 +620,7 @@ VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj,
UtilResetImageViews(vk_obj); UtilResetImageViews(vk_obj);
mem->property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; mem->property = vk::MemoryPropertyFlagBits::eDeviceLocal;
bool created = VulkanCreateImage(ctx, &image_info, vk_obj, mem); bool created = VulkanCreateImage(ctx, &image_info, vk_obj, mem);
EXIT_NOT_IMPLEMENTED(!created); EXIT_NOT_IMPLEMENTED(!created);
@@ -623,7 +631,7 @@ VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj,
} }
void TextureCreateImageViews(GraphicContext* ctx, VulkanImage* vk_obj, void TextureCreateImageViews(GraphicContext* ctx, VulkanImage* vk_obj,
VkComponentMapping components, uint64_t type, uint32_t base_array, vk::ComponentMapping components, uint64_t type, uint32_t base_array,
uint32_t base_level, uint32_t level_count, uint32_t depth, uint32_t base_level, uint32_t level_count, uint32_t depth,
bool allow_cube_view, TextureFormatUsage view_usage) { bool allow_cube_view, TextureFormatUsage view_usage) {
EXIT_IF(ctx == nullptr); EXIT_IF(ctx == nullptr);
@@ -635,44 +643,44 @@ void TextureCreateImageViews(GraphicContext* ctx, VulkanImage* vk_obj,
const auto layer_count = (layered_texture && base_array < depth ? depth - base_array : 1u); const auto layer_count = (layered_texture && base_array < depth ? depth - base_array : 1u);
const auto volume_slices = std::max(depth >> base_level, 1u); const auto volume_slices = std::max(depth >> base_level, 1u);
VkImageViewUsageCreateInfo usage_info {}; vk::ImageViewUsageCreateInfo usage_info {};
usage_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO; usage_info.sType = vk::StructureType::eImageViewUsageCreateInfo;
usage_info.pNext = nullptr; usage_info.pNext = nullptr;
usage_info.usage = TextureGetViewUsage(view_usage); usage_info.usage = TextureGetViewUsage(view_usage);
VkImageViewCreateInfo create_info {}; vk::ImageViewCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; create_info.sType = vk::StructureType::eImageViewCreateInfo;
create_info.pNext = (usage_info.usage != 0 ? &usage_info : nullptr); create_info.pNext = (usage_info.usage ? &usage_info : nullptr);
create_info.flags = 0; create_info.flags = {};
create_info.image = vk_obj->image; create_info.image = vk_obj->image;
create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; create_info.viewType = vk::ImageViewType::e2D;
create_info.format = vk_obj->format; create_info.format = vk_obj->format;
create_info.components = components; create_info.components = components;
create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; create_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
create_info.subresourceRange.baseArrayLayer = (layered_texture ? base_array : 0); create_info.subresourceRange.baseArrayLayer = (layered_texture ? base_array : 0);
create_info.subresourceRange.baseMipLevel = base_level; create_info.subresourceRange.baseMipLevel = base_level;
create_info.subresourceRange.layerCount = layer_count; create_info.subresourceRange.layerCount = layer_count;
create_info.subresourceRange.levelCount = level_count; create_info.subresourceRange.levelCount = level_count;
if (volume_texture) { if (volume_texture) {
create_info.viewType = VK_IMAGE_VIEW_TYPE_3D; create_info.viewType = vk::ImageViewType::e3D;
create_info.subresourceRange.baseArrayLayer = 0; create_info.subresourceRange.baseArrayLayer = 0;
create_info.subresourceRange.layerCount = 1; create_info.subresourceRange.layerCount = 1;
} else if (allow_cube_view && TextureCanCreateCubeView(type, base_array, layer_count)) { } else if (allow_cube_view && TextureCanCreateCubeView(type, base_array, layer_count)) {
create_info.viewType = create_info.viewType =
(layer_count > 6 ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE); (layer_count > 6 ? vk::ImageViewType::eCubeArray : vk::ImageViewType::eCube);
} else if (layered_texture) { } else if (layered_texture) {
create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; create_info.viewType = vk::ImageViewType::e2DArray;
} }
vkCreateImageView(ctx->device, &create_info, nullptr, ctx->device.createImageView(&create_info, nullptr,
&vk_obj->image_view[VulkanImage::VIEW_DEFAULT]); &vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr); EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);
if (!volume_texture || depth >= 1) { if (!volume_texture || depth >= 1) {
create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; create_info.viewType = vk::ImageViewType::e2DArray;
create_info.subresourceRange.layerCount = (volume_texture ? volume_slices : layer_count); create_info.subresourceRange.layerCount = (volume_texture ? volume_slices : layer_count);
vkCreateImageView(ctx->device, &create_info, nullptr, ctx->device.createImageView(&create_info, nullptr,
&vk_obj->image_view[VulkanImage::VIEW_DEFAULT_ARRAY]); &vk_obj->image_view[VulkanImage::VIEW_DEFAULT_ARRAY]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT_ARRAY] == nullptr); EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT_ARRAY] == nullptr);
} }
} }
@@ -827,11 +835,10 @@ TextureUploadLayout TextureCalcUploadLayout(uint32_t fmt, uint64_t width, uint64
return layout; return layout;
} }
std::vector<BufferImageCopy> std::vector<BufferImageCopy> TextureBuildUploadRegions(
TextureBuildUploadRegions(const TextureUploadLayout& layout, VkFormat image_format, uint32_t width, const TextureUploadLayout& layout, vk::Format image_format, uint32_t width, uint32_t height,
uint32_t height, uint32_t depth, uint64_t levels, bool array_texture, uint32_t depth, uint64_t levels, bool array_texture, bool volume_texture,
bool volume_texture, TextureUploadDestination destination, TextureUploadDestination destination, TextureUploadSliceLayout slice_layout) {
TextureUploadSliceLayout slice_layout) {
uint32_t mip_width = width; uint32_t mip_width = width;
uint32_t mip_height = height; uint32_t mip_height = height;
uint32_t mip_pitch = layout.pitch; uint32_t mip_pitch = layout.pitch;
@@ -930,8 +937,8 @@ static uint64_t FmaskRegionCopySize(const BufferImageCopy& region) {
} }
static void UploadFmaskIdentity(GraphicContext* ctx, VulkanImage* vk_obj, static void UploadFmaskIdentity(GraphicContext* ctx, VulkanImage* vk_obj,
const std::vector<BufferImageCopy>& regions, uint64_t dst_layout, const std::vector<BufferImageCopy>& regions,
const char* owner) { vk::ImageLayout dst_layout, const char* owner) {
constexpr uint32_t kIdentityFmaskPattern = 0x76543210u; constexpr uint32_t kIdentityFmaskPattern = 0x76543210u;
std::vector<BufferImageCopy> upload_regions = regions; std::vector<BufferImageCopy> upload_regions = regions;
@@ -961,7 +968,7 @@ void TextureUploadGuestImage(GraphicContext* ctx, VulkanImage* vk_obj, const voi
const TextureUploadLayout& layout, uint32_t fmt, uint64_t width, const TextureUploadLayout& layout, uint32_t fmt, uint64_t width,
uint64_t height, uint32_t depth, uint64_t levels, uint64_t height, uint32_t depth, uint64_t levels,
TextureUploadSliceLayout source_slice_layout, const char* owner, TextureUploadSliceLayout source_slice_layout, const char* owner,
uint64_t dst_layout) { vk::ImageLayout dst_layout) {
if (fmt == 0) { if (fmt == 0) {
EXIT("%s: legacy texture upload format unsupported: fmt=0 tile=%u size=%" PRIu64 EXIT("%s: legacy texture upload format unsupported: fmt=0 tile=%u size=%" PRIu64
" extent=%" PRIu64 "x%" PRIu64 " depth=%u pitch=%u levels=%" PRIu64 "\n", " extent=%" PRIu64 "x%" PRIu64 " depth=%u pitch=%u levels=%" PRIu64 "\n",
+20 -21
View File
@@ -6,9 +6,9 @@
#include "graphics/guest_gpu/gpu_defs.h" #include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/guest_gpu/tile.h" #include "graphics/guest_gpu/tile.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <vector> #include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -48,7 +48,7 @@ enum class TextureUploadDestination { MipLevels, MipAtlas };
enum class TextureUploadSliceLayout { MipChainPerSlice, MipLevelPerSlice }; enum class TextureUploadSliceLayout { MipChainPerSlice, MipLevelPerSlice };
struct RenderTargetFormatInfo { struct RenderTargetFormatInfo {
VkFormat format = VK_FORMAT_UNDEFINED; vk::Format format = vk::Format::eUndefined;
uint32_t bytes_per_element = 0; uint32_t bytes_per_element = 0;
Prospero::ColorComponentMapping export_mapping; Prospero::ColorComponentMapping export_mapping;
}; };
@@ -87,28 +87,28 @@ struct TextureImageCreateParams {
const char* owner = nullptr; const char* owner = nullptr;
}; };
VkComponentSwizzle TextureGetComponentSwizzle(uint8_t s); vk::ComponentSwizzle TextureGetComponentSwizzle(uint8_t s);
VkComponentMapping TextureGetComponentMapping(uint32_t swizzle); vk::ComponentMapping TextureGetComponentMapping(uint32_t swizzle);
bool TextureCheckFormat(GraphicContext* ctx, VkImageCreateInfo* image_info); bool TextureCheckFormat(GraphicContext* ctx, vk::ImageCreateInfo* image_info);
bool TextureCheckStorageSwizzle(VkImageCreateInfo* image_info, VkComponentMapping* components); bool TextureCheckStorageSwizzle(vk::ImageCreateInfo* image_info, vk::ComponentMapping* components);
VkImageUsageFlags TextureGetUsage(TextureFormatUsage usage); vk::ImageUsageFlags TextureGetUsage(TextureFormatUsage usage);
VkImageUsageFlags TextureGetViewUsage(TextureFormatUsage usage); vk::ImageUsageFlags TextureGetViewUsage(TextureFormatUsage usage);
VkFormat TextureGetFormat(uint32_t fmt, TextureFormatUsage usage); vk::Format TextureGetFormat(uint32_t fmt, TextureFormatUsage usage);
RenderTargetFormatInfo TextureGetRenderTargetFormat(uint32_t layout, uint32_t type, uint32_t order); RenderTargetFormatInfo TextureGetRenderTargetFormat(uint32_t layout, uint32_t type, uint32_t order);
uint32_t TextureGetAtlasSliceYStride(VkFormat format, uint32_t mip_height, uint32_t depth, uint32_t TextureGetAtlasSliceYStride(vk::Format format, uint32_t mip_height, uint32_t depth,
uint64_t levels); uint64_t levels);
uint32_t TextureCalcStackedImageHeight(VkFormat format, uint32_t height, uint32_t depth, uint32_t TextureCalcStackedImageHeight(vk::Format format, uint32_t height, uint32_t depth,
uint64_t levels); uint64_t levels);
uint32_t TextureCalcMipmapAtlasImageHeight(VkFormat format, uint32_t width, uint32_t height, uint32_t TextureCalcMipmapAtlasImageHeight(vk::Format format, uint32_t width, uint32_t height,
uint32_t depth, uint64_t levels); uint32_t depth, uint64_t levels);
bool TextureIs3DTexture(uint64_t type); bool TextureIs3DTexture(uint64_t type);
bool TextureIsCubeTexture(uint64_t type); bool TextureIsCubeTexture(uint64_t type);
bool TextureIsLayeredTexture(uint64_t type); bool TextureIsLayeredTexture(uint64_t type);
bool TextureCanCreateCubeView(uint64_t type, uint32_t base_array, uint32_t layer_count); bool TextureCanCreateCubeView(uint64_t type, uint32_t base_array, uint32_t layer_count);
VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj, VulkanMemory* mem, vk::ComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj, VulkanMemory* mem,
const TextureImageCreateParams& params); const TextureImageCreateParams& params);
void TextureCreateImageViews(GraphicContext* ctx, VulkanImage* vk_obj, void TextureCreateImageViews(GraphicContext* ctx, VulkanImage* vk_obj,
VkComponentMapping components, uint64_t type, uint32_t base_array, vk::ComponentMapping components, uint64_t type, uint32_t base_array,
uint32_t base_level, uint32_t level_count, uint32_t depth, uint32_t base_level, uint32_t level_count, uint32_t depth,
bool allow_cube_view, TextureFormatUsage view_usage); bool allow_cube_view, TextureFormatUsage view_usage);
TextureUploadLayout TextureCalcUploadLayout(uint32_t fmt, uint64_t width, uint64_t height, TextureUploadLayout TextureCalcUploadLayout(uint32_t fmt, uint64_t width, uint64_t height,
@@ -123,11 +123,10 @@ uint64_t TextureUploadSliceSourceOffset(const TextureUploadLayout& layout, uint3
uint64_t TextureCalcUploadSize(const TextureUploadLayout& layout, uint64_t TextureCalcUploadSize(const TextureUploadLayout& layout,
const std::vector<BufferImageCopy>& regions, uint64_t levels, const std::vector<BufferImageCopy>& regions, uint64_t levels,
uint32_t depth, TextureUploadSliceLayout source_slice_layout); uint32_t depth, TextureUploadSliceLayout source_slice_layout);
std::vector<BufferImageCopy> std::vector<BufferImageCopy> TextureBuildUploadRegions(
TextureBuildUploadRegions(const TextureUploadLayout& layout, VkFormat image_format, uint32_t width, const TextureUploadLayout& layout, vk::Format image_format, uint32_t width, uint32_t height,
uint32_t height, uint32_t depth, uint64_t levels, bool array_texture, uint32_t depth, uint64_t levels, bool array_texture, bool volume_texture,
bool volume_texture, TextureUploadDestination destination, TextureUploadDestination destination, TextureUploadSliceLayout slice_layout);
TextureUploadSliceLayout slice_layout);
void TextureCopyBufferBytes(GraphicContext* ctx, VulkanBuffer* src_buffer, void TextureCopyBufferBytes(GraphicContext* ctx, VulkanBuffer* src_buffer,
uint64_t src_buffer_offset, uint64_t copy_size, UtilScratchBuffer* dst); uint64_t src_buffer_offset, uint64_t copy_size, UtilScratchBuffer* dst);
void TextureUploadGuestImage(GraphicContext* ctx, VulkanImage* vk_obj, const void* src_data, void TextureUploadGuestImage(GraphicContext* ctx, VulkanImage* vk_obj, const void* src_data,
@@ -135,7 +134,7 @@ void TextureUploadGuestImage(GraphicContext* ctx, VulkanImage* vk_obj, const voi
const TextureUploadLayout& layout, uint32_t fmt, uint64_t width, const TextureUploadLayout& layout, uint32_t fmt, uint64_t width,
uint64_t height, uint32_t depth, uint64_t levels, uint64_t height, uint32_t depth, uint64_t levels,
TextureUploadSliceLayout source_slice_layout, const char* owner, TextureUploadSliceLayout source_slice_layout, const char* owner,
uint64_t dst_layout); vk::ImageLayout dst_layout);
} // namespace Libs::Graphics } // namespace Libs::Graphics
+91 -88
View File
@@ -421,10 +421,10 @@ struct BufferCache::ReadbackWorker {
i, family, ctx->queues[i].family); i, family, ctx->queues[i].family);
} }
} }
readback.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; readback.usage = vk::BufferUsageFlagBits::eTransferDst;
readback.memory.property = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | readback.memory.property = vk::MemoryPropertyFlagBits::eHostVisible |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | vk::MemoryPropertyFlagBits::eHostCoherent |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT; vk::MemoryPropertyFlagBits::eHostCached;
VulkanCreateBuffer(ctx, READBACK_CAPACITY, &readback); VulkanCreateBuffer(ctx, READBACK_CAPACITY, &readback);
VulkanMapMemory(ctx, &readback.memory, &mapped); VulkanMapMemory(ctx, &readback.memory, &mapped);
command = std::make_unique<CommandBuffer>(GraphicContext::QUEUE_UTIL); command = std::make_unique<CommandBuffer>(GraphicContext::QUEUE_UTIL);
@@ -456,9 +456,9 @@ struct BufferCache::ReadbackWorker {
" page=0x%016" PRIx64 " buffer=0x%016" PRIx64 " size=0x%016" PRIx64 "\n", " page=0x%016" PRIx64 " buffer=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
vaddr, page, cached.vaddr, cached.size); vaddr, page, cached.vaddr, cached.size);
} }
uint32_t data_offset = 0; uint32_t data_offset = 0;
std::array<VkBufferCopy, MAX_RANGES> copies {}; std::array<vk::BufferCopy, MAX_RANGES> copies {};
std::array<VkBufferMemoryBarrier, MAX_RANGES> barriers {}; std::array<vk::BufferMemoryBarrier, MAX_RANGES> barriers {};
cache.m_gpu_modified_ranges.ForEachIntersection( cache.m_gpu_modified_ranges.ForEachIntersection(
page, TRACKER_PAGE_SIZE, [&](RangeSet::Range range) { page, TRACKER_PAGE_SIZE, [&](RangeSet::Range range) {
if (range_count == MAX_RANGES || (range.address - cached.vaddr) % 4 != 0 || if (range_count == MAX_RANGES || (range.address - cached.vaddr) % 4 != 0 ||
@@ -475,9 +475,9 @@ struct BufferCache::ReadbackWorker {
.dstOffset = data_offset, .dstOffset = data_offset,
.size = range.size}; .size = range.size};
auto& barrier = barriers[range_count]; auto& barrier = barriers[range_count];
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; barrier.sType = vk::StructureType::eBufferMemoryBarrier;
barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; barrier.srcAccessMask = vk::AccessFlagBits::eMemoryWrite;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.buffer = cached.buffer->buffer; barrier.buffer = cached.buffer->buffer;
@@ -498,13 +498,13 @@ struct BufferCache::ReadbackWorker {
" count=%u bytes=%u\n", " count=%u bytes=%u\n",
page, range_count, data_offset); page, range_count, data_offset);
} }
auto* vk_buffer = command->GetPool()->buffers[command->GetIndex()]; auto vk_buffer = command->GetPool()->buffers[command->GetIndex()];
command->Begin(); command->Begin();
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, range_count, vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlags {},
barriers.data(), 0, nullptr); 0, nullptr, range_count, barriers.data(), 0, nullptr);
vkCmdCopyBuffer(vk_buffer, cached.buffer->buffer, readback.buffer, range_count, vk_buffer.copyBuffer(cached.buffer->buffer, readback.buffer, range_count,
copies.data()); copies.data());
command->End(); command->End();
command->Execute(); command->Execute();
command->WaitForFenceAndReset(); command->WaitForFenceAndReset();
@@ -687,10 +687,10 @@ std::pair<VulkanBuffer*, uint64_t> BufferCache::ObtainBuffer(CommandBuffer* com
!texture_region.gpu_metadata_bytes) { !texture_region.gpu_metadata_bytes) {
std::array<uint8_t, CACHING_PAGE_SIZE> guest_data; std::array<uint8_t, CACHING_PAGE_SIZE> guest_data;
if (Libs::LibKernel::Memory::TryReadBacking(vaddr, guest_data.data(), size)) { if (Libs::LibKernel::Memory::TryReadBacking(vaddr, guest_data.data(), size)) {
VulkanBuffer* stream_buffer = nullptr; VulkanBuffer* stream_buffer = nullptr;
VkDeviceSize stream_offset = 0; vk::DeviceSize stream_offset = 0;
VkDeviceSize stream_range = 0; vk::DeviceSize stream_range = 0;
const auto stream_alignment = std::max<uint64_t>(ctx->StorageMinAlignment(), 16); const auto stream_alignment = std::max<uint64_t>(ctx->StorageMinAlignment(), 16);
if (UploadHostData(command, ctx, guest_data.data(), size, stream_alignment, if (UploadHostData(command, ctx, guest_data.data(), size, stream_alignment,
&stream_buffer, &stream_offset, &stream_range)) { &stream_buffer, &stream_offset, &stream_range)) {
return {stream_buffer, stream_offset}; return {stream_buffer, stream_offset};
@@ -795,20 +795,20 @@ std::pair<VulkanBuffer*, uint64_t> BufferCache::ObtainBuffer(CommandBuffer* com
cached->ctx = ctx; cached->ctx = ctx;
cached->buffer = MakeSharedVulkanBuffer(ctx); cached->buffer = MakeSharedVulkanBuffer(ctx);
cached->buffer->usage = cached->buffer->usage =
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst |
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eIndexBuffer |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; vk::BufferUsageFlagBits::eStorageBuffer;
cached->buffer->memory.property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; cached->buffer->memory.property = vk::MemoryPropertyFlagBits::eDeviceLocal;
VulkanCreateBuffer(ctx, cached->size, cached->buffer.get()); VulkanCreateBuffer(ctx, cached->size, cached->buffer.get());
if (!overlaps.empty()) { if (!overlaps.empty()) {
auto* vk_buffer = command->GetPool()->buffers[command->GetIndex()]; auto vk_buffer = command->GetPool()->buffers[command->GetIndex()];
std::vector<VkBufferMemoryBarrier> before; std::vector<vk::BufferMemoryBarrier> before;
before.reserve(overlaps.size() + 1); before.reserve(overlaps.size() + 1);
for (const auto& overlap: overlaps) { for (const auto& overlap: overlaps) {
VkBufferMemoryBarrier barrier {}; vk::BufferMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; barrier.sType = vk::StructureType::eBufferMemoryBarrier;
barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; barrier.srcAccessMask = vk::AccessFlagBits::eMemoryWrite;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.buffer = overlap->second->buffer->buffer; barrier.buffer = overlap->second->buffer->buffer;
@@ -816,37 +816,38 @@ std::pair<VulkanBuffer*, uint64_t> BufferCache::ObtainBuffer(CommandBuffer* com
barrier.size = overlap->second->size; barrier.size = overlap->second->size;
before.push_back(barrier); before.push_back(barrier);
} }
VkBufferMemoryBarrier destination {}; vk::BufferMemoryBarrier destination {};
destination.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; destination.sType = vk::StructureType::eBufferMemoryBarrier;
destination.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; destination.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
destination.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; destination.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
destination.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; destination.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
destination.buffer = cached->buffer->buffer; destination.buffer = cached->buffer->buffer;
destination.offset = 0; destination.offset = 0;
destination.size = cached->size; destination.size = cached->size;
before.push_back(destination); before.push_back(destination);
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk_buffer.pipelineBarrier(
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eTransfer,
nullptr, static_cast<uint32_t>(before.size()), before.data(), 0, vk::DependencyFlagBits::eByRegion, 0, nullptr, static_cast<uint32_t>(before.size()),
nullptr); before.data(), 0, nullptr);
for (const auto& overlap: overlaps) { for (const auto& overlap: overlaps) {
const auto& old = *overlap->second; const auto& old = *overlap->second;
const VkBufferCopy copy { const vk::BufferCopy copy {
.srcOffset = 0, .dstOffset = old.vaddr - cached->vaddr, .size = old.size}; .srcOffset = 0, .dstOffset = old.vaddr - cached->vaddr, .size = old.size};
vkCmdCopyBuffer(vk_buffer, old.buffer->buffer, cached->buffer->buffer, 1, &copy); vk_buffer.copyBuffer(old.buffer->buffer, cached->buffer->buffer, 1, &copy);
} }
VkBufferMemoryBarrier after {}; vk::BufferMemoryBarrier after {};
after.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; after.sType = vk::StructureType::eBufferMemoryBarrier;
after.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; after.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
after.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; after.dstAccessMask =
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
after.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; after.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
after.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; after.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
after.buffer = cached->buffer->buffer; after.buffer = cached->buffer->buffer;
after.offset = 0; after.offset = 0;
after.size = cached->size; after.size = cached->size;
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, vk_buffer.pipelineBarrier(
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eAllCommands,
nullptr, 1, &after, 0, nullptr); vk::DependencyFlagBits::eByRegion, 0, nullptr, 1, &after, 0, nullptr);
for (const auto& overlap: overlaps) { for (const auto& overlap: overlaps) {
command->RetainResourceUntilFence(overlap->second->buffer); command->RetainResourceUntilFence(overlap->second->buffer);
m_buffers.erase(overlap); m_buffers.erase(overlap);
@@ -896,12 +897,13 @@ VulkanBuffer* BufferCache::ObtainNullBuffer(CommandBuffer* command, GraphicConte
if (m_null_buffer == nullptr) { if (m_null_buffer == nullptr) {
// robustBufferAccess makes every fetch safe; TODO: Use a // robustBufferAccess makes every fetch safe; TODO: Use a
// persistent 16-byte fallback when Vulkan null vertex descriptors are unavailable. // persistent 16-byte fallback when Vulkan null vertex descriptors are unavailable.
auto buffer = MakeSharedVulkanBuffer(ctx); auto buffer = MakeSharedVulkanBuffer(ctx);
buffer->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | buffer->usage = vk::BufferUsageFlagBits::eStorageBuffer |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT; vk::BufferUsageFlagBits::eVertexBuffer |
buffer->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) | vk::BufferUsageFlagBits::eIndexBuffer;
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | buffer->memory.property = vk::MemoryPropertyFlagBits::eHostVisible |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT; vk::MemoryPropertyFlagBits::eHostCoherent |
vk::MemoryPropertyFlagBits::eHostCached;
VulkanCreateBuffer(ctx, 16, buffer.get()); VulkanCreateBuffer(ctx, 16, buffer.get());
void* data = nullptr; void* data = nullptr;
VulkanMapMemory(ctx, &buffer->memory, &data); VulkanMapMemory(ctx, &buffer->memory, &data);
@@ -1040,8 +1042,8 @@ BufferImageCopySource BufferCache::ObtainBufferForImage(uint64_t vaddr, uint64_t
} }
namespace { namespace {
VkBufferMemoryBarrier MakeDmaBarrier(VulkanBuffer* buffer, uint64_t offset, uint64_t size, vk::BufferMemoryBarrier MakeDmaBarrier(VulkanBuffer* buffer, uint64_t offset, uint64_t size,
VkAccessFlags source, VkAccessFlags destination) { vk::AccessFlags source, vk::AccessFlags destination) {
if (buffer == nullptr || buffer->buffer == nullptr || size == 0 || if (buffer == nullptr || buffer->buffer == nullptr || size == 0 ||
offset > buffer->buffer_size || size > buffer->buffer_size - offset) { offset > buffer->buffer_size || size > buffer->buffer_size - offset) {
EXIT("BufferCache: invalid DMA barrier, buffer=%p handle=%p offset=0x%016" PRIx64 EXIT("BufferCache: invalid DMA barrier, buffer=%p handle=%p offset=0x%016" PRIx64
@@ -1050,8 +1052,8 @@ VkBufferMemoryBarrier MakeDmaBarrier(VulkanBuffer* buffer, uint64_t offset, uint
buffer == nullptr ? nullptr : static_cast<const void*>(buffer->buffer), offset, size, buffer == nullptr ? nullptr : static_cast<const void*>(buffer->buffer), offset, size,
buffer == nullptr ? 0 : buffer->buffer_size); buffer == nullptr ? 0 : buffer->buffer_size);
} }
VkBufferMemoryBarrier barrier {}; vk::BufferMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; barrier.sType = vk::StructureType::eBufferMemoryBarrier;
barrier.srcAccessMask = source; barrier.srcAccessMask = source;
barrier.dstAccessMask = destination; barrier.dstAccessMask = destination;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@@ -1062,7 +1064,7 @@ VkBufferMemoryBarrier MakeDmaBarrier(VulkanBuffer* buffer, uint64_t offset, uint
return barrier; return barrier;
} }
VkCommandBuffer GetDmaCommandBuffer(CommandBuffer* command) { vk::CommandBuffer GetDmaCommandBuffer(CommandBuffer* command) {
if (command == nullptr || command->IsInvalid() || command->GetPool() == nullptr || if (command == nullptr || command->IsInvalid() || command->GetPool() == nullptr ||
command->GetIndex() >= command->GetPool()->buffers_count) { command->GetIndex() >= command->GetPool()->buffers_count) {
EXIT("BufferCache: invalid DMA command buffer, command=%p\n", EXIT("BufferCache: invalid DMA command buffer, command=%p\n",
@@ -1113,19 +1115,20 @@ void BufferCache::FillBuffer(CommandBuffer* command, GraphicContext* ctx, uint64
} }
} }
const auto [dst, dst_offset] = ObtainBuffer(command, ctx, vaddr, size, true, false); const auto [dst, dst_offset] = ObtainBuffer(command, ctx, vaddr, size, true, false);
const auto before = MakeDmaBarrier(dst, dst_offset, size, const auto before = MakeDmaBarrier(
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, dst, dst_offset, size, vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite,
VK_ACCESS_TRANSFER_WRITE_BIT); vk::AccessFlagBits::eTransferWrite);
const auto vk_buffer = GetDmaCommandBuffer(command); const auto vk_buffer = GetDmaCommandBuffer(command);
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk_buffer.pipelineBarrier(
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eTransfer,
&before, 0, nullptr); vk::DependencyFlagBits::eByRegion, 0, nullptr, 1, &before, 0, nullptr);
vkCmdFillBuffer(vk_buffer, dst->buffer, dst_offset, size, value); vk_buffer.fillBuffer(dst->buffer, dst_offset, size, value);
const auto after = MakeDmaBarrier(dst, dst_offset, size, VK_ACCESS_TRANSFER_WRITE_BIT, const auto after =
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT); MakeDmaBarrier(dst, dst_offset, size, vk::AccessFlagBits::eTransferWrite,
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite);
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
nullptr, 1, &after, 0, nullptr); vk::PipelineStageFlagBits::eAllCommands,
vk::DependencyFlagBits::eByRegion, 0, nullptr, 1, &after, 0, nullptr);
} }
void BufferCache::CopyBuffer(CommandBuffer* command, GraphicContext* ctx, uint64_t dst_vaddr, void BufferCache::CopyBuffer(CommandBuffer* command, GraphicContext* ctx, uint64_t dst_vaddr,
@@ -1200,28 +1203,28 @@ void BufferCache::CopyBuffer(CommandBuffer* command, GraphicContext* ctx, uint64
" dst_offset=0x%016" PRIx64 " size=0x%016" PRIx64 "\n", " dst_offset=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
src_offset, dst_offset, size); src_offset, dst_offset, size);
} }
const VkBufferMemoryBarrier before[] = { const vk::BufferMemoryBarrier before[] = {
MakeDmaBarrier(dst, dst_offset, size, MakeDmaBarrier(dst, dst_offset, size,
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite,
VK_ACCESS_TRANSFER_WRITE_BIT), vk::AccessFlagBits::eTransferWrite),
MakeDmaBarrier(src, src_offset, size, VK_ACCESS_MEMORY_WRITE_BIT, MakeDmaBarrier(src, src_offset, size, vk::AccessFlagBits::eMemoryWrite,
VK_ACCESS_TRANSFER_READ_BIT), vk::AccessFlagBits::eTransferRead),
}; };
const auto vk_buffer = GetDmaCommandBuffer(command); const auto vk_buffer = GetDmaCommandBuffer(command);
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 2, vk::PipelineStageFlagBits::eTransfer,
before, 0, nullptr); vk::DependencyFlagBits::eByRegion, 0, nullptr, 2, before, 0, nullptr);
const VkBufferCopy copy {src_offset, dst_offset, size}; const vk::BufferCopy copy {src_offset, dst_offset, size};
vkCmdCopyBuffer(vk_buffer, src->buffer, dst->buffer, 1, &copy); vk_buffer.copyBuffer(src->buffer, dst->buffer, 1, &copy);
const VkBufferMemoryBarrier after[] = { const vk::BufferMemoryBarrier after[] = {
MakeDmaBarrier(dst, dst_offset, size, VK_ACCESS_TRANSFER_WRITE_BIT, MakeDmaBarrier(dst, dst_offset, size, vk::AccessFlagBits::eTransferWrite,
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT), vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite),
MakeDmaBarrier(src, src_offset, size, VK_ACCESS_TRANSFER_READ_BIT, MakeDmaBarrier(src, src_offset, size, vk::AccessFlagBits::eTransferRead,
VK_ACCESS_MEMORY_WRITE_BIT), vk::AccessFlagBits::eMemoryWrite),
}; };
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, vk::PipelineStageFlagBits::eAllCommands,
nullptr, 2, after, 0, nullptr); vk::DependencyFlagBits::eByRegion, 0, nullptr, 2, after, 0, nullptr);
} }
bool BufferCache::HasPageOverlap(uint64_t vaddr, uint64_t size) { bool BufferCache::HasPageOverlap(uint64_t vaddr, uint64_t size) {
@@ -17,6 +17,7 @@
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/displayBuffer.h" #include "graphics/presentation/displayBuffer.h"
#include <algorithm> #include <algorithm>
@@ -25,7 +26,6 @@
#include <cstdarg> #include <cstdarg>
#include <cstdio> #include <cstdio>
#include <limits> #include <limits>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -71,11 +71,11 @@ static float ColorClearF16(uint32_t value) {
std::ldexp(static_cast<float>(0x400u | mantissa), static_cast<int>(exponent) - 25); std::ldexp(static_cast<float>(0x400u | mantissa), static_cast<int>(exponent) - 25);
} }
[[maybe_unused]] static VkClearColorValue ColorClearValue(const HW::RenderTarget& rt) { [[maybe_unused]] static vk::ClearColorValue ColorClearValue(const HW::RenderTarget& rt) {
const uint32_t c0 = rt.clear_word0.word0; const uint32_t c0 = rt.clear_word0.word0;
const uint32_t c1 = rt.clear_word1.word1; const uint32_t c1 = rt.clear_word1.word1;
VkClearColorValue color {}; vk::ClearColorValue color {};
switch (static_cast<Prospero::ChannelType>(rt.info.channel_type)) { switch (static_cast<Prospero::ChannelType>(rt.info.channel_type)) {
case Prospero::ChannelType::kUNorm: case Prospero::ChannelType::kUNorm:
@@ -312,7 +312,7 @@ void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const H
r->base_addr = 0; r->base_addr = 0;
r->vulkan_buffer = nullptr; r->vulkan_buffer = nullptr;
r->vulkan_view = nullptr; r->vulkan_view = nullptr;
r->format = VK_FORMAT_UNDEFINED; r->format = vk::Format::eUndefined;
r->extent = {}; r->extent = {};
r->base_mip_level = 0; r->base_mip_level = 0;
r->buffer_size = 0; r->buffer_size = 0;
@@ -480,8 +480,8 @@ void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const H
if (!render_to_texture && (levels != 1 || rt.view.current_mip_level != 0)) { if (!render_to_texture && (levels != 1 || rt.view.current_mip_level != 0)) {
EXIT("mipmapped display render targets are unsupported\n"); EXIT("mipmapped display render targets are unsupported\n");
} }
const VkExtent2D view_extent = {std::max(width >> rt.view.current_mip_level, 1u), const vk::Extent2D view_extent = {std::max(width >> rt.view.current_mip_level, 1u),
std::max(height >> rt.view.current_mip_level, 1u)}; std::max(height >> rt.view.current_mip_level, 1u)};
auto decision_log_id = g_render_color_log_count.fetch_add(1); auto decision_log_id = g_render_color_log_count.fetch_add(1);
if (decision_log_id < 128 || !render_to_texture) { if (decision_log_id < 128 || !render_to_texture) {
@@ -3,9 +3,9 @@
#include "graphics/guest_gpu/gpu_defs.h" #include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/host_gpu/renderer/renderTarget.h" #include "graphics/host_gpu/renderer/renderTarget.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <cstdint> #include <cstdint>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -25,9 +25,9 @@ enum class RenderColorType {
struct RenderColorInfo { struct RenderColorInfo {
RenderColorType type = RenderColorType::NoColorOutput; RenderColorType type = RenderColorType::NoColorOutput;
VulkanImage* vulkan_buffer = nullptr; VulkanImage* vulkan_buffer = nullptr;
VkImageView vulkan_view = nullptr; vk::ImageView vulkan_view = nullptr;
VkFormat format = VK_FORMAT_UNDEFINED; vk::Format format = vk::Format::eUndefined;
VkExtent2D extent = {}; vk::Extent2D extent = {};
uint32_t base_mip_level = 0; uint32_t base_mip_level = 0;
uint32_t base_array_layer = 0; uint32_t base_array_layer = 0;
uint64_t base_addr = 0; uint64_t base_addr = 0;
@@ -35,7 +35,7 @@ struct RenderColorInfo {
uint32_t target_slot = 0; uint32_t target_slot = 0;
Prospero::ColorComponentMapping export_mapping; Prospero::ColorComponentMapping export_mapping;
bool color_clear_enable = false; bool color_clear_enable = false;
VkClearColorValue color_clear_value {}; vk::ClearColorValue color_clear_value {};
}; };
void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const HW::Context& hw, void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const HW::Context& hw,
+135 -132
View File
@@ -14,13 +14,13 @@
#include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h" #include "graphics/host_gpu/vma.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/window.h" #include "graphics/presentation/window.h"
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <cstring> #include <cstring>
#include <memory> #include <memory>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics { namespace Libs::Graphics {
static std::atomic<uint64_t> g_command_buffer_submit_seq = 0; static std::atomic<uint64_t> g_command_buffer_submit_seq = 0;
class CommandPool { class CommandPool {
@@ -103,51 +103,53 @@ void CommandPool::Create(int id) {
pool = new VulkanCommandPool; pool = new VulkanCommandPool;
VkCommandPoolCreateInfo pool_info {}; vk::CommandPoolCreateInfo pool_info {};
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; pool_info.sType = vk::StructureType::eCommandPoolCreateInfo;
pool_info.pNext = nullptr; pool_info.pNext = nullptr;
pool_info.queueFamilyIndex = ctx->queues[id].family; pool_info.queueFamilyIndex = ctx->queues[id].family;
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; pool_info.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
vkCreateCommandPool(ctx->device, &pool_info, nullptr, &pool->pool); ctx->device.createCommandPool(&pool_info, nullptr, &pool->pool);
EXIT_NOT_IMPLEMENTED(pool->pool == nullptr); EXIT_NOT_IMPLEMENTED(pool->pool == nullptr);
pool->buffers_count = 8; pool->buffers_count = 8;
pool->buffers = std::make_unique<VkCommandBuffer[]>(pool->buffers_count); pool->buffers = std::make_unique<vk::CommandBuffer[]>(pool->buffers_count);
pool->fences = std::make_unique<VkFence[]>(pool->buffers_count); pool->fences = std::make_unique<vk::Fence[]>(pool->buffers_count);
pool->semaphores = std::make_unique<VkSemaphore[]>(pool->buffers_count); pool->semaphores = std::make_unique<vk::Semaphore[]>(pool->buffers_count);
pool->busy = std::make_unique<bool[]>(pool->buffers_count); pool->busy = std::make_unique<bool[]>(pool->buffers_count);
VkCommandBufferAllocateInfo alloc_info {}; vk::CommandBufferAllocateInfo alloc_info {};
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; alloc_info.sType = vk::StructureType::eCommandBufferAllocateInfo;
alloc_info.commandPool = pool->pool; alloc_info.commandPool = pool->pool;
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; alloc_info.level = vk::CommandBufferLevel::ePrimary;
alloc_info.commandBufferCount = pool->buffers_count; alloc_info.commandBufferCount = pool->buffers_count;
if (vkAllocateCommandBuffers(ctx->device, &alloc_info, pool->buffers.get()) != VK_SUCCESS) { if (ctx->device.allocateCommandBuffers(&alloc_info, pool->buffers.get()) !=
vk::Result::eSuccess) {
EXIT("Can't allocate command buffers"); EXIT("Can't allocate command buffers");
} }
for (uint32_t i = 0; i < pool->buffers_count; i++) { for (uint32_t i = 0; i < pool->buffers_count; i++) {
pool->busy[i] = false; pool->busy[i] = false;
VkFenceCreateInfo fence_info {}; vk::FenceCreateInfo fence_info {};
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fence_info.sType = vk::StructureType::eFenceCreateInfo;
fence_info.pNext = nullptr; fence_info.pNext = nullptr;
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; fence_info.flags = vk::FenceCreateFlagBits::eSignaled;
if (vkCreateFence(ctx->device, &fence_info, nullptr, &pool->fences[i]) != VK_SUCCESS) { if (ctx->device.createFence(&fence_info, nullptr, &pool->fences[i]) !=
vk::Result::eSuccess) {
EXIT("Can't create fence"); EXIT("Can't create fence");
} }
VkSemaphoreCreateInfo semaphore_info {}; vk::SemaphoreCreateInfo semaphore_info {};
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphore_info.sType = vk::StructureType::eSemaphoreCreateInfo;
semaphore_info.pNext = nullptr; semaphore_info.pNext = nullptr;
semaphore_info.flags = 0; semaphore_info.flags = {};
if (vkCreateSemaphore(ctx->device, &semaphore_info, nullptr, &pool->semaphores[i]) != if (ctx->device.createSemaphore(&semaphore_info, nullptr, &pool->semaphores[i]) !=
VK_SUCCESS) { vk::Result::eSuccess) {
EXIT("Can't create semaphore"); EXIT("Can't create semaphore");
} }
@@ -166,13 +168,13 @@ void CommandPool::DeleteAll() {
EXIT_IF(ctx->device == nullptr); EXIT_IF(ctx->device == nullptr);
for (uint32_t i = 0; i < pool->buffers_count; i++) { for (uint32_t i = 0; i < pool->buffers_count; i++) {
vkDestroySemaphore(ctx->device, pool->semaphores[i], nullptr); ctx->device.destroySemaphore(pool->semaphores[i], nullptr);
vkDestroyFence(ctx->device, pool->fences[i], nullptr); ctx->device.destroyFence(pool->fences[i], nullptr);
} }
vkFreeCommandBuffers(ctx->device, pool->pool, pool->buffers_count, pool->buffers.get()); ctx->device.freeCommandBuffers(pool->pool, pool->buffers_count, pool->buffers.get());
vkDestroyCommandPool(ctx->device, pool->pool, nullptr); ctx->device.destroyCommandPool(pool->pool, nullptr);
delete pool; delete pool;
pool = nullptr; pool = nullptr;
@@ -202,7 +204,7 @@ void CommandBuffer::Allocate() {
for (uint32_t i = 0; i < m_pool->buffers_count; i++) { for (uint32_t i = 0; i < m_pool->buffers_count; i++) {
if (!m_pool->busy[i]) { if (!m_pool->busy[i]) {
m_pool->busy[i] = true; m_pool->busy[i] = true;
vkResetCommandBuffer(m_pool->buffers[i], VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); m_pool->buffers[i].reset(vk::CommandBufferResetFlagBits::eReleaseResources);
m_index = i; m_index = i;
break; break;
} }
@@ -221,7 +223,7 @@ void CommandBuffer::Free() {
m_host_stream.Release(); m_host_stream.Release();
m_pool->busy[m_index] = false; m_pool->busy[m_index] = false;
vkResetCommandBuffer(m_pool->buffers[m_index], VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); m_pool->buffers[m_index].reset(vk::CommandBufferResetFlagBits::eReleaseResources);
RecycleDescriptorsAfterFence(); RecycleDescriptorsAfterFence();
m_fence_resources.ReleaseAfterFence(); m_fence_resources.ReleaseAfterFence();
m_index = static_cast<uint32_t>(-1); m_index = static_cast<uint32_t>(-1);
@@ -258,27 +260,27 @@ void CommandBuffer::RecycleDescriptorsAfterFence() {
void CommandBuffer::Begin() const { void CommandBuffer::Begin() const {
EXIT_IF(IsInvalid()); EXIT_IF(IsInvalid());
auto* buffer = m_pool->buffers[m_index]; auto buffer = m_pool->buffers[m_index];
VkCommandBufferBeginInfo begin_info {}; vk::CommandBufferBeginInfo begin_info {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; begin_info.sType = vk::StructureType::eCommandBufferBeginInfo;
begin_info.pNext = nullptr; begin_info.pNext = nullptr;
begin_info.flags = 0; begin_info.flags = {};
begin_info.pInheritanceInfo = nullptr; begin_info.pInheritanceInfo = nullptr;
auto result = vkBeginCommandBuffer(buffer, &begin_info); auto result = buffer.begin(&begin_info);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
} }
void CommandBuffer::End() const { void CommandBuffer::End() const {
EXIT_IF(IsInvalid()); EXIT_IF(IsInvalid());
auto* buffer = m_pool->buffers[m_index]; auto buffer = m_pool->buffers[m_index];
auto result = vkEndCommandBuffer(buffer); auto result = buffer.end();
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
} }
void CommandBuffer::SetDebugInfo(uint32_t op, uint64_t submit_id, uint32_t arg0, uint32_t arg1, void CommandBuffer::SetDebugInfo(uint32_t op, uint64_t submit_id, uint32_t arg0, uint32_t arg1,
@@ -296,11 +298,11 @@ void CommandBuffer::Execute() {
EXIT_IF(IsInvalid()); EXIT_IF(IsInvalid());
EXIT_IF(m_execute); EXIT_IF(m_execute);
auto* buffer = m_pool->buffers[m_index]; auto buffer = m_pool->buffers[m_index];
auto* fence = m_pool->fences[m_index]; auto fence = m_pool->fences[m_index];
VkSubmitInfo submit_info {}; vk::SubmitInfo submit_info {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.sType = vk::StructureType::eSubmitInfo;
submit_info.pNext = nullptr; submit_info.pNext = nullptr;
submit_info.waitSemaphoreCount = 0; submit_info.waitSemaphoreCount = 0;
submit_info.pWaitSemaphores = nullptr; submit_info.pWaitSemaphores = nullptr;
@@ -314,12 +316,12 @@ void CommandBuffer::Execute() {
const auto& queue = g_render_ctx->GetGraphicCtx()->queues[m_queue]; const auto& queue = g_render_ctx->GetGraphicCtx()->queues[m_queue];
auto result = vkResetFences(g_render_ctx->GetGraphicCtx()->device, 1, &fence); auto result = g_render_ctx->GetGraphicCtx()->device.resetFences(1, &fence);
if (result != VK_SUCCESS) { if (result != vk::Result::eSuccess) {
LOGF("vkResetFences failed before submit: %s (%d)\n", string_VkResult(result), LOGF("vkResetFences failed before submit: %s (%d)\n", VulkanToString(result).c_str(),
static_cast<int>(result)); static_cast<int>(result));
} }
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
if (queue.mutex != nullptr) { if (queue.mutex != nullptr) {
queue.mutex->Lock(); queue.mutex->Lock();
@@ -332,7 +334,7 @@ void CommandBuffer::Execute() {
m_debug_arg2, m_debug_arg3, m_debug_arg4); m_debug_arg2, m_debug_arg3, m_debug_arg4);
} }
result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence); result = queue.vk_queue.submit(1, &submit_info, fence);
if (queue.mutex != nullptr) { if (queue.mutex != nullptr) {
queue.mutex->Unlock(); queue.mutex->Unlock();
@@ -342,29 +344,29 @@ void CommandBuffer::Execute() {
m_fence_waited = false; m_fence_waited = false;
m_submit_seq = g_command_buffer_submit_seq.fetch_add(1, std::memory_order_relaxed) + 1; m_submit_seq = g_command_buffer_submit_seq.fetch_add(1, std::memory_order_relaxed) + 1;
if (result != VK_SUCCESS) { if (result != vk::Result::eSuccess) {
LOGF("vkQueueSubmit failed: %s (%d), queue=%d index=%u submit_seq=%" PRIu64 LOGF("vkQueueSubmit failed: %s (%d), queue=%d index=%u submit_seq=%" PRIu64
" debug_op=%u debug_submit=%" PRIu64 " args=%u,%u,%u,%u,0x%016" PRIx64 "\n", " debug_op=%u debug_submit=%" PRIu64 " args=%u,%u,%u,%u,0x%016" PRIx64 "\n",
string_VkResult(result), static_cast<int>(result), m_queue, m_index, m_submit_seq, VulkanToString(result).c_str(), static_cast<int>(result), m_queue, m_index,
m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2, m_debug_arg3, m_submit_seq, m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2,
m_debug_arg4); m_debug_arg3, m_debug_arg4);
} }
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
} }
void CommandBuffer::ExecuteWithSemaphore(VkSemaphore signal_semaphore) { void CommandBuffer::ExecuteWithSemaphore(vk::Semaphore signal_semaphore) {
EXIT_IF(IsInvalid()); EXIT_IF(IsInvalid());
EXIT_IF(m_execute); EXIT_IF(m_execute);
auto* buffer = m_pool->buffers[m_index]; auto buffer = m_pool->buffers[m_index];
auto* fence = m_pool->fences[m_index]; auto fence = m_pool->fences[m_index];
if (signal_semaphore == nullptr) { if (signal_semaphore == nullptr) {
signal_semaphore = m_pool->semaphores[m_index]; signal_semaphore = m_pool->semaphores[m_index];
} }
VkSubmitInfo submit_info {}; vk::SubmitInfo submit_info {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.sType = vk::StructureType::eSubmitInfo;
submit_info.pNext = nullptr; submit_info.pNext = nullptr;
submit_info.waitSemaphoreCount = 0; submit_info.waitSemaphoreCount = 0;
submit_info.pWaitSemaphores = nullptr; submit_info.pWaitSemaphores = nullptr;
@@ -378,12 +380,12 @@ void CommandBuffer::ExecuteWithSemaphore(VkSemaphore signal_semaphore) {
const auto& queue = g_render_ctx->GetGraphicCtx()->queues[m_queue]; const auto& queue = g_render_ctx->GetGraphicCtx()->queues[m_queue];
auto result = vkResetFences(g_render_ctx->GetGraphicCtx()->device, 1, &fence); auto result = g_render_ctx->GetGraphicCtx()->device.resetFences(1, &fence);
if (result != VK_SUCCESS) { if (result != vk::Result::eSuccess) {
LOGF("vkResetFences failed before submit: %s (%d)\n", string_VkResult(result), LOGF("vkResetFences failed before submit: %s (%d)\n", VulkanToString(result).c_str(),
static_cast<int>(result)); static_cast<int>(result));
} }
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
if (queue.mutex != nullptr) { if (queue.mutex != nullptr) {
queue.mutex->Lock(); queue.mutex->Lock();
@@ -396,7 +398,7 @@ void CommandBuffer::ExecuteWithSemaphore(VkSemaphore signal_semaphore) {
m_debug_arg0, m_debug_arg1, m_debug_arg2, m_debug_arg3, m_debug_arg4); m_debug_arg0, m_debug_arg1, m_debug_arg2, m_debug_arg3, m_debug_arg4);
} }
result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence); result = queue.vk_queue.submit(1, &submit_info, fence);
if (queue.mutex != nullptr) { if (queue.mutex != nullptr) {
queue.mutex->Unlock(); queue.mutex->Unlock();
@@ -406,32 +408,32 @@ void CommandBuffer::ExecuteWithSemaphore(VkSemaphore signal_semaphore) {
m_fence_waited = false; m_fence_waited = false;
m_submit_seq = g_command_buffer_submit_seq.fetch_add(1, std::memory_order_relaxed) + 1; m_submit_seq = g_command_buffer_submit_seq.fetch_add(1, std::memory_order_relaxed) + 1;
if (result != VK_SUCCESS) { if (result != vk::Result::eSuccess) {
LOGF("vkQueueSubmit failed: %s (%d), queue=%d index=%u submit_seq=%" PRIu64 LOGF("vkQueueSubmit failed: %s (%d), queue=%d index=%u submit_seq=%" PRIu64
" debug_op=%u debug_submit=%" PRIu64 " args=%u,%u,%u,%u,0x%016" PRIx64 "\n", " debug_op=%u debug_submit=%" PRIu64 " args=%u,%u,%u,%u,0x%016" PRIx64 "\n",
string_VkResult(result), static_cast<int>(result), m_queue, m_index, m_submit_seq, VulkanToString(result).c_str(), static_cast<int>(result), m_queue, m_index,
m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2, m_debug_arg3, m_submit_seq, m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2,
m_debug_arg4); m_debug_arg3, m_debug_arg4);
} }
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
} }
void CommandBuffer::ExecuteWithSemaphore(VkSemaphore wait_semaphore, void CommandBuffer::ExecuteWithSemaphore(vk::Semaphore wait_semaphore,
VkPipelineStageFlags wait_stage, vk::PipelineStageFlags wait_stage,
VkSemaphore signal_semaphore) { vk::Semaphore signal_semaphore) {
EXIT_IF(IsInvalid()); EXIT_IF(IsInvalid());
EXIT_IF(m_execute); EXIT_IF(m_execute);
EXIT_IF(wait_semaphore == nullptr); EXIT_IF(wait_semaphore == nullptr);
auto* buffer = m_pool->buffers[m_index]; auto buffer = m_pool->buffers[m_index];
auto* fence = m_pool->fences[m_index]; auto fence = m_pool->fences[m_index];
if (signal_semaphore == nullptr) { if (signal_semaphore == nullptr) {
signal_semaphore = m_pool->semaphores[m_index]; signal_semaphore = m_pool->semaphores[m_index];
} }
VkSubmitInfo submit_info {}; vk::SubmitInfo submit_info {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.sType = vk::StructureType::eSubmitInfo;
submit_info.pNext = nullptr; submit_info.pNext = nullptr;
submit_info.waitSemaphoreCount = 1; submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &wait_semaphore; submit_info.pWaitSemaphores = &wait_semaphore;
@@ -445,12 +447,12 @@ void CommandBuffer::ExecuteWithSemaphore(VkSemaphore wait_semaphore,
const auto& queue = g_render_ctx->GetGraphicCtx()->queues[m_queue]; const auto& queue = g_render_ctx->GetGraphicCtx()->queues[m_queue];
auto result = vkResetFences(g_render_ctx->GetGraphicCtx()->device, 1, &fence); auto result = g_render_ctx->GetGraphicCtx()->device.resetFences(1, &fence);
if (result != VK_SUCCESS) { if (result != vk::Result::eSuccess) {
LOGF("vkResetFences failed before submit: %s (%d)\n", string_VkResult(result), LOGF("vkResetFences failed before submit: %s (%d)\n", VulkanToString(result).c_str(),
static_cast<int>(result)); static_cast<int>(result));
} }
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
if (queue.mutex != nullptr) { if (queue.mutex != nullptr) {
queue.mutex->Lock(); queue.mutex->Lock();
@@ -464,7 +466,7 @@ void CommandBuffer::ExecuteWithSemaphore(VkSemaphore wait_semaphore,
m_debug_arg1, m_debug_arg2, m_debug_arg3, m_debug_arg4); m_debug_arg1, m_debug_arg2, m_debug_arg3, m_debug_arg4);
} }
result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence); result = queue.vk_queue.submit(1, &submit_info, fence);
if (queue.mutex != nullptr) { if (queue.mutex != nullptr) {
queue.mutex->Unlock(); queue.mutex->Unlock();
@@ -474,14 +476,14 @@ void CommandBuffer::ExecuteWithSemaphore(VkSemaphore wait_semaphore,
m_fence_waited = false; m_fence_waited = false;
m_submit_seq = g_command_buffer_submit_seq.fetch_add(1, std::memory_order_relaxed) + 1; m_submit_seq = g_command_buffer_submit_seq.fetch_add(1, std::memory_order_relaxed) + 1;
if (result != VK_SUCCESS) { if (result != vk::Result::eSuccess) {
LOGF("vkQueueSubmit failed: %s (%d), queue=%d index=%u submit_seq=%" PRIu64 LOGF("vkQueueSubmit failed: %s (%d), queue=%d index=%u submit_seq=%" PRIu64
" debug_op=%u debug_submit=%" PRIu64 " args=%u,%u,%u,%u,0x%016" PRIx64 "\n", " debug_op=%u debug_submit=%" PRIu64 " args=%u,%u,%u,%u,0x%016" PRIx64 "\n",
string_VkResult(result), static_cast<int>(result), m_queue, m_index, m_submit_seq, VulkanToString(result).c_str(), static_cast<int>(result), m_queue, m_index,
m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2, m_debug_arg3, m_submit_seq, m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2,
m_debug_arg4); m_debug_arg3, m_debug_arg4);
} }
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
} }
void CommandBuffer::WaitForFence() { void CommandBuffer::WaitForFence() {
@@ -505,16 +507,16 @@ void CommandBuffer::WaitForFenceOnly() {
if (!m_execute || m_fence_waited) { if (!m_execute || m_fence_waited) {
return; return;
} }
auto* device = g_render_ctx->GetGraphicCtx()->device; auto device = g_render_ctx->GetGraphicCtx()->device;
auto result = vkWaitForFences(device, 1, &m_pool->fences[m_index], VK_TRUE, UINT64_MAX); auto result = device.waitForFences(1, &m_pool->fences[m_index], VK_TRUE, UINT64_MAX);
if (result != VK_SUCCESS) { if (result != vk::Result::eSuccess) {
LOGF("vkWaitForFences failed: %s (%d), queue=%d index=%u submit_seq=%" PRIu64 LOGF("vkWaitForFences failed: %s (%d), queue=%d index=%u submit_seq=%" PRIu64
" debug_op=%u debug_submit=%" PRIu64 " args=%u,%u,%u,%u,0x%016" PRIx64 "\n", " debug_op=%u debug_submit=%" PRIu64 " args=%u,%u,%u,%u,0x%016" PRIx64 "\n",
string_VkResult(result), static_cast<int>(result), m_queue, m_index, m_submit_seq, VulkanToString(result).c_str(), static_cast<int>(result), m_queue, m_index,
m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2, m_debug_arg3, m_submit_seq, m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2,
m_debug_arg4); m_debug_arg3, m_debug_arg4);
} }
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
m_fence_waited = true; m_fence_waited = true;
} }
@@ -524,8 +526,7 @@ void CommandBuffer::WaitForFenceAndReset() {
if (was_executed) { if (was_executed) {
m_execute = false; m_execute = false;
m_fence_waited = false; m_fence_waited = false;
vkResetCommandBuffer(m_pool->buffers[m_index], m_pool->buffers[m_index].reset(vk::CommandBufferResetFlagBits::eReleaseResources);
VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
m_recording_generation++; m_recording_generation++;
} }
m_host_stream.Reset(); m_host_stream.Reset();
@@ -544,13 +545,13 @@ void CommandBuffer::BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorI
uint32_t requested_color_count, RenderDepthInfo* depth) const { uint32_t requested_color_count, RenderDepthInfo* depth) const {
EXIT_IF(IsInvalid()); EXIT_IF(IsInvalid());
auto* buffer = m_pool->buffers[m_index]; auto buffer = m_pool->buffers[m_index];
EXIT_IF(framebuffer == nullptr); EXIT_IF(framebuffer == nullptr);
EXIT_IF(colors == nullptr); EXIT_IF(colors == nullptr);
EXIT_IF(requested_color_count > RENDER_COLOR_ATTACHMENTS_MAX); EXIT_IF(requested_color_count > RENDER_COLOR_ATTACHMENTS_MAX);
bool with_depth = (depth->format != VK_FORMAT_UNDEFINED && depth->vulkan_buffer != nullptr); bool with_depth = (depth->format != vk::Format::eUndefined && depth->vulkan_buffer != nullptr);
uint32_t color_count = 0; uint32_t color_count = 0;
for (uint32_t i = 0; i < requested_color_count; i++) { for (uint32_t i = 0; i < requested_color_count; i++) {
if (colors[i].vulkan_buffer == nullptr) { if (colors[i].vulkan_buffer == nullptr) {
@@ -562,16 +563,16 @@ void CommandBuffer::BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorI
EXIT_NOT_IMPLEMENTED(!with_depth && !with_color); EXIT_NOT_IMPLEMENTED(!with_depth && !with_color);
VkClearValue clears[RENDER_COLOR_ATTACHMENTS_MAX + 1] = {}; vk::ClearValue clears[RENDER_COLOR_ATTACHMENTS_MAX + 1] = {};
for (uint32_t i = 0; i < color_count; i++) { for (uint32_t i = 0; i < color_count; i++) {
clears[i].color = colors[i].color_clear_value; clears[i].color = colors[i].color_clear_value;
} }
clears[color_count].depthStencil = {depth->depth_clear_value, depth->stencil_clear_value}; clears[color_count].depthStencil = {depth->depth_clear_value, depth->stencil_clear_value};
VkExtent2D extent = (with_color ? colors[0].extent : depth->vulkan_buffer->extent); vk::Extent2D extent = (with_color ? colors[0].extent : depth->vulkan_buffer->extent);
VkRenderPassBeginInfo render_pass_info {}; vk::RenderPassBeginInfo render_pass_info {};
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; render_pass_info.sType = vk::StructureType::eRenderPassBeginInfo;
render_pass_info.pNext = nullptr; render_pass_info.pNext = nullptr;
render_pass_info.renderPass = framebuffer->render_pass; render_pass_info.renderPass = framebuffer->render_pass;
render_pass_info.framebuffer = framebuffer->framebuffer; render_pass_info.framebuffer = framebuffer->framebuffer;
@@ -585,55 +586,57 @@ void CommandBuffer::BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorI
if (colors[i].vulkan_buffer->layout != color_initial_layout) { if (colors[i].vulkan_buffer->layout != color_initial_layout) {
if (graphics_debug_dump_enabled()) { if (graphics_debug_dump_enabled()) {
LOGF("BeginRenderPass: color%u initial barrier image=%p mem=%" PRIu64 " %s -> %s\n", LOGF("BeginRenderPass: color%u initial barrier image=%p mem=%" PRIu64 " %s -> %s\n",
i, reinterpret_cast<void*>(colors[i].vulkan_buffer->image), i, VulkanHandleToPointer(colors[i].vulkan_buffer->image),
colors[i].vulkan_buffer->memory.unique_id, colors[i].vulkan_buffer->memory.unique_id,
string_VkImageLayout(colors[i].vulkan_buffer->layout), VulkanToString(colors[i].vulkan_buffer->layout).c_str(),
string_VkImageLayout(color_initial_layout)); VulkanToString(color_initial_layout).c_str());
} }
VkImageMemoryBarrier image_memory_barrier {}; vk::ImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; image_memory_barrier.sType = vk::StructureType::eImageMemoryBarrier;
image_memory_barrier.pNext = nullptr; image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = 0; image_memory_barrier.srcAccessMask = {};
image_memory_barrier.dstAccessMask = image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; vk::AccessFlagBits::eColorAttachmentWrite;
image_memory_barrier.oldLayout = colors[i].vulkan_buffer->layout; image_memory_barrier.oldLayout = colors[i].vulkan_buffer->layout;
image_memory_barrier.newLayout = color_initial_layout; image_memory_barrier.newLayout = color_initial_layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = colors[i].vulkan_buffer->image; image_memory_barrier.image = colors[i].vulkan_buffer->image;
image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_memory_barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
image_memory_barrier.subresourceRange.baseMipLevel = 0; image_memory_barrier.subresourceRange.baseMipLevel = 0;
image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
image_memory_barrier.subresourceRange.baseArrayLayer = 0; image_memory_barrier.subresourceRange.baseArrayLayer = 0;
image_memory_barrier.subresourceRange.layerCount = colors[i].vulkan_buffer->layers; image_memory_barrier.subresourceRange.layerCount = colors[i].vulkan_buffer->layers;
vkCmdPipelineBarrier(buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, vk::PipelineStageFlagBits::eColorAttachmentOutput,
nullptr, 1, &image_memory_barrier); vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1,
&image_memory_barrier);
colors[i].vulkan_buffer->layout = image_memory_barrier.newLayout; colors[i].vulkan_buffer->layout = image_memory_barrier.newLayout;
} else if (graphics_debug_dump_enabled()) { } else if (graphics_debug_dump_enabled()) {
LOGF("BeginRenderPass: color%u initial image=%p mem=%" PRIu64 " layout=%s\n", i, LOGF("BeginRenderPass: color%u initial image=%p mem=%" PRIu64 " layout=%s\n", i,
reinterpret_cast<void*>(colors[i].vulkan_buffer->image), VulkanHandleToPointer(colors[i].vulkan_buffer->image),
colors[i].vulkan_buffer->memory.unique_id, colors[i].vulkan_buffer->memory.unique_id,
string_VkImageLayout(colors[i].vulkan_buffer->layout)); VulkanToString(colors[i].vulkan_buffer->layout).c_str());
} }
} }
const auto depth_layout = const auto depth_layout =
(with_depth && framebuffer != nullptr ? framebuffer->depth_layout (with_depth && framebuffer != nullptr ? framebuffer->depth_layout
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); : vk::ImageLayout::eDepthStencilAttachmentOptimal);
if (with_depth && depth->vulkan_buffer->layout != depth_layout) { if (with_depth && depth->vulkan_buffer->layout != depth_layout) {
VkImageMemoryBarrier image_memory_barrier {}; vk::ImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; image_memory_barrier.sType = vk::StructureType::eImageMemoryBarrier;
image_memory_barrier.pNext = nullptr; image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; image_memory_barrier.srcAccessMask =
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
image_memory_barrier.dstAccessMask = image_memory_barrier.dstAccessMask =
(depth_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL (depth_layout == vk::ImageLayout::eDepthStencilReadOnlyOptimal
? VK_ACCESS_MEMORY_READ_BIT ? vk::AccessFlagBits::eMemoryRead
: VK_ACCESS_MEMORY_WRITE_BIT); : vk::AccessFlagBits::eMemoryWrite);
image_memory_barrier.oldLayout = depth->vulkan_buffer->layout; image_memory_barrier.oldLayout = depth->vulkan_buffer->layout;
image_memory_barrier.newLayout = depth_layout; image_memory_barrier.newLayout = depth_layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@@ -646,15 +649,15 @@ void CommandBuffer::BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorI
image_memory_barrier.subresourceRange.baseArrayLayer = 0; image_memory_barrier.subresourceRange.baseArrayLayer = 0;
image_memory_barrier.subresourceRange.layerCount = depth->vulkan_buffer->layers; image_memory_barrier.subresourceRange.layerCount = depth->vulkan_buffer->layers;
vkCmdPipelineBarrier( buffer.pipelineBarrier(
buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader,
nullptr, 0, nullptr, 1, &image_memory_barrier); vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
depth->vulkan_buffer->layout = image_memory_barrier.newLayout; depth->vulkan_buffer->layout = image_memory_barrier.newLayout;
} }
vkCmdBeginRenderPass(buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); buffer.beginRenderPass(&render_pass_info, vk::SubpassContents::eInline);
for (uint32_t i = 0; i < color_count; i++) { for (uint32_t i = 0; i < color_count; i++) {
colors[i].vulkan_buffer->layout = RENDER_COLOR_IMAGE_LAYOUT; colors[i].vulkan_buffer->layout = RENDER_COLOR_IMAGE_LAYOUT;
@@ -664,9 +667,9 @@ void CommandBuffer::BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorI
void CommandBuffer::EndRenderPass() const { void CommandBuffer::EndRenderPass() const {
EXIT_IF(IsInvalid()); EXIT_IF(IsInvalid());
auto* buffer = m_pool->buffers[m_index]; auto buffer = m_pool->buffers[m_index];
vkCmdEndRenderPass(buffer); buffer.endRenderPass();
} }
} // namespace Libs::Graphics } // namespace Libs::Graphics
+1 -1
View File
@@ -1168,7 +1168,7 @@ static bool ScissorClipRuleToIntersectionMask(uint16_t rule, uint8_t* mask) {
} }
ScissorRect calc_final_scissor(const HW::ScreenViewport& vp, const HW::ScanModeControl& smc, ScissorRect calc_final_scissor(const HW::ScreenViewport& vp, const HW::ScanModeControl& smc,
VkExtent2D extent) { vk::Extent2D extent) {
ScissorRect screen {vp.screen_scissor_left, vp.screen_scissor_top, vp.screen_scissor_right, ScissorRect screen {vp.screen_scissor_left, vp.screen_scissor_top, vp.screen_scissor_right,
vp.screen_scissor_bottom}; vp.screen_scissor_bottom};
ScissorRect final = screen; ScissorRect final = screen;
+3 -2
View File
@@ -1,10 +1,11 @@
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DEBUG_H_ #ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DEBUG_H_
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DEBUG_H_ #define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DEBUG_H_
#include "graphics/host_gpu/vulkanCommon.h"
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <vector> #include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -37,7 +38,7 @@ void hw_print(const HW::Context& hw);
void hw_check(const HW::Context& hw); void hw_check(const HW::Context& hw);
void LogDrawPhase(const char* draw_name, const char* phase); void LogDrawPhase(const char* draw_name, const char* phase);
ScissorRect calc_final_scissor(const HW::ScreenViewport& vp, const HW::ScanModeControl& smc, ScissorRect calc_final_scissor(const HW::ScreenViewport& vp, const HW::ScanModeControl& smc,
VkExtent2D extent); vk::Extent2D extent);
} // namespace Libs::Graphics } // namespace Libs::Graphics
@@ -17,6 +17,7 @@
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/displayBuffer.h" #include "graphics/presentation/displayBuffer.h"
#include <algorithm> #include <algorithm>
@@ -25,7 +26,6 @@
#include <cstdarg> #include <cstdarg>
#include <cstdio> #include <cstdio>
#include <limits> #include <limits>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -40,17 +40,17 @@ namespace Libs::Graphics {
EXIT("unsupported render state; details were printed above\n"); EXIT("unsupported render state; details were printed above\n");
} }
static VkStencilOp ConvertStencilOp(uint8_t value) { static vk::StencilOp ConvertStencilOp(uint8_t value) {
switch (static_cast<Prospero::StencilOp>(value)) { switch (static_cast<Prospero::StencilOp>(value)) {
case Prospero::StencilOp::kKeep: return VK_STENCIL_OP_KEEP; case Prospero::StencilOp::kKeep: return vk::StencilOp::eKeep;
case Prospero::StencilOp::kZero: return VK_STENCIL_OP_ZERO; case Prospero::StencilOp::kZero: return vk::StencilOp::eZero;
case Prospero::StencilOp::kReplaceTest: case Prospero::StencilOp::kReplaceTest:
case Prospero::StencilOp::kReplaceOp: return VK_STENCIL_OP_REPLACE; case Prospero::StencilOp::kReplaceOp: return vk::StencilOp::eReplace;
case Prospero::StencilOp::kAddClamp: return VK_STENCIL_OP_INCREMENT_AND_CLAMP; case Prospero::StencilOp::kAddClamp: return vk::StencilOp::eIncrementAndClamp;
case Prospero::StencilOp::kSubClamp: return VK_STENCIL_OP_DECREMENT_AND_CLAMP; case Prospero::StencilOp::kSubClamp: return vk::StencilOp::eDecrementAndClamp;
case Prospero::StencilOp::kInvert: return VK_STENCIL_OP_INVERT; case Prospero::StencilOp::kInvert: return vk::StencilOp::eInvert;
case Prospero::StencilOp::kAddWrap: return VK_STENCIL_OP_INCREMENT_AND_WRAP; case Prospero::StencilOp::kAddWrap: return vk::StencilOp::eIncrementAndWrap;
case Prospero::StencilOp::kSubWrap: return VK_STENCIL_OP_DECREMENT_AND_WRAP; case Prospero::StencilOp::kSubWrap: return vk::StencilOp::eDecrementAndWrap;
default: DepthFatal("unsupported stencil operation"); default: DepthFatal("unsupported stencil operation");
} }
} }
@@ -61,9 +61,9 @@ static bool UsesStencilOpValue(uint8_t fail, uint8_t pass, uint8_t depth_fail) {
depth_fail == Prospero::GpuEnumValue(Prospero::StencilOp::kReplaceOp); depth_fail == Prospero::GpuEnumValue(Prospero::StencilOp::kReplaceOp);
} }
[[nodiscard]] static VkFormat ResolveHostDepthAttachmentFormat(GraphicContext* ctx, [[nodiscard]] static vk::Format ResolveHostDepthAttachmentFormat(GraphicContext* ctx,
const DepthFormatPolicy& policy, const DepthFormatPolicy& policy,
bool has_stencil) { bool has_stencil) {
if (!has_stencil) { if (!has_stencil) {
return policy.depth_attachment_format; return policy.depth_attachment_format;
} }
@@ -71,19 +71,20 @@ static bool UsesStencilOpValue(uint8_t fail, uint8_t pass, uint8_t depth_fail) {
case Prospero::DepthFormat::kZ32F: return policy.stencil_attachment_formats.front(); case Prospero::DepthFormat::kZ32F: return policy.stencil_attachment_formats.front();
case Prospero::DepthFormat::kZ16: { case Prospero::DepthFormat::kZ16: {
if (ctx == nullptr) { if (ctx == nullptr) {
return VK_FORMAT_UNDEFINED; return vk::Format::eUndefined;
} }
for (const auto format: policy.stencil_attachment_formats) { for (const auto format: policy.stencil_attachment_formats) {
VkImageFormatProperties properties {}; vk::ImageFormatProperties properties {};
if (ctx->GetImageFormatProperties(format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, if (ctx->GetImageFormatProperties(format, vk::ImageType::e2D,
DepthTargetImageUsage(), 0, vk::ImageTiling::eOptimal,
&properties) == VK_SUCCESS) { DepthTargetImageUsage(), vk::ImageCreateFlags {},
&properties) == vk::Result::eSuccess) {
return format; return format;
} }
} }
return VK_FORMAT_UNDEFINED; return vk::Format::eUndefined;
} }
default: return VK_FORMAT_UNDEFINED; default: return vk::Format::eUndefined;
} }
} }
@@ -172,7 +173,7 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
z.htile_surface.prefetch_width != 0 || z.htile_surface.prefetch_height != 0 || z.htile_surface.prefetch_width != 0 || z.htile_surface.prefetch_height != 0 ||
z.htile_surface.dst_outside_zero_to_one != 0 || z.z_read_base_addr == 0 || z.htile_surface.dst_outside_zero_to_one != 0 || z.z_read_base_addr == 0 ||
z.z_write_base_addr != z.z_read_base_addr || (z.z_read_base_addr & 0xffffu) != 0 || z.z_write_base_addr != z.z_read_base_addr || (z.z_read_base_addr & 0xffffu) != 0 ||
dc.zfunc > static_cast<uint8_t>(VK_COMPARE_OP_ALWAYS)) { dc.zfunc > static_cast<uint8_t>(vk::CompareOp::eAlways)) {
DepthFatal("unsupported depth register state"); DepthFatal("unsupported depth register state");
} }
if (msaa_compat) { if (msaa_compat) {
@@ -237,9 +238,9 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
const auto ideal_format = DepthAttachmentFormat(*policy, has_stencil); const auto ideal_format = DepthAttachmentFormat(*policy, has_stencil);
r->format = r->format =
ResolveHostDepthAttachmentFormat(g_render_ctx->GetGraphicCtx(), *policy, has_stencil); ResolveHostDepthAttachmentFormat(g_render_ctx->GetGraphicCtx(), *policy, has_stencil);
if (r->format == VK_FORMAT_UNDEFINED) { if (r->format == vk::Format::eUndefined) {
DepthFatal("no host depth/stencil format supports required usage for %s", DepthFatal("no host depth/stencil format supports required usage for %s",
string_VkFormat(ideal_format)); VulkanToString(ideal_format).c_str());
} }
const uint32_t guest_format = Prospero::GpuEnumValue(policy->guest_format); const uint32_t guest_format = Prospero::GpuEnumValue(policy->guest_format);
const uint32_t bytes = policy->bytes_per_element; const uint32_t bytes = policy->bytes_per_element;
@@ -324,7 +325,7 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
r->depth_clear_value = hw.GetDepthClearValue(); r->depth_clear_value = hw.GetDepthClearValue();
r->depth_test_enable = dc.z_enable; r->depth_test_enable = dc.z_enable;
r->depth_write_enable = dc.z_write_enable && !z.depth_view.depth_write_disable; r->depth_write_enable = dc.z_write_enable && !z.depth_view.depth_write_disable;
r->depth_compare_op = static_cast<VkCompareOp>(dc.zfunc); r->depth_compare_op = static_cast<vk::CompareOp>(dc.zfunc);
r->depth_bounds_test_enable = dc.depth_bounds_enable; r->depth_bounds_test_enable = dc.depth_bounds_enable;
r->depth_min_bounds = hw.GetDepthBoundsMin(); r->depth_min_bounds = hw.GetDepthBoundsMin();
@@ -334,9 +335,9 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
r->stencil_clear_value = hw.GetStencilClearValue(); r->stencil_clear_value = hw.GetStencilClearValue();
r->stencil_test_enable = dc.stencil_enable; r->stencil_test_enable = dc.stencil_enable;
if (dc.stencil_enable) { if (dc.stencil_enable) {
if (dc.stencilfunc > static_cast<uint8_t>(VK_COMPARE_OP_ALWAYS) || if (dc.stencilfunc > static_cast<uint8_t>(vk::CompareOp::eAlways) ||
(dc.backface_enable && (dc.backface_enable &&
dc.stencilfunc_bf > static_cast<uint8_t>(VK_COMPARE_OP_ALWAYS)) || dc.stencilfunc_bf > static_cast<uint8_t>(vk::CompareOp::eAlways)) ||
(UsesStencilOpValue(sc.stencil_fail, sc.stencil_zpass, sc.stencil_zfail) && (UsesStencilOpValue(sc.stencil_fail, sc.stencil_zpass, sc.stencil_zfail) &&
sm.stencil_opval != sm.stencil_testval) || sm.stencil_opval != sm.stencil_testval) ||
(dc.backface_enable && (dc.backface_enable &&
@@ -346,14 +347,15 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
} }
r->stencil_static_front = { r->stencil_static_front = {
ConvertStencilOp(sc.stencil_fail), ConvertStencilOp(sc.stencil_zpass), ConvertStencilOp(sc.stencil_fail), ConvertStencilOp(sc.stencil_zpass),
ConvertStencilOp(sc.stencil_zfail), static_cast<VkCompareOp>(dc.stencilfunc)}; ConvertStencilOp(sc.stencil_zfail), static_cast<vk::CompareOp>(dc.stencilfunc)};
r->stencil_dynamic_front = {sm.stencil_mask, r->stencil_dynamic_front = {sm.stencil_mask,
rc.stencil_clear_enable ? 0u : sm.stencil_writemask, rc.stencil_clear_enable ? 0u : sm.stencil_writemask,
sm.stencil_testval}; sm.stencil_testval};
if (dc.backface_enable) { if (dc.backface_enable) {
r->stencil_static_back = { r->stencil_static_back = {ConvertStencilOp(sc.stencil_fail_bf),
ConvertStencilOp(sc.stencil_fail_bf), ConvertStencilOp(sc.stencil_zpass_bf), ConvertStencilOp(sc.stencil_zpass_bf),
ConvertStencilOp(sc.stencil_zfail_bf), static_cast<VkCompareOp>(dc.stencilfunc_bf)}; ConvertStencilOp(sc.stencil_zfail_bf),
static_cast<vk::CompareOp>(dc.stencilfunc_bf)};
r->stencil_dynamic_back = {sm.stencil_mask_bf, r->stencil_dynamic_back = {sm.stencil_mask_bf,
rc.stencil_clear_enable ? 0u : sm.stencil_writemask_bf, rc.stencil_clear_enable ? 0u : sm.stencil_writemask_bf,
sm.stencil_testval_bf}; sm.stencil_testval_bf};
@@ -402,7 +404,8 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
} }
void MarkRenderTargetGpuWritten(const RenderDepthInfo& target) { void MarkRenderTargetGpuWritten(const RenderDepthInfo& target) {
const bool with_depth = target.format != VK_FORMAT_UNDEFINED && target.vulkan_buffer != nullptr; const bool with_depth =
target.format != vk::Format::eUndefined && target.vulkan_buffer != nullptr;
if (with_depth && !depth_attachment_read_only(&target)) { if (with_depth && !depth_attachment_read_only(&target)) {
g_render_ctx->GetTextureCache()->MarkGpuWritten(target.vulkan_buffer); g_render_ctx->GetTextureCache()->MarkGpuWritten(target.vulkan_buffer);
@@ -3,9 +3,9 @@
#include "common/assert.h" #include "common/assert.h"
#include "graphics/host_gpu/renderer/renderTarget.h" #include "graphics/host_gpu/renderer/renderTarget.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <cstdint> #include <cstdint>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -22,7 +22,7 @@ inline constexpr bool depth_htile_stencil_acceleration_compatible(bool has_stenc
} }
struct RenderDepthInfo { struct RenderDepthInfo {
VkFormat format = VK_FORMAT_UNDEFINED; vk::Format format = vk::Format::eUndefined;
uint32_t width = 0; uint32_t width = 0;
uint32_t height = 0; uint32_t height = 0;
bool htile = false; bool htile = false;
@@ -41,7 +41,7 @@ struct RenderDepthInfo {
float depth_clear_value = 0.0f; float depth_clear_value = 0.0f;
bool depth_test_enable = false; bool depth_test_enable = false;
bool depth_write_enable = false; bool depth_write_enable = false;
VkCompareOp depth_compare_op = VK_COMPARE_OP_NEVER; vk::CompareOp depth_compare_op = vk::CompareOp::eNever;
bool depth_bounds_test_enable = false; bool depth_bounds_test_enable = false;
float depth_min_bounds = 0.0f; float depth_min_bounds = 0.0f;
float depth_max_bounds = 0.0f; float depth_max_bounds = 0.0f;
@@ -53,7 +53,7 @@ struct RenderDepthInfo {
PipelineStencilDynamicState stencil_dynamic_front; PipelineStencilDynamicState stencil_dynamic_front;
PipelineStencilDynamicState stencil_dynamic_back; PipelineStencilDynamicState stencil_dynamic_back;
DepthStencilVulkanImage* vulkan_buffer = nullptr; DepthStencilVulkanImage* vulkan_buffer = nullptr;
VkImageView vulkan_view = nullptr; vk::ImageView vulkan_view = nullptr;
uint64_t vaddr[3] = {}; uint64_t vaddr[3] = {};
uint64_t size[3] = {}; uint64_t size[3] = {};
int vaddr_num = 0; int vaddr_num = 0;
@@ -68,9 +68,9 @@ inline bool depth_attachment_read_only(const RenderDepthInfo* depth) {
!depth->depth_write_enable && !stencil_write; !depth->depth_write_enable && !stencil_write;
} }
inline VkImageLayout depth_attachment_layout(const RenderDepthInfo* depth) { inline vk::ImageLayout depth_attachment_layout(const RenderDepthInfo* depth) {
return depth_attachment_read_only(depth) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL return depth_attachment_read_only(depth) ? vk::ImageLayout::eDepthStencilReadOnlyOptimal
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; : vk::ImageLayout::eDepthStencilAttachmentOptimal;
} }
void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const HW::Context& hw, void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const HW::Context& hw,
@@ -12,11 +12,11 @@ namespace {
using BindingKind = ShaderRecompiler::IR::DescriptorBindingKind; using BindingKind = ShaderRecompiler::IR::DescriptorBindingKind;
VkShaderStageFlags StageFlags(DescriptorCache::Stage stage) { vk::ShaderStageFlags StageFlags(DescriptorCache::Stage stage) {
switch (stage) { switch (stage) {
case DescriptorCache::Stage::Vertex: return VK_SHADER_STAGE_VERTEX_BIT; case DescriptorCache::Stage::Vertex: return vk::ShaderStageFlagBits::eVertex;
case DescriptorCache::Stage::Pixel: return VK_SHADER_STAGE_FRAGMENT_BIT; case DescriptorCache::Stage::Pixel: return vk::ShaderStageFlagBits::eFragment;
case DescriptorCache::Stage::Compute: return VK_SHADER_STAGE_COMPUTE_BIT; case DescriptorCache::Stage::Compute: return vk::ShaderStageFlagBits::eCompute;
default: EXIT("unknown descriptor stage\n"); default: EXIT("unknown descriptor stage\n");
} }
} }
@@ -45,17 +45,17 @@ bool IsStorageImage(BindingKind kind) {
} }
} }
VkDescriptorType DescriptorType(BindingKind kind) { vk::DescriptorType DescriptorType(BindingKind kind) {
if (kind == BindingKind::Samplers) { if (kind == BindingKind::Samplers) {
return VK_DESCRIPTOR_TYPE_SAMPLER; return vk::DescriptorType::eSampler;
} }
if (IsSampledImage(kind)) { if (IsSampledImage(kind)) {
return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; return vk::DescriptorType::eSampledImage;
} }
if (IsStorageImage(kind)) { if (IsStorageImage(kind)) {
return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; return vk::DescriptorType::eStorageImage;
} }
return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; return vk::DescriptorType::eStorageBuffer;
} }
uint32_t DescriptorCount(const ShaderRecompiler::IR::DescriptorBinding& binding) { uint32_t DescriptorCount(const ShaderRecompiler::IR::DescriptorBinding& binding) {
@@ -76,23 +76,23 @@ std::vector<uint32_t> LayoutKey(DescriptorCache::Stage stage,
return key; return key;
} }
VkImageLayout SampledLayout(const VulkanImage* image) { vk::ImageLayout SampledLayout(const VulkanImage* image) {
EXIT_IF(image == nullptr); EXIT_IF(image == nullptr);
switch (image->layout) { switch (image->layout) {
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: case vk::ImageLayout::eTransferDstOptimal:
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: case vk::ImageLayout::eTransferSrcOptimal:
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: return VK_IMAGE_LAYOUT_GENERAL; case vk::ImageLayout::eColorAttachmentOptimal: return vk::ImageLayout::eGeneral;
default: return image->layout; default: return image->layout;
} }
} }
VkDescriptorBufferInfo BufferInfo(const BufferView& view) { vk::DescriptorBufferInfo BufferInfo(const BufferView& view) {
EXIT_IF(view.buffer == nullptr || view.buffer->buffer == nullptr); EXIT_IF(view.buffer == nullptr || view.buffer->buffer == nullptr);
return {view.buffer->buffer, view.offset, view.range}; return {view.buffer->buffer, view.offset, view.range};
} }
VkDescriptorImageInfo MakeDescriptorImageInfo(const DescriptorCache::TextureBinding& texture, vk::DescriptorImageInfo MakeDescriptorImageInfo(const DescriptorCache::TextureBinding& texture,
VkImageLayout layout) { vk::ImageLayout layout) {
EXIT_IF(texture.image == nullptr || texture.view < 0 || texture.view >= VulkanImage::VIEW_MAX); EXIT_IF(texture.image == nullptr || texture.view < 0 || texture.view >= VulkanImage::VIEW_MAX);
const auto view = texture.image_view != nullptr ? texture.image_view const auto view = texture.image_view != nullptr ? texture.image_view
: texture.image->image_view[texture.view]; : texture.image->image_view[texture.view];
@@ -106,7 +106,7 @@ void DescriptorCache::Init() {
m_initialized = true; m_initialized = true;
} }
VkDescriptorSetLayout vk::DescriptorSetLayout
DescriptorCache::GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stage, DescriptorCache::GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stage,
const ShaderRecompiler::IR::Program& program) { const ShaderRecompiler::IR::Program& program) {
EXIT_IF(gctx == nullptr); EXIT_IF(gctx == nullptr);
@@ -117,7 +117,7 @@ DescriptorCache::GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stag
return found->second; return found->second;
} }
std::vector<VkDescriptorSetLayoutBinding> bindings; std::vector<vk::DescriptorSetLayoutBinding> bindings;
bindings.reserve(program.bindings.descriptors.size()); bindings.reserve(program.bindings.descriptors.size());
for (const auto& descriptor: program.bindings.descriptors) { for (const auto& descriptor: program.bindings.descriptors) {
bindings.push_back({descriptor.binding, DescriptorType(descriptor.kind), bindings.push_back({descriptor.binding, DescriptorType(descriptor.kind),
@@ -127,12 +127,12 @@ DescriptorCache::GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stag
return nullptr; return nullptr;
} }
VkDescriptorSetLayoutCreateInfo info {}; vk::DescriptorSetLayoutCreateInfo info {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; info.sType = vk::StructureType::eDescriptorSetLayoutCreateInfo;
info.bindingCount = static_cast<uint32_t>(bindings.size()); info.bindingCount = static_cast<uint32_t>(bindings.size());
info.pBindings = bindings.data(); info.pBindings = bindings.data();
VkDescriptorSetLayout layout = nullptr; vk::DescriptorSetLayout layout = nullptr;
vkCreateDescriptorSetLayout(gctx->device, &info, nullptr, &layout); gctx->device.createDescriptorSetLayout(&info, nullptr, &layout);
EXIT_NOT_IMPLEMENTED(layout == nullptr); EXIT_NOT_IMPLEMENTED(layout == nullptr);
m_descriptor_set_layouts.emplace(key, layout); m_descriptor_set_layouts.emplace(key, layout);
return layout; return layout;
@@ -141,23 +141,23 @@ DescriptorCache::GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stag
void DescriptorCache::CreatePool(GraphicContext* gctx) { void DescriptorCache::CreatePool(GraphicContext* gctx) {
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
EXIT_IF(gctx == nullptr); EXIT_IF(gctx == nullptr);
constexpr uint32_t MaxSets = 512; constexpr uint32_t MaxSets = 512;
const VkDescriptorPoolSize sizes[] = { const vk::DescriptorPoolSize sizes[] = {
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, {vk::DescriptorType::eStorageBuffer,
MaxSets * (ShaderRecompiler::IR::ShaderInfo::MaxBuffers + MaxSets * (ShaderRecompiler::IR::ShaderInfo::MaxBuffers +
ShaderRecompiler::IR::ShaderInfo::MaxAddresses + 3u)}, ShaderRecompiler::IR::ShaderInfo::MaxAddresses + 3u)},
{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxImages}, {vk::DescriptorType::eSampledImage, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxImages},
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxImages}, {vk::DescriptorType::eStorageImage, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxImages},
{VK_DESCRIPTOR_TYPE_SAMPLER, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxSamplers}, {vk::DescriptorType::eSampler, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxSamplers},
}; };
VkDescriptorPoolCreateInfo info {}; vk::DescriptorPoolCreateInfo info {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; info.sType = vk::StructureType::eDescriptorPoolCreateInfo;
info.poolSizeCount = static_cast<uint32_t>(std::size(sizes)); info.poolSizeCount = static_cast<uint32_t>(std::size(sizes));
info.pPoolSizes = sizes; info.pPoolSizes = sizes;
info.maxSets = MaxSets; info.maxSets = MaxSets;
const auto pool_id = static_cast<int>(m_pools.size()); const auto pool_id = static_cast<int>(m_pools.size());
auto& pool = m_pools.emplace_back(); auto& pool = m_pools.emplace_back();
vkCreateDescriptorPool(gctx->device, &info, nullptr, &pool.pool); gctx->device.createDescriptorPool(&info, nullptr, &pool.pool);
EXIT_NOT_IMPLEMENTED(pool.pool == nullptr); EXIT_NOT_IMPLEMENTED(pool.pool == nullptr);
pool.next_free_pool = m_first_free_pool; pool.next_free_pool = m_first_free_pool;
m_first_free_pool = pool_id; m_first_free_pool = pool_id;
@@ -182,16 +182,16 @@ VulkanDescriptorSet* DescriptorCache::Allocate(Stage
for (int attempt = 0; attempt < 2; attempt++) { for (int attempt = 0; attempt < 2; attempt++) {
for (int pool_id = m_first_free_pool; pool_id != -1; for (int pool_id = m_first_free_pool; pool_id != -1;
pool_id = m_pools[pool_id].next_free_pool) { pool_id = m_pools[pool_id].next_free_pool) {
auto& pool = m_pools[pool_id]; auto& pool = m_pools[pool_id];
std::array<VkDescriptorSetLayout, Batch> layouts; std::array<vk::DescriptorSetLayout, Batch> layouts;
layouts.fill(layout); layouts.fill(layout);
std::array<VkDescriptorSet, Batch> sets {}; std::array<vk::DescriptorSet, Batch> sets {};
VkDescriptorSetAllocateInfo info {}; vk::DescriptorSetAllocateInfo info {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; info.sType = vk::StructureType::eDescriptorSetAllocateInfo;
info.descriptorPool = pool.pool; info.descriptorPool = pool.pool;
info.descriptorSetCount = Batch; info.descriptorSetCount = Batch;
info.pSetLayouts = layouts.data(); info.pSetLayouts = layouts.data();
if (vkAllocateDescriptorSets(gctx->device, &info, sets.data()) == VK_SUCCESS) { if (gctx->device.allocateDescriptorSets(&info, sets.data()) == vk::Result::eSuccess) {
free_sets.reserve(free_sets.size() + Batch - 1u); free_sets.reserve(free_sets.size() + Batch - 1u);
for (uint32_t i = 0; i + 1u < Batch; i++) { for (uint32_t i = 0; i + 1u < Batch; i++) {
free_sets.push_back(new VulkanDescriptorSet {sets[i], layout, pool_id}); free_sets.push_back(new VulkanDescriptorSet {sets[i], layout, pool_id});
@@ -228,16 +228,16 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage
const auto descriptor_count = program.info.buffers.size() + program.info.images.size() + const auto descriptor_count = program.info.buffers.size() + program.info.images.size() +
program.info.samplers.size() + program.info.addresses.size() + 3u; program.info.samplers.size() + program.info.addresses.size() + 3u;
std::vector<VkDescriptorBufferInfo> buffer_infos; std::vector<vk::DescriptorBufferInfo> buffer_infos;
std::vector<VkDescriptorImageInfo> image_infos; std::vector<vk::DescriptorImageInfo> image_infos;
std::vector<VkWriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
buffer_infos.reserve(descriptor_count); buffer_infos.reserve(descriptor_count);
image_infos.reserve(descriptor_count); image_infos.reserve(descriptor_count);
writes.reserve(program.bindings.descriptors.size()); writes.reserve(program.bindings.descriptors.size());
for (const auto& binding: program.bindings.descriptors) { for (const auto& binding: program.bindings.descriptors) {
VkWriteDescriptorSet write {}; vk::WriteDescriptorSet write {};
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write.sType = vk::StructureType::eWriteDescriptorSet;
write.dstSet = set->set; write.dstSet = set->set;
write.dstBinding = binding.binding; write.dstBinding = binding.binding;
write.descriptorType = DescriptorType(binding.kind); write.descriptorType = DescriptorType(binding.kind);
@@ -264,12 +264,12 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage
for (const auto resource: binding.resources) { for (const auto resource: binding.resources) {
const auto sampler = data.samplers.at(resource); const auto sampler = data.samplers.at(resource);
EXIT_IF(sampler == nullptr); EXIT_IF(sampler == nullptr);
image_infos.push_back({sampler, nullptr, VK_IMAGE_LAYOUT_UNDEFINED}); image_infos.push_back({sampler, nullptr, vk::ImageLayout::eUndefined});
} }
break; break;
default: { default: {
const auto layout = IsStorageImage(binding.kind) ? VK_IMAGE_LAYOUT_GENERAL const auto layout = IsStorageImage(binding.kind) ? vk::ImageLayout::eGeneral
: VK_IMAGE_LAYOUT_UNDEFINED; : vk::ImageLayout::eUndefined;
for (const auto resource: binding.resources) { for (const auto resource: binding.resources) {
const auto& texture = data.images.at(resource); const auto& texture = data.images.at(resource);
image_infos.push_back(MakeDescriptorImageInfo( image_infos.push_back(MakeDescriptorImageInfo(
@@ -287,12 +287,12 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage
} }
writes.push_back(write); writes.push_back(write);
} }
vkUpdateDescriptorSets(gctx->device, static_cast<uint32_t>(writes.size()), writes.data(), 0, gctx->device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0,
nullptr); nullptr);
return set; return set;
} }
VkDescriptorSetLayout vk::DescriptorSetLayout
DescriptorCache::GetDescriptorSetLayout(Stage stage, const ShaderRecompiler::IR::Program& program) { DescriptorCache::GetDescriptorSetLayout(Stage stage, const ShaderRecompiler::IR::Program& program) {
auto* gctx = g_render_ctx->GetGraphicCtx(); auto* gctx = g_render_ctx->GetGraphicCtx();
EXIT_IF(gctx == nullptr); EXIT_IF(gctx == nullptr);
@@ -6,12 +6,12 @@
#include "common/common.h" #include "common/common.h"
#include "common/threads.h" #include "common/threads.h"
#include "graphics/host_gpu/graphicContext.h" #include "graphics/host_gpu/graphicContext.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/shaderBindings.h" #include "graphics/shader/shaderBindings.h"
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -23,19 +23,19 @@ class CommandBuffer;
struct ShaderStageRuntime; struct ShaderStageRuntime;
struct VulkanDescriptor { struct VulkanDescriptor {
VkDescriptorSet descriptor_set = nullptr; vk::DescriptorSet descriptor_set = nullptr;
}; };
struct VulkanDescriptorSet { struct VulkanDescriptorSet {
VkDescriptorSet set = nullptr; vk::DescriptorSet set = nullptr;
VkDescriptorSetLayout layout = nullptr; vk::DescriptorSetLayout layout = nullptr;
int pool_id = -1; int pool_id = -1;
}; };
struct BufferView { struct BufferView {
VulkanBuffer* buffer = nullptr; VulkanBuffer* buffer = nullptr;
VkDeviceSize offset = 0; vk::DeviceSize offset = 0;
VkDeviceSize range = VK_WHOLE_SIZE; vk::DeviceSize range = VK_WHOLE_SIZE;
}; };
struct ShaderAddressWriteRange { struct ShaderAddressWriteRange {
@@ -49,9 +49,9 @@ public:
enum class Stage { Unknown, Vertex, Pixel, Compute }; enum class Stage { Unknown, Vertex, Pixel, Compute };
struct TextureBinding { struct TextureBinding {
VulkanImage* image = nullptr; VulkanImage* image = nullptr;
int view = VulkanImage::VIEW_DEFAULT; int view = VulkanImage::VIEW_DEFAULT;
VkImageView image_view = nullptr; vk::ImageView image_view = nullptr;
}; };
enum class TextureVariant : int { enum class TextureVariant : int {
@@ -66,7 +66,7 @@ public:
struct NativeDescriptors { struct NativeDescriptors {
std::vector<BufferView> buffers; std::vector<BufferView> buffers;
std::vector<TextureBinding> images; std::vector<TextureBinding> images;
std::vector<VkSampler> samplers; std::vector<vk::Sampler> samplers;
std::vector<BufferView> addresses; std::vector<BufferView> addresses;
BufferView gds; BufferView gds;
BufferView flattened_srt; BufferView flattened_srt;
@@ -77,41 +77,43 @@ public:
virtual ~DescriptorCache() { KYTY_NOT_IMPLEMENTED; } virtual ~DescriptorCache() { KYTY_NOT_IMPLEMENTED; }
KYTY_CLASS_NO_COPY(DescriptorCache); KYTY_CLASS_NO_COPY(DescriptorCache);
VkDescriptorSetLayout GetDescriptorSetLayout(Stage stage, vk::DescriptorSetLayout GetDescriptorSetLayout(Stage stage,
const ShaderRecompiler::IR::Program& program); const ShaderRecompiler::IR::Program& program);
void Recycle(VulkanDescriptorSet* set); void Recycle(VulkanDescriptorSet* set);
VulkanDescriptorSet* GetDescriptor(Stage stage, const ShaderRecompiler::IR::Program& program, VulkanDescriptorSet* GetDescriptor(Stage stage, const ShaderRecompiler::IR::Program& program,
const NativeDescriptors& descriptors); const NativeDescriptors& descriptors);
private: private:
struct Pool { struct Pool {
VkDescriptorPool pool = nullptr; vk::DescriptorPool pool = nullptr;
int next_free_pool = -1; int next_free_pool = -1;
bool free = true; bool free = true;
}; };
void Init(); void Init();
void CreatePool(GraphicContext* gctx); void CreatePool(GraphicContext* gctx);
VulkanDescriptorSet* Allocate(Stage stage, const ShaderRecompiler::IR::Program& program); VulkanDescriptorSet* Allocate(Stage stage, const ShaderRecompiler::IR::Program& program);
VkDescriptorSetLayout vk::DescriptorSetLayout
GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stage, GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stage,
const ShaderRecompiler::IR::Program& program); const ShaderRecompiler::IR::Program& program);
Common::Mutex m_mutex; Common::Mutex m_mutex;
std::vector<Pool> m_pools; std::vector<Pool> m_pools;
int m_first_free_pool = -1; int m_first_free_pool = -1;
std::unordered_map<VkDescriptorSetLayout, std::vector<VulkanDescriptorSet*>> std::unordered_map<vk::DescriptorSetLayout, std::vector<VulkanDescriptorSet*>>
m_free_sets_by_layout; m_free_sets_by_layout;
std::map<std::vector<uint32_t>, VkDescriptorSetLayout> m_descriptor_set_layouts; std::map<std::vector<uint32_t>, vk::DescriptorSetLayout> m_descriptor_set_layouts;
bool m_initialized = false; bool m_initialized = false;
}; };
const char* storage_usage_name(ShaderStorageUsage usage); const char* storage_usage_name(ShaderStorageUsage usage);
VkImageAspectFlags DepthStencilAspectMask(VkFormat format); vk::ImageAspectFlags DepthStencilAspectMask(vk::Format format);
std::vector<ShaderAddressWriteRange> std::vector<ShaderAddressWriteRange> BindDescriptors(uint64_t submit_id, CommandBuffer* buffer,
BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint pipeline_bind_point, vk::PipelineBindPoint pipeline_bind_point,
VkPipelineLayout layout, const ShaderStageRuntime& runtime, vk::PipelineLayout layout,
VkShaderStageFlags vk_stage, DescriptorCache::Stage stage); const ShaderStageRuntime& runtime,
vk::ShaderStageFlags vk_stage,
DescriptorCache::Stage stage);
} // namespace Libs::Graphics } // namespace Libs::Graphics
+47 -43
View File
@@ -25,6 +25,7 @@
#include "graphics/host_gpu/renderer/shaderResourceBarrier.h" #include "graphics/host_gpu/renderer/shaderResourceBarrier.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h" #include "graphics/host_gpu/vma.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/displayBuffer.h" #include "graphics/presentation/displayBuffer.h"
#include "graphics/shader/recompiler/BindingLayout.h" #include "graphics/shader/recompiler/BindingLayout.h"
#include "graphics/shader/recompiler/ResourceMaterialization.h" #include "graphics/shader/recompiler/ResourceMaterialization.h"
@@ -36,7 +37,6 @@
#include <cstring> #include <cstring>
#include <fmt/format.h> #include <fmt/format.h>
#include <limits> #include <limits>
#include <vulkan/vk_enum_string_helper.h>
#ifdef min #ifdef min
#undef min #undef min
@@ -71,10 +71,10 @@ static const char* VulkanImageTypeName(VulkanImageType type) {
} }
} }
VkImageAspectFlags DepthStencilAspectMask(VkFormat format) { vk::ImageAspectFlags DepthStencilAspectMask(vk::Format format) {
auto ret = static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT); auto ret = static_cast<vk::ImageAspectFlags>(vk::ImageAspectFlagBits::eDepth);
if (format == VK_FORMAT_D24_UNORM_S8_UINT || format == VK_FORMAT_D32_SFLOAT_S8_UINT) { if (format == vk::Format::eD24UnormS8Uint || format == vk::Format::eD32SfloatS8Uint) {
ret |= VK_IMAGE_ASPECT_STENCIL_BIT; ret |= vk::ImageAspectFlagBits::eStencil;
} }
return ret; return ret;
} }
@@ -229,7 +229,7 @@ static BufferView NativeStorageBuffer(uint64_t submit_id, CommandBuffer* command
} }
result.buffer = binding.first; result.buffer = binding.first;
result.offset = binding.second; result.offset = binding.second;
result.range = static_cast<VkDeviceSize>(size); result.range = static_cast<vk::DeviceSize>(size);
return result; return result;
} }
@@ -267,7 +267,7 @@ NativeAddressBuffer(uint64_t submit_id, CommandBuffer* command_buffer,
address.binding_base, size); address.binding_base, size);
result.buffer = binding.first; result.buffer = binding.first;
result.offset = binding.second; result.offset = binding.second;
result.range = static_cast<VkDeviceSize>(size); result.range = static_cast<vk::DeviceSize>(size);
return result; return result;
} }
@@ -306,16 +306,16 @@ TargetTextureViewInfo ResolveTargetTextureView(const ShaderRecompiler::IR::Image
case Prospero::ImageType::kColor2D: case Prospero::ImageType::kColor2D:
return resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D && return resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D &&
base_layer == 0 && image_layers == 1 base_layer == 0 && image_layers == 1
? TargetTextureViewInfo {VK_IMAGE_VIEW_TYPE_2D, 0, 1} ? TargetTextureViewInfo {vk::ImageViewType::e2D, 0, 1}
: TargetTextureViewInfo {}; : TargetTextureViewInfo {};
case Prospero::ImageType::kColor2DArray: case Prospero::ImageType::kColor2DArray:
if (resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D && if (resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D &&
base_layer == 0 && image_layers == 1) { base_layer == 0 && image_layers == 1) {
return {VK_IMAGE_VIEW_TYPE_2D, 0, 1}; return {vk::ImageViewType::e2D, 0, 1};
} }
return resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DArray && return resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DArray &&
base_layer < image_layers base_layer < image_layers
? TargetTextureViewInfo {VK_IMAGE_VIEW_TYPE_2D_ARRAY, base_layer, ? TargetTextureViewInfo {vk::ImageViewType::e2DArray, base_layer,
image_layers - base_layer} image_layers - base_layer}
: TargetTextureViewInfo {}; : TargetTextureViewInfo {};
default: return {}; default: return {};
@@ -365,7 +365,7 @@ static bool IsSupportedDepthTextureEncoding(const ShaderTextureResource& descrip
static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource& resource, static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource& resource,
const ShaderTextureResource& descriptor, const ShaderTextureResource& descriptor,
const VulkanImage* image, VkFormat view_format, const VulkanImage* image, vk::Format view_format,
uint64_t size) { uint64_t size) {
const bool resource_ok = IsSupportedSampledDepthResource(resource); const bool resource_ok = IsSupportedSampledDepthResource(resource);
const bool descriptor_ok = const bool descriptor_ok =
@@ -389,7 +389,8 @@ static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource
static_cast<uint32_t>(resource.dimension), static_cast<uint32_t>(resource.mip_mode), static_cast<uint32_t>(resource.dimension), static_cast<uint32_t>(resource.mip_mode),
resource.read, resource.written, resource.atomic, resource.depth_compare, resource.read, resource.written, resource.atomic, resource.depth_compare,
descriptor.Format(), descriptor.DstSelXYZW(), descriptor.Format(), descriptor.DstSelXYZW(),
image == nullptr ? static_cast<int>(VK_FORMAT_UNDEFINED) : static_cast<int>(image->format), image == nullptr ? static_cast<int>(vk::Format::eUndefined)
: static_cast<int>(image->format),
static_cast<int>(view_format), image == nullptr ? 0u : image->layers, descriptor.Type(), static_cast<int>(view_format), image == nullptr ? 0u : image->layers, descriptor.Type(),
descriptor.BaseArray5(), descriptor.Depth(), descriptor_pitch, descriptor.BaseArray5(), descriptor.Depth(), descriptor_pitch,
image == nullptr ? 0u : image->guest_pitch, descriptor.Base40(), size, image == nullptr ? 0u : image->guest_pitch, descriptor.Base40(), size,
@@ -559,11 +560,11 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer,
resource.written); resource.written);
} }
VulkanImage* image = nullptr; VulkanImage* image = nullptr;
int view = VulkanImage::VIEW_DEFAULT; int view = VulkanImage::VIEW_DEFAULT;
VkImageView image_view = nullptr; vk::ImageView image_view = nullptr;
const bool check_depth = static_cast<Prospero::TileMode>(tile) == Prospero::TileMode::kDepth || const bool check_depth = static_cast<Prospero::TileMode>(tile) == Prospero::TileMode::kDepth ||
descriptor.MsaaDepth(); descriptor.MsaaDepth();
if (image == nullptr) { if (image == nullptr) {
if (check_depth) { if (check_depth) {
image = g_render_ctx->GetTextureCache()->FindDepthTargetByRange(command_buffer, address, image = g_render_ctx->GetTextureCache()->FindDepthTargetByRange(command_buffer, address,
@@ -592,7 +593,8 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer,
const auto depth_view = ResolveTargetTextureView( const auto depth_view = ResolveTargetTextureView(
resource, type, descriptor.BaseArray5(), image->layers); resource, type, descriptor.BaseArray5(), image->layers);
ValidateDepthTargetBinding(resource, descriptor, image, view_format, size.size); ValidateDepthTargetBinding(resource, descriptor, image, view_format, size.size);
if (depth_view.type == VK_IMAGE_VIEW_TYPE_MAX_ENUM) { if (depth_view.type ==
static_cast<vk::ImageViewType>(VK_IMAGE_VIEW_TYPE_MAX_ENUM)) {
EXIT("unsupported sampled depth target view: dimension=%u " EXIT("unsupported sampled depth target view: dimension=%u "
"descriptor_type=%u " "descriptor_type=%u "
"base_array=%u image_layers=%u\n", "base_array=%u image_layers=%u\n",
@@ -611,7 +613,8 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer,
height != image->extent.height || height != image->extent.height ||
(storage ? levels != image->mip_levels || base_level != 0 (storage ? levels != image->mip_levels || base_level != 0
: levels != image->mip_levels || base_level >= levels) || : levels != image->mip_levels || base_level >= levels) ||
target_view.type == VK_IMAGE_VIEW_TYPE_MAX_ENUM || target_view.type ==
static_cast<vk::ImageViewType>(VK_IMAGE_VIEW_TYPE_MAX_ENUM) ||
target_view.base_layer >= image->layers || target_view.base_layer >= image->layers ||
target_view.layer_count > image->layers - target_view.base_layer) { target_view.layer_count > image->layers - target_view.base_layer) {
EXIT("unsupported cached render-target image view: storage=%d resource=%u " EXIT("unsupported cached render-target image view: storage=%d resource=%u "
@@ -656,13 +659,13 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer,
resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D && resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D &&
!resource.read && resource.written && !resource.atomic && !resource.read && resource.written && !resource.atomic &&
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8UInt) && format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8UInt) &&
view_format == VK_FORMAT_R8G8B8A8_UINT && swizzle == DstSel(6, 5, 4, 7) && view_format == vk::Format::eR8G8B8A8Uint && swizzle == DstSel(6, 5, 4, 7) &&
width == video.image->extent.width && height == video.image->extent.height && width == video.image->extent.width && height == video.image->extent.height &&
depth == 1 && levels == 1 && base_level == 0 && view_levels == 1 && depth == 1 && levels == 1 && base_level == 0 && view_levels == 1 &&
type == Prospero::ImageType::kColor2D && video.size == size.size && type == Prospero::ImageType::kColor2D && video.size == size.size &&
video.pitch == pitch && video.pitch == pitch &&
(video.image->format == VK_FORMAT_R8G8B8A8_SRGB || (video.image->format == vk::Format::eR8G8B8A8Srgb ||
video.image->format == VK_FORMAT_B8G8R8A8_SRGB) && video.image->format == vk::Format::eB8G8R8A8Srgb) &&
video.image->image_view[VulkanImage::VIEW_STORAGE] != nullptr; video.image->image_view[VulkanImage::VIEW_STORAGE] != nullptr;
if (!exact) { if (!exact) {
EXIT("unsupported storage access to video-out surface: format=%u view=%d" EXIT("unsupported storage access to video-out surface: format=%u view=%d"
@@ -693,7 +696,7 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer,
image = video.image; image = video.image;
image_view = g_render_ctx->GetTextureCache()->GetSampledColorView( image_view = g_render_ctx->GetTextureCache()->GetSampledColorView(
g_render_ctx->GetGraphicCtx(), video.image, view_format, swizzle, 0, 1, g_render_ctx->GetGraphicCtx(), video.image, view_format, swizzle, 0, 1,
VK_IMAGE_VIEW_TYPE_2D, 0, 1); vk::ImageViewType::e2D, 0, 1);
} }
} }
} }
@@ -749,8 +752,8 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer,
return {image, view, image_view}; return {image, view, image_view};
} }
static VkSampler NativeSampler(const ShaderRecompiler::IR::Program& program, uint32_t index, static vk::Sampler NativeSampler(const ShaderRecompiler::IR::Program& program, uint32_t index,
const ShaderRecompiler::IR::DescriptorValue& value) { const ShaderRecompiler::IR::DescriptorValue& value) {
auto descriptor = NativeSamplerDescriptor(value); auto descriptor = NativeSamplerDescriptor(value);
const bool depth_compare = std::any_of(program.info.sampled_pairs.begin(), const bool depth_compare = std::any_of(program.info.sampled_pairs.begin(),
program.info.sampled_pairs.end(), [&](const auto& pair) { program.info.sampled_pairs.end(), [&](const auto& pair) {
@@ -773,10 +776,12 @@ static BufferView NativeUpload(CommandBuffer* command_buffer, std::span<const ui
return result; return result;
} }
std::vector<ShaderAddressWriteRange> std::vector<ShaderAddressWriteRange> BindDescriptors(uint64_t submit_id, CommandBuffer* buffer,
BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint pipeline_bind_point, vk::PipelineBindPoint pipeline_bind_point,
VkPipelineLayout layout, const ShaderStageRuntime& runtime, vk::PipelineLayout layout,
VkShaderStageFlags vk_stage, DescriptorCache::Stage stage) { const ShaderStageRuntime& runtime,
vk::ShaderStageFlags vk_stage,
DescriptorCache::Stage stage) {
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
EXIT_IF(buffer == nullptr || !runtime); EXIT_IF(buffer == nullptr || !runtime);
const auto& program = *runtime.program; const auto& program = *runtime.program;
@@ -785,7 +790,7 @@ BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint p
if (!ShaderRecompiler::IR::ValidateResourceSpecialization(program, snapshot, &error)) { if (!ShaderRecompiler::IR::ValidateResourceSpecialization(program, snapshot, &error)) {
EXIT("invalid native shader runtime snapshot: %s\n", error.c_str()); EXIT("invalid native shader runtime snapshot: %s\n", error.c_str());
} }
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; auto vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
const auto shader_stages = ShaderPipelineStages(vk_stage); const auto shader_stages = ShaderPipelineStages(vk_stage);
DescriptorCache::NativeDescriptors descriptors; DescriptorCache::NativeDescriptors descriptors;
@@ -800,7 +805,7 @@ BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint p
const auto kind = program.info.images[i].kind; const auto kind = program.info.images[i].kind;
if ((kind == ShaderRecompiler::IR::ResourceKind::StorageImage || if ((kind == ShaderRecompiler::IR::ResourceKind::StorageImage ||
kind == ShaderRecompiler::IR::ResourceKind::StorageImageUint) && kind == ShaderRecompiler::IR::ResourceKind::StorageImageUint) &&
vk_stage != VK_SHADER_STAGE_COMPUTE_BIT) { vk_stage != vk::ShaderStageFlagBits::eCompute) {
EXIT("storage images are unsupported outside compute shaders\n"); EXIT("storage images are unsupported outside compute shaders\n");
} }
descriptors.images.push_back( descriptors.images.push_back(
@@ -843,11 +848,10 @@ BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint p
descriptors.gds.buffer = descriptors.gds.buffer =
g_render_ctx->GetGdsBuffer()->GetBuffer(g_render_ctx->GetGraphicCtx()); g_render_ctx->GetGdsBuffer()->GetBuffer(g_render_ctx->GetGraphicCtx());
const auto barrier = MakeGdsDependency(*descriptors.gds.buffer); const auto barrier = MakeGdsDependency(*descriptors.gds.buffer);
vkCmdPipelineBarrier(vk_buffer, vk_buffer.pipelineBarrier(
VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT | vk::PipelineStageFlagBits::eHost | vk::PipelineStageFlagBits::eTransfer |
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, shader_stages, vk::DependencyFlags {}, 0, nullptr, 1, &barrier, 0, nullptr);
shader_stages, 0, 0, nullptr, 1, &barrier, 0, nullptr);
} }
for (uint32_t i = 0; i < program.info.images.size(); i++) { for (uint32_t i = 0; i < program.info.images.size(); i++) {
@@ -871,23 +875,23 @@ BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint p
} else { } else {
const auto barrier = const auto barrier =
MakeStorageImageDependency(*image, resource.read, resource.written); MakeStorageImageDependency(*image, resource.read, resource.written);
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, shader_stages, 0, 0, vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, shader_stages,
nullptr, 0, nullptr, 1, &barrier); vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1, &barrier);
image->layout = VK_IMAGE_LAYOUT_GENERAL; image->layout = vk::ImageLayout::eGeneral;
} }
} }
if (!program.bindings.descriptors.empty()) { if (!program.bindings.descriptors.empty()) {
auto* set = g_render_ctx->GetDescriptorCache()->GetDescriptor(stage, program, descriptors); auto* set = g_render_ctx->GetDescriptorCache()->GetDescriptor(stage, program, descriptors);
EXIT_IF(set == nullptr); EXIT_IF(set == nullptr);
vkCmdBindDescriptorSets(vk_buffer, pipeline_bind_point, layout, vk_buffer.bindDescriptorSets(pipeline_bind_point, layout, program.bindings.descriptor_set,
program.bindings.descriptor_set, 1, &set->set, 0, nullptr); 1, &set->set, 0, nullptr);
buffer->RecycleDescriptorAfterFence(set); buffer->RecycleDescriptorAfterFence(set);
} }
if (program.bindings.push_constant_size != 0) { if (program.bindings.push_constant_size != 0) {
EXIT_IF(program.bindings.push_constant_size != user_data.size() * sizeof(uint32_t)); EXIT_IF(program.bindings.push_constant_size != user_data.size() * sizeof(uint32_t));
vkCmdPushConstants(vk_buffer, layout, vk_stage, program.bindings.push_constant_offset, vk_buffer.pushConstants(layout, vk_stage, program.bindings.push_constant_offset,
program.bindings.push_constant_size, user_data.data()); program.bindings.push_constant_size, user_data.data());
} }
return address_writes; return address_writes;
} }
+4 -4
View File
@@ -1,20 +1,20 @@
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DESCRIPTORS_H_ #ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DESCRIPTORS_H_
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DESCRIPTORS_H_ #define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_DESCRIPTORS_H_
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/recompiler/ShaderIR.h" #include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/shaderBindings.h" #include "graphics/shader/shaderBindings.h"
#include <cstdint> #include <cstdint>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
struct VulkanImage; struct VulkanImage;
struct TargetTextureViewInfo { struct TargetTextureViewInfo {
VkImageViewType type = VK_IMAGE_VIEW_TYPE_MAX_ENUM; vk::ImageViewType type = static_cast<vk::ImageViewType>(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
uint32_t base_layer = 0; uint32_t base_layer = 0;
uint32_t layer_count = 0; uint32_t layer_count = 0;
}; };
[[nodiscard]] TargetTextureViewInfo [[nodiscard]] TargetTextureViewInfo
@@ -7,10 +7,10 @@
#include "graphics/host_gpu/renderer/depthRenderTarget.h" #include "graphics/host_gpu/renderer/depthRenderTarget.h"
#include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -26,11 +26,11 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(requested_color_count > RENDER_COLOR_ATTACHMENTS_MAX); EXIT_IF(requested_color_count > RENDER_COLOR_ATTACHMENTS_MAX);
bool with_depth = (depth->format != VK_FORMAT_UNDEFINED && depth->vulkan_buffer != nullptr); bool with_depth = (depth->format != vk::Format::eUndefined && depth->vulkan_buffer != nullptr);
bool with_color[RENDER_COLOR_ATTACHMENTS_MAX] = {}; bool with_color[RENDER_COLOR_ATTACHMENTS_MAX] = {};
uint32_t color_count = 0; uint32_t color_count = 0;
VulkanImage* first_color = nullptr; VulkanImage* first_color = nullptr;
VkExtent2D first_color_extent = {}; vk::Extent2D first_color_extent = {};
for (uint32_t i = 0; i < requested_color_count; i++) { for (uint32_t i = 0; i < requested_color_count; i++) {
with_color[i] = (colors[i].vulkan_buffer != nullptr); with_color[i] = (colors[i].vulkan_buffer != nullptr);
if (!with_color[i]) { if (!with_color[i]) {
@@ -50,14 +50,14 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
} }
color_count++; color_count++;
} }
VkImageLayout color_layout[RENDER_COLOR_ATTACHMENTS_MAX] = {}; vk::ImageLayout color_layout[RENDER_COLOR_ATTACHMENTS_MAX] = {};
for (auto& layout: color_layout) { for (auto& layout: color_layout) {
layout = RENDER_COLOR_IMAGE_LAYOUT; layout = RENDER_COLOR_IMAGE_LAYOUT;
} }
auto depth_layout = (with_depth ? depth_attachment_layout(depth) auto depth_layout = (with_depth ? depth_attachment_layout(depth)
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); : vk::ImageLayout::eDepthStencilAttachmentOptimal);
auto depth_read_only = auto depth_read_only =
(with_depth && depth_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); (with_depth && depth_layout == vk::ImageLayout::eDepthStencilReadOnlyOptimal);
if (with_depth && first_color != nullptr && if (with_depth && first_color != nullptr &&
(first_color_extent.width != depth->vulkan_buffer->extent.width || (first_color_extent.width != depth->vulkan_buffer->extent.width ||
@@ -68,9 +68,9 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
"depth=%ux%u format=%s\n", "depth=%ux%u format=%s\n",
first_color_extent.width, first_color_extent.height, first_color_extent.width, first_color_extent.height,
depth->vulkan_buffer->extent.width, depth->vulkan_buffer->extent.height, depth->vulkan_buffer->extent.width, depth->vulkan_buffer->extent.height,
string_VkFormat(depth->format)); VulkanToString(depth->format).c_str());
} }
depth->format = VK_FORMAT_UNDEFINED; depth->format = vk::Format::eUndefined;
depth->vulkan_buffer = nullptr; depth->vulkan_buffer = nullptr;
depth->vulkan_view = nullptr; depth->vulkan_view = nullptr;
depth->depth_test_enable = false; depth->depth_test_enable = false;
@@ -81,7 +81,7 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
depth->depth_load_clear_enable = false; depth->depth_load_clear_enable = false;
depth->stencil_clear_enable = false; depth->stencil_clear_enable = false;
with_depth = false; with_depth = false;
depth_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; depth_layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
depth_read_only = false; depth_read_only = false;
} }
@@ -131,51 +131,53 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
first_color_extent.height != depth->vulkan_buffer->extent.height)); first_color_extent.height != depth->vulkan_buffer->extent.height));
if (first_color == nullptr) { if (first_color == nullptr) {
first_color = CreateDummyBuffer(VK_FORMAT_B8G8R8A8_SRGB, depth->vulkan_buffer->extent.width, first_color =
depth->vulkan_buffer->extent.height); CreateDummyBuffer(vk::Format::eB8G8R8A8Srgb, depth->vulkan_buffer->extent.width,
depth->vulkan_buffer->extent.height);
first_color_extent = first_color->extent; first_color_extent = first_color->extent;
} }
VkAttachmentDescription attachments[RENDER_COLOR_ATTACHMENTS_MAX + 1] = {}; vk::AttachmentDescription attachments[RENDER_COLOR_ATTACHMENTS_MAX + 1] = {};
for (uint32_t i = 0; i < color_count; i++) { for (uint32_t i = 0; i < color_count; i++) {
attachments[i].flags = 0; attachments[i].flags = {};
attachments[i].format = colors[i].format; attachments[i].format = colors[i].format;
attachments[i].samples = VK_SAMPLE_COUNT_1_BIT; attachments[i].samples = vk::SampleCountFlagBits::e1;
attachments[i].loadOp = (colors[i].color_clear_enable ? VK_ATTACHMENT_LOAD_OP_CLEAR attachments[i].loadOp = (colors[i].color_clear_enable ? vk::AttachmentLoadOp::eClear
: VK_ATTACHMENT_LOAD_OP_LOAD); : vk::AttachmentLoadOp::eLoad);
attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[i].storeOp = vk::AttachmentStoreOp::eStore;
attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments[i].stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachments[i].stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
attachments[i].initialLayout = color_layout[i]; attachments[i].initialLayout = color_layout[i];
attachments[i].finalLayout = RENDER_COLOR_IMAGE_LAYOUT; attachments[i].finalLayout = RENDER_COLOR_IMAGE_LAYOUT;
} }
const uint32_t depth_attachment = color_count; const uint32_t depth_attachment = color_count;
attachments[depth_attachment].flags = 0; attachments[depth_attachment].flags = {};
attachments[depth_attachment].format = depth->format; attachments[depth_attachment].format = depth->format;
attachments[depth_attachment].samples = VK_SAMPLE_COUNT_1_BIT; attachments[depth_attachment].samples = vk::SampleCountFlagBits::e1;
attachments[depth_attachment].loadOp = attachments[depth_attachment].loadOp =
(depth->depth_load_clear_enable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD); (depth->depth_load_clear_enable ? vk::AttachmentLoadOp::eClear
attachments[depth_attachment].storeOp = VK_ATTACHMENT_STORE_OP_STORE; : vk::AttachmentLoadOp::eLoad);
attachments[depth_attachment].storeOp = vk::AttachmentStoreOp::eStore;
attachments[depth_attachment].stencilLoadOp = attachments[depth_attachment].stencilLoadOp =
(depth->stencil_clear_enable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD); (depth->stencil_clear_enable ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad);
attachments[depth_attachment].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[depth_attachment].stencilStoreOp = vk::AttachmentStoreOp::eStore;
attachments[depth_attachment].initialLayout = depth_layout; attachments[depth_attachment].initialLayout = depth_layout;
attachments[depth_attachment].finalLayout = depth_layout; attachments[depth_attachment].finalLayout = depth_layout;
VkAttachmentReference color_attachment_ref[RENDER_COLOR_ATTACHMENTS_MAX] = {}; vk::AttachmentReference color_attachment_ref[RENDER_COLOR_ATTACHMENTS_MAX] = {};
for (uint32_t i = 0; i < RENDER_COLOR_ATTACHMENTS_MAX; i++) { for (uint32_t i = 0; i < RENDER_COLOR_ATTACHMENTS_MAX; i++) {
color_attachment_ref[i].attachment = (i < color_count ? i : VK_ATTACHMENT_UNUSED); color_attachment_ref[i].attachment = (i < color_count ? i : VK_ATTACHMENT_UNUSED);
color_attachment_ref[i].layout = RENDER_COLOR_IMAGE_LAYOUT; color_attachment_ref[i].layout = RENDER_COLOR_IMAGE_LAYOUT;
} }
VkAttachmentReference depth_attachment_ref {}; vk::AttachmentReference depth_attachment_ref {};
depth_attachment_ref.attachment = depth_attachment; depth_attachment_ref.attachment = depth_attachment;
depth_attachment_ref.layout = depth_layout; depth_attachment_ref.layout = depth_layout;
VkSubpassDescription subpass {}; vk::SubpassDescription subpass {};
subpass.flags = 0; subpass.flags = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
subpass.inputAttachmentCount = 0; subpass.inputAttachmentCount = 0;
subpass.pInputAttachments = nullptr; subpass.pInputAttachments = nullptr;
subpass.colorAttachmentCount = color_count; subpass.colorAttachmentCount = color_count;
@@ -185,34 +187,38 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
subpass.preserveAttachmentCount = 0; subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = nullptr; subpass.pPreserveAttachments = nullptr;
const auto attachment_stage_mask = static_cast<VkPipelineStageFlags>( const auto attachment_stage_mask =
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | static_cast<vk::PipelineStageFlags>(vk::PipelineStageFlagBits::eColorAttachmentOutput |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); vk::PipelineStageFlagBits::eEarlyFragmentTests |
const auto attachment_access_mask = static_cast<VkAccessFlags>( vk::PipelineStageFlagBits::eLateFragmentTests);
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | const auto attachment_access_mask = static_cast<vk::AccessFlags>(
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite |
vk::AccessFlagBits::eDepthStencilAttachmentRead |
vk::AccessFlagBits::eDepthStencilAttachmentWrite);
VkSubpassDependency dependencies[2] = {}; vk::SubpassDependency dependencies[2] = {};
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0; dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; dependencies[0].srcStageMask = vk::PipelineStageFlagBits::eAllCommands;
dependencies[0].dstStageMask = attachment_stage_mask; dependencies[0].dstStageMask = attachment_stage_mask;
dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; dependencies[0].srcAccessMask =
dependencies[0].dstAccessMask = attachment_access_mask; vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; dependencies[0].dstAccessMask = attachment_access_mask;
dependencies[0].dependencyFlags = vk::DependencyFlagBits::eByRegion;
dependencies[1].srcSubpass = 0; dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = attachment_stage_mask; dependencies[1].srcStageMask = attachment_stage_mask;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; dependencies[1].dstStageMask = vk::PipelineStageFlagBits::eAllCommands;
dependencies[1].srcAccessMask = attachment_access_mask; dependencies[1].srcAccessMask = attachment_access_mask;
dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; dependencies[1].dstAccessMask =
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
dependencies[1].dependencyFlags = vk::DependencyFlagBits::eByRegion;
VkRenderPassCreateInfo render_pass_info {}; vk::RenderPassCreateInfo render_pass_info {};
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; render_pass_info.sType = vk::StructureType::eRenderPassCreateInfo;
render_pass_info.pNext = nullptr; render_pass_info.pNext = nullptr;
render_pass_info.flags = 0; render_pass_info.flags = {};
render_pass_info.attachmentCount = color_count + (with_depth ? 1u : 0u); render_pass_info.attachmentCount = color_count + (with_depth ? 1u : 0u);
render_pass_info.pAttachments = attachments; render_pass_info.pAttachments = attachments;
render_pass_info.subpassCount = 1; render_pass_info.subpassCount = 1;
@@ -221,10 +227,10 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
render_pass_info.pDependencies = dependencies; render_pass_info.pDependencies = dependencies;
auto result = auto result =
vkCreateRenderPass(gctx->device, &render_pass_info, nullptr, &framebuffer->render_pass); gctx->device.createRenderPass(&render_pass_info, nullptr, &framebuffer->render_pass);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
VkFormat color_formats[RENDER_COLOR_ATTACHMENTS_MAX] = {}; vk::Format color_formats[RENDER_COLOR_ATTACHMENTS_MAX] = {};
for (uint32_t i = 0; i < color_count; i++) { for (uint32_t i = 0; i < color_count; i++) {
color_formats[i] = colors[i].format; color_formats[i] = colors[i].format;
} }
@@ -233,7 +239,7 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
EXIT_NOT_IMPLEMENTED(framebuffer->render_pass == nullptr); EXIT_NOT_IMPLEMENTED(framebuffer->render_pass == nullptr);
VkImageView views[RENDER_COLOR_ATTACHMENTS_MAX + 1] = {}; vk::ImageView views[RENDER_COLOR_ATTACHMENTS_MAX + 1] = {};
for (uint32_t i = 0; i < color_count; i++) { for (uint32_t i = 0; i < color_count; i++) {
if (colors[i].vulkan_view == nullptr) { if (colors[i].vulkan_view == nullptr) {
EXIT("Framebuffer: color attachment view is missing at slot %u\n", i); EXIT("Framebuffer: color attachment view is missing at slot %u\n", i);
@@ -247,10 +253,10 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
views[color_count] = depth->vulkan_view; views[color_count] = depth->vulkan_view;
} }
VkFramebufferCreateInfo framebuffer_info {}; vk::FramebufferCreateInfo framebuffer_info {};
framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebuffer_info.sType = vk::StructureType::eFramebufferCreateInfo;
framebuffer_info.pNext = nullptr; framebuffer_info.pNext = nullptr;
framebuffer_info.flags = 0; framebuffer_info.flags = {};
framebuffer_info.renderPass = framebuffer->render_pass; framebuffer_info.renderPass = framebuffer->render_pass;
framebuffer_info.attachmentCount = color_count + (with_depth ? 1u : 0u); framebuffer_info.attachmentCount = color_count + (with_depth ? 1u : 0u);
framebuffer_info.pAttachments = views; framebuffer_info.pAttachments = views;
@@ -258,9 +264,8 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
framebuffer_info.height = first_color_extent.height; framebuffer_info.height = first_color_extent.height;
framebuffer_info.layers = 1; framebuffer_info.layers = 1;
result = result = gctx->device.createFramebuffer(&framebuffer_info, nullptr, &framebuffer->framebuffer);
vkCreateFramebuffer(gctx->device, &framebuffer_info, nullptr, &framebuffer->framebuffer); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
EXIT_NOT_IMPLEMENTED(framebuffer->framebuffer == nullptr); EXIT_NOT_IMPLEMENTED(framebuffer->framebuffer == nullptr);
@@ -316,9 +321,9 @@ void FramebufferCache::FreeFramebufferByColor(VulkanImage* image) {
EXIT_IF(gctx == nullptr); EXIT_IF(gctx == nullptr);
vkDestroyFramebuffer(gctx->device, f.framebuffer->framebuffer, nullptr); gctx->device.destroyFramebuffer(f.framebuffer->framebuffer, nullptr);
vkDestroyRenderPass(gctx->device, f.framebuffer->render_pass, nullptr); gctx->device.destroyRenderPass(f.framebuffer->render_pass, nullptr);
delete f.framebuffer; delete f.framebuffer;
@@ -339,9 +344,9 @@ void FramebufferCache::FreeFramebufferByDepth(DepthStencilVulkanImage* image) {
EXIT_IF(gctx == nullptr); EXIT_IF(gctx == nullptr);
vkDestroyFramebuffer(gctx->device, f.framebuffer->framebuffer, nullptr); gctx->device.destroyFramebuffer(f.framebuffer->framebuffer, nullptr);
vkDestroyRenderPass(gctx->device, f.framebuffer->render_pass, nullptr); gctx->device.destroyRenderPass(f.framebuffer->render_pass, nullptr);
delete f.framebuffer; delete f.framebuffer;
@@ -350,7 +355,7 @@ void FramebufferCache::FreeFramebufferByDepth(DepthStencilVulkanImage* image) {
} }
} }
VideoOutVulkanImage* FramebufferCache::CreateDummyBuffer(VkFormat format, uint32_t width, VideoOutVulkanImage* FramebufferCache::CreateDummyBuffer(vk::Format format, uint32_t width,
uint32_t height) { uint32_t height) {
for (auto* b: m_dummy_buffers) { for (auto* b: m_dummy_buffers) {
if (b->extent.width == width && b->extent.height == height && b->format == format) { if (b->extent.width == width && b->extent.height == height && b->format == format) {
@@ -368,55 +373,55 @@ VideoOutVulkanImage* FramebufferCache::CreateDummyBuffer(VkFormat format, uint32
vk_obj->extent.height = height; vk_obj->extent.height = height;
vk_obj->format = format; vk_obj->format = format;
vk_obj->image = nullptr; vk_obj->image = nullptr;
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED; vk_obj->layout = vk::ImageLayout::eUndefined;
UtilResetImageViews(vk_obj); UtilResetImageViews(vk_obj);
VkImageCreateInfo image_info {}; vk::ImageCreateInfo image_info {};
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; image_info.sType = vk::StructureType::eImageCreateInfo;
image_info.pNext = nullptr; image_info.pNext = nullptr;
image_info.flags = 0; image_info.flags = {};
image_info.imageType = VK_IMAGE_TYPE_2D; image_info.imageType = vk::ImageType::e2D;
image_info.extent.width = vk_obj->extent.width; image_info.extent.width = vk_obj->extent.width;
image_info.extent.height = vk_obj->extent.height; image_info.extent.height = vk_obj->extent.height;
image_info.extent.depth = 1; image_info.extent.depth = 1;
image_info.mipLevels = 1; image_info.mipLevels = 1;
image_info.arrayLayers = 1; image_info.arrayLayers = 1;
image_info.format = vk_obj->format; image_info.format = vk_obj->format;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL; image_info.tiling = vk::ImageTiling::eOptimal;
image_info.initialLayout = vk_obj->layout; image_info.initialLayout = vk_obj->layout;
image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; image_info.usage = vk::ImageUsageFlagBits::eColorAttachment;
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; image_info.sharingMode = vk::SharingMode::eExclusive;
image_info.samples = VK_SAMPLE_COUNT_1_BIT; image_info.samples = vk::SampleCountFlagBits::e1;
VulkanMemory mem; VulkanMemory mem;
mem.property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; mem.property = vk::MemoryPropertyFlagBits::eDeviceLocal;
bool created = VulkanCreateImage(ctx, &image_info, vk_obj, &mem); bool created = VulkanCreateImage(ctx, &image_info, vk_obj, &mem);
EXIT_NOT_IMPLEMENTED(!created); EXIT_NOT_IMPLEMENTED(!created);
vk_obj->memory = mem; vk_obj->memory = mem;
VkImageViewCreateInfo create_info {}; vk::ImageViewCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; create_info.sType = vk::StructureType::eImageViewCreateInfo;
create_info.pNext = nullptr; create_info.pNext = nullptr;
create_info.flags = 0; create_info.flags = {};
create_info.image = vk_obj->image; create_info.image = vk_obj->image;
create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; create_info.viewType = vk::ImageViewType::e2D;
create_info.format = vk_obj->format; create_info.format = vk_obj->format;
create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; create_info.components.r = vk::ComponentSwizzle::eIdentity;
create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; create_info.components.g = vk::ComponentSwizzle::eIdentity;
create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; create_info.components.b = vk::ComponentSwizzle::eIdentity;
create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; create_info.components.a = vk::ComponentSwizzle::eIdentity;
create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; create_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
create_info.subresourceRange.baseArrayLayer = 0; create_info.subresourceRange.baseArrayLayer = 0;
create_info.subresourceRange.baseMipLevel = 0; create_info.subresourceRange.baseMipLevel = 0;
create_info.subresourceRange.layerCount = 1; create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = 1; create_info.subresourceRange.levelCount = 1;
vkCreateImageView(ctx->device, &create_info, nullptr, ctx->device.createImageView(&create_info, nullptr,
&vk_obj->image_view[VulkanImage::VIEW_DEFAULT]); &vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr); EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);
@@ -7,28 +7,28 @@
#include "common/threads.h" #include "common/threads.h"
#include "graphics/host_gpu/graphicContext.h" #include "graphics/host_gpu/graphicContext.h"
#include "graphics/host_gpu/renderer/renderTarget.h" #include "graphics/host_gpu/renderer/renderTarget.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <vector> #include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
struct RenderColorInfo; struct RenderColorInfo;
struct RenderDepthInfo; struct RenderDepthInfo;
static constexpr VkImageLayout RENDER_COLOR_IMAGE_LAYOUT = VK_IMAGE_LAYOUT_GENERAL; static constexpr vk::ImageLayout RENDER_COLOR_IMAGE_LAYOUT = vk::ImageLayout::eGeneral;
struct VulkanFramebuffer { struct VulkanFramebuffer {
VkRenderPass render_pass = nullptr; vk::RenderPass render_pass = nullptr;
uint64_t render_pass_id = 0; uint64_t render_pass_id = 0;
VkFramebuffer framebuffer = nullptr; vk::Framebuffer framebuffer = nullptr;
VkImageLayout color_layout[RENDER_COLOR_ATTACHMENTS_MAX] = {}; vk::ImageLayout color_layout[RENDER_COLOR_ATTACHMENTS_MAX] = {};
VkImageLayout depth_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; vk::ImageLayout depth_layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
}; };
inline uint64_t render_pass_compat_id(uint32_t color_count, const VkFormat* color_formats, inline uint64_t render_pass_compat_id(uint32_t color_count, const vk::Format* color_formats,
bool with_depth, VkFormat depth_format, bool with_depth, vk::Format depth_format,
VkImageLayout depth_layout) { vk::ImageLayout depth_layout) {
uint64_t id = 0xcbf29ce484222325ull; uint64_t id = 0xcbf29ce484222325ull;
auto mix = [&id](uint64_t v) { auto mix = [&id](uint64_t v) {
id ^= v; id ^= v;
@@ -42,7 +42,7 @@ inline uint64_t render_pass_compat_id(uint32_t color_count, const VkFormat* colo
mix(with_depth ? 1u : 0u); mix(with_depth ? 1u : 0u);
mix(static_cast<uint32_t>(depth_format)); mix(static_cast<uint32_t>(depth_format));
mix(static_cast<uint32_t>(depth_layout)); mix(static_cast<uint32_t>(depth_layout));
mix(VK_SAMPLE_COUNT_1_BIT); mix(static_cast<uint32_t>(vk::SampleCountFlagBits::e1));
return id; return id;
} }
@@ -59,16 +59,16 @@ public:
void FreeFramebufferByDepth(DepthStencilVulkanImage* image); void FreeFramebufferByDepth(DepthStencilVulkanImage* image);
private: private:
VideoOutVulkanImage* CreateDummyBuffer(VkFormat format, uint32_t width, uint32_t height); VideoOutVulkanImage* CreateDummyBuffer(vk::Format format, uint32_t width, uint32_t height);
struct Framebuffer { struct Framebuffer {
VulkanFramebuffer* framebuffer = nullptr; VulkanFramebuffer* framebuffer = nullptr;
uint64_t image_id[RENDER_COLOR_ATTACHMENTS_MAX] = {}; uint64_t image_id[RENDER_COLOR_ATTACHMENTS_MAX] = {};
VkImageView color_view[RENDER_COLOR_ATTACHMENTS_MAX] = {}; vk::ImageView color_view[RENDER_COLOR_ATTACHMENTS_MAX] = {};
uint64_t depth_id = 0; uint64_t depth_id = 0;
VkImageView depth_view = nullptr; vk::ImageView depth_view = nullptr;
bool color_clear_enable[RENDER_COLOR_ATTACHMENTS_MAX] = {}; bool color_clear_enable[RENDER_COLOR_ATTACHMENTS_MAX] = {};
VkImageLayout color_layout[RENDER_COLOR_ATTACHMENTS_MAX] = {}; vk::ImageLayout color_layout[RENDER_COLOR_ATTACHMENTS_MAX] = {};
bool depth_clear_enable = false; bool depth_clear_enable = false;
bool stencil_clear_enable = false; bool stencil_clear_enable = false;
bool depth_read_only = false; bool depth_read_only = false;
+4 -4
View File
@@ -10,10 +10,10 @@ void GdsBuffer::Init(GraphicContext* ctx) {
if (m_buffer == nullptr) { if (m_buffer == nullptr) {
m_buffer = std::make_unique<VulkanBuffer>(); m_buffer = std::make_unique<VulkanBuffer>();
m_buffer->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; m_buffer->usage = vk::BufferUsageFlagBits::eStorageBuffer;
m_buffer->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) | m_buffer->memory.property = vk::MemoryPropertyFlagBits::eHostVisible |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | vk::MemoryPropertyFlagBits::eHostCoherent |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT; vk::MemoryPropertyFlagBits::eHostCached;
VulkanCreateBuffer(ctx, DW_SIZE * 4, m_buffer.get()); VulkanCreateBuffer(ctx, DW_SIZE * 4, m_buffer.get());
} }
} }
+68 -66
View File
@@ -47,42 +47,43 @@ TextureImageCreateParams MakeImageParams(const ImageInfo& info, bool storage) {
return params; return params;
} }
bool RenderTargetSupportsStorage(GraphicContext* ctx, VkFormat format, VkImageCreateFlags flags) { bool RenderTargetSupportsStorage(GraphicContext* ctx, vk::Format format,
vk::ImageCreateFlags flags) {
const auto compatible = SrgbStorageViewFormat(format); const auto compatible = SrgbStorageViewFormat(format);
const auto required_flags = const auto required_flags =
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; vk::ImageCreateFlagBits::eMutableFormat | vk::ImageCreateFlagBits::eExtendedUsage;
const bool compatible_views = (flags & required_flags) == required_flags; const bool compatible_views = (flags & required_flags) == required_flags;
return ImageViewOps::FormatSupportsStorage(ctx, format) || return ImageViewOps::FormatSupportsStorage(ctx, format) ||
(compatible_views && compatible != VK_FORMAT_UNDEFINED && (compatible_views && compatible != vk::Format::eUndefined &&
ImageViewOps::FormatSupportsStorage(ctx, compatible)); ImageViewOps::FormatSupportsStorage(ctx, compatible));
} }
VkImageCreateFlags RenderTargetCreateFlags(VkFormat format) { vk::ImageCreateFlags RenderTargetCreateFlags(vk::Format format) {
const bool compatible_format_view = const bool compatible_format_view =
IsRgba8SrgbViewFormat(format) || IsRgba8SrgbViewFormat(format) ||
BgraToRgbaSampledViewFormat(format) != VK_FORMAT_UNDEFINED || BgraToRgbaSampledViewFormat(format) != vk::Format::eUndefined ||
format == VK_FORMAT_R8G8B8A8_UINT || format == VK_FORMAT_R16G16B16A16_SFLOAT || format == vk::Format::eR8G8B8A8Uint || format == vk::Format::eR16G16B16A16Sfloat ||
format == VK_FORMAT_R16G16B16A16_UINT; format == vk::Format::eR16G16B16A16Uint;
return compatible_format_view return compatible_format_view
? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT ? vk::ImageCreateFlagBits::eMutableFormat | vk::ImageCreateFlagBits::eExtendedUsage
: VkImageCreateFlags {0}; : vk::ImageCreateFlags {0};
} }
VkImageUsageFlags RenderTargetUsage(GraphicContext* ctx, VkFormat format, vk::ImageUsageFlags RenderTargetUsage(GraphicContext* ctx, vk::Format format,
VkImageCreateFlags flags) { vk::ImageCreateFlags flags) {
auto usage = static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) | auto usage = static_cast<vk::ImageUsageFlags>(vk::ImageUsageFlagBits::eColorAttachment) |
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_SRC_BIT) | static_cast<vk::ImageUsageFlags>(vk::ImageUsageFlagBits::eTransferSrc) |
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_DST_BIT) | static_cast<vk::ImageUsageFlags>(vk::ImageUsageFlagBits::eTransferDst) |
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_SAMPLED_BIT); static_cast<vk::ImageUsageFlags>(vk::ImageUsageFlagBits::eSampled);
if (RenderTargetSupportsStorage(ctx, format, flags)) { if (RenderTargetSupportsStorage(ctx, format, flags)) {
usage |= VK_IMAGE_USAGE_STORAGE_BIT; usage |= vk::ImageUsageFlagBits::eStorage;
} }
VkImageFormatProperties properties {}; vk::ImageFormatProperties properties {};
if (ctx->GetImageFormatProperties(format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, if (ctx->GetImageFormatProperties(format, vk::ImageType::e2D, vk::ImageTiling::eOptimal, usage,
flags, &properties) != VK_SUCCESS) { flags, &properties) != vk::Result::eSuccess) {
EXIT("TextureCache: render-target format does not support required usage, format=%d " EXIT("TextureCache: render-target format does not support required usage, format=%d "
"usage=0x%x\n", "usage=0x%x\n",
static_cast<int>(format), usage); static_cast<int>(format), static_cast<vk::ImageUsageFlags::MaskType>(usage));
} }
return usage; return usage;
} }
@@ -139,7 +140,7 @@ uint32_t RenderTargetTransferFormat(uint32_t bytes_per_element) {
} }
GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info, bool storage, GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info, bool storage,
VulkanMemory* memory, VkComponentMapping* components) { VulkanMemory* memory, vk::ComponentMapping* components) {
if (components == nullptr) { if (components == nullptr) {
EXIT("TextureCache: invalid texture component output\n"); EXIT("TextureCache: invalid texture component output\n");
} }
@@ -150,7 +151,7 @@ GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info,
} }
void CreateTextureViews(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info, void CreateTextureViews(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info,
bool storage, VkComponentMapping components) { bool storage, vk::ComponentMapping components) {
if (storage) { if (storage) {
TextureCreateImageViews(ctx, image, components, info.type, 0, 0, 1, info.depth, false, TextureCreateImageViews(ctx, image, components, info.type, 0, 0, 1, info.depth, false,
TextureFormatUsage::Sampled | TextureFormatUsage::Storage); TextureFormatUsage::Sampled | TextureFormatUsage::Storage);
@@ -195,11 +196,11 @@ void UploadRenderTargetLayers(GraphicContext* ctx, RenderTextureVulkanImage* ima
region.dst_layer += base_layer; region.dst_layer += base_layer;
} }
const auto source_address = info.address + slice_size * base_layer; const auto source_address = info.address + slice_size * base_layer;
TextureUploadGuestImage( TextureUploadGuestImage(ctx, image, reinterpret_cast<const void*>(source_address),
ctx, image, reinterpret_cast<const void*>(source_address), upload_size, regions, layout, upload_size, regions, layout, format, info.width, info.height,
format, info.width, info.height, layer_count, info.levels, layer_count, info.levels,
TextureUploadSliceLayout::MipChainPerSlice, "TextureCache render target", TextureUploadSliceLayout::MipChainPerSlice,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_GENERAL)); "TextureCache render target", vk::ImageLayout::eGeneral);
return; return;
} }
if (info.tile_mode == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) && if (info.tile_mode == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
@@ -209,10 +210,10 @@ void UploadRenderTargetLayers(GraphicContext* ctx, RenderTextureVulkanImage* ima
scratch.Data(), reinterpret_cast<const void*>(info.address), info.width, info.height, scratch.Data(), reinterpret_cast<const void*>(info.address), info.width, info.height,
info.pitch, info.bytes_per_element, slice_size); info.pitch, info.bytes_per_element, slice_size);
UtilFillImage(ctx, image, scratch.Data(), slice_size, info.pitch, UtilFillImage(ctx, image, scratch.Data(), slice_size, info.pitch,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_GENERAL)); vk::ImageLayout::eGeneral);
} else { } else {
UtilFillImage(ctx, image, reinterpret_cast<const void*>(info.address), slice_size, UtilFillImage(ctx, image, reinterpret_cast<const void*>(info.address), slice_size,
info.pitch, static_cast<uint64_t>(VK_IMAGE_LAYOUT_GENERAL)); info.pitch, vk::ImageLayout::eGeneral);
} }
} }
@@ -229,22 +230,22 @@ RenderTextureVulkanImage* CreateRenderTarget(GraphicContext* ctx, const RenderTa
image->format = info.format; image->format = info.format;
image->mip_levels = info.levels; image->mip_levels = info.levels;
image->layers = info.layers; image->layers = info.layers;
image->layout = VK_IMAGE_LAYOUT_UNDEFINED; image->layout = vk::ImageLayout::eUndefined;
UtilResetImageViews(image); UtilResetImageViews(image);
VkImageCreateInfo create {}; vk::ImageCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; create.sType = vk::StructureType::eImageCreateInfo;
create.flags = RenderTargetCreateFlags(info.format); create.flags = RenderTargetCreateFlags(info.format);
create.imageType = VK_IMAGE_TYPE_2D; create.imageType = vk::ImageType::e2D;
create.extent = {info.width, info.height, 1}; create.extent = {info.width, info.height, 1};
create.mipLevels = info.levels; create.mipLevels = info.levels;
create.arrayLayers = info.layers; create.arrayLayers = info.layers;
create.format = info.format; create.format = info.format;
create.tiling = VK_IMAGE_TILING_OPTIMAL; create.tiling = vk::ImageTiling::eOptimal;
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; create.initialLayout = vk::ImageLayout::eUndefined;
create.usage = RenderTargetUsage(ctx, info.format, create.flags); create.usage = RenderTargetUsage(ctx, info.format, create.flags);
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE; create.sharingMode = vk::SharingMode::eExclusive;
create.samples = VK_SAMPLE_COUNT_1_BIT; create.samples = vk::SampleCountFlagBits::e1;
memory->property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; memory->property = vk::MemoryPropertyFlagBits::eDeviceLocal;
if (!VulkanCreateImage(ctx, &create, image, memory)) { if (!VulkanCreateImage(ctx, &create, image, memory)) {
EXIT("TextureCache: failed to create render target, addr=0x%016" PRIx64 EXIT("TextureCache: failed to create render target, addr=0x%016" PRIx64
" extent=%ux%u format=%d\n", " extent=%ux%u format=%d\n",
@@ -257,23 +258,25 @@ RenderTextureVulkanImage* CreateRenderTarget(GraphicContext* ctx, const RenderTa
DepthStencilVulkanImage* CreateDepthTarget(GraphicContext* ctx, const DepthTargetInfo& info, DepthStencilVulkanImage* CreateDepthTarget(GraphicContext* ctx, const DepthTargetInfo& info,
VulkanMemory* memory) { VulkanMemory* memory) {
VkImageCreateInfo create {}; vk::ImageCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; create.sType = vk::StructureType::eImageCreateInfo;
create.imageType = VK_IMAGE_TYPE_2D; create.imageType = vk::ImageType::e2D;
create.extent = {info.width, info.height, 1}; create.extent = {info.width, info.height, 1};
create.mipLevels = 1; create.mipLevels = 1;
create.arrayLayers = info.layers; create.arrayLayers = info.layers;
create.format = info.format; create.format = info.format;
create.tiling = VK_IMAGE_TILING_OPTIMAL; create.tiling = vk::ImageTiling::eOptimal;
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; create.initialLayout = vk::ImageLayout::eUndefined;
create.usage = DepthTargetImageUsage(); create.usage = DepthTargetImageUsage();
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE; create.sharingMode = vk::SharingMode::eExclusive;
create.samples = VK_SAMPLE_COUNT_1_BIT; create.samples = vk::SampleCountFlagBits::e1;
VkImageFormatProperties properties {}; vk::ImageFormatProperties properties {};
if (ctx->GetImageFormatProperties(info.format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, if (ctx->GetImageFormatProperties(info.format, vk::ImageType::e2D, vk::ImageTiling::eOptimal,
create.usage, 0, &properties) != VK_SUCCESS) { create.usage, vk::ImageCreateFlags {},
&properties) != vk::Result::eSuccess) {
EXIT("TextureCache: depth format does not support required usage, format=%d usage=0x%x\n", EXIT("TextureCache: depth format does not support required usage, format=%d usage=0x%x\n",
static_cast<int>(info.format), create.usage); static_cast<int>(info.format),
static_cast<vk::ImageUsageFlags::MaskType>(create.usage));
} }
auto* image = new DepthStencilVulkanImage; auto* image = new DepthStencilVulkanImage;
image->extent.width = info.width; image->extent.width = info.width;
@@ -281,10 +284,10 @@ DepthStencilVulkanImage* CreateDepthTarget(GraphicContext* ctx, const DepthTarge
image->guest_pitch = info.pitch; image->guest_pitch = info.pitch;
image->layers = info.layers; image->layers = info.layers;
image->format = info.format; image->format = info.format;
image->layout = VK_IMAGE_LAYOUT_UNDEFINED; image->layout = vk::ImageLayout::eUndefined;
image->compressed = false; image->compressed = false;
UtilResetImageViews(image); UtilResetImageViews(image);
memory->property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; memory->property = vk::MemoryPropertyFlagBits::eDeviceLocal;
if (!VulkanCreateImage(ctx, &create, image, memory)) { if (!VulkanCreateImage(ctx, &create, image, memory)) {
EXIT("TextureCache: failed to create depth target, addr=0x%016" PRIx64 EXIT("TextureCache: failed to create depth target, addr=0x%016" PRIx64
" extent=%ux%u format=%d\n", " extent=%ux%u format=%d\n",
@@ -328,7 +331,7 @@ void ValidateVideoOut(GraphicContext* ctx, const VideoOutInfo& info) {
" pitch=%u\n", " pitch=%u\n",
info.address, info.size, exact.size, exact.align, info.pitch); info.address, info.size, exact.size, exact.align, info.pitch);
} }
(void)RenderTargetUsage(ctx, info.format, 0); (void)RenderTargetUsage(ctx, info.format, vk::ImageCreateFlags {});
} }
VideoOutVulkanImage* CreateVideoOut(GraphicContext* ctx, const VideoOutInfo& info, VideoOutVulkanImage* CreateVideoOut(GraphicContext* ctx, const VideoOutInfo& info,
@@ -337,22 +340,22 @@ VideoOutVulkanImage* CreateVideoOut(GraphicContext* ctx, const VideoOutInfo& inf
image->extent.width = info.width; image->extent.width = info.width;
image->extent.height = info.height; image->extent.height = info.height;
image->format = info.format; image->format = info.format;
image->layout = VK_IMAGE_LAYOUT_UNDEFINED; image->layout = vk::ImageLayout::eUndefined;
UtilResetImageViews(image); UtilResetImageViews(image);
VkImageCreateInfo create {}; vk::ImageCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; create.sType = vk::StructureType::eImageCreateInfo;
create.imageType = VK_IMAGE_TYPE_2D; create.imageType = vk::ImageType::e2D;
create.extent = {info.width, info.height, 1}; create.extent = {info.width, info.height, 1};
create.mipLevels = 1; create.mipLevels = 1;
create.arrayLayers = 1; create.arrayLayers = 1;
create.format = info.format; create.format = info.format;
create.tiling = VK_IMAGE_TILING_OPTIMAL; create.tiling = vk::ImageTiling::eOptimal;
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; create.initialLayout = vk::ImageLayout::eUndefined;
create.flags = RenderTargetCreateFlags(info.format); create.flags = RenderTargetCreateFlags(info.format);
create.usage = RenderTargetUsage(ctx, info.format, create.flags); create.usage = RenderTargetUsage(ctx, info.format, create.flags);
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE; create.sharingMode = vk::SharingMode::eExclusive;
create.samples = VK_SAMPLE_COUNT_1_BIT; create.samples = vk::SampleCountFlagBits::e1;
memory->property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; memory->property = vk::MemoryPropertyFlagBits::eDeviceLocal;
if (!VulkanCreateImage(ctx, &create, image, memory)) { if (!VulkanCreateImage(ctx, &create, image, memory)) {
EXIT("TextureCache: failed to create video-out image, addr=0x%016" PRIx64 EXIT("TextureCache: failed to create video-out image, addr=0x%016" PRIx64
" extent=%ux%u format=%d\n", " extent=%ux%u format=%d\n",
@@ -373,7 +376,7 @@ void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const Video
if (refresh) { if (refresh) {
VulkanDeviceWaitIdle(ctx); VulkanDeviceWaitIdle(ctx);
} }
image->layout = VK_IMAGE_LAYOUT_UNDEFINED; image->layout = vk::ImageLayout::eUndefined;
UtilScratchBuffer scratch(info.size); UtilScratchBuffer scratch(info.size);
TileConvertTiledToLinearRenderTarget( TileConvertTiledToLinearRenderTarget(
scratch.Data(), reinterpret_cast<const void*>(info.address), info.width, info.height, scratch.Data(), reinterpret_cast<const void*>(info.address), info.width, info.height,
@@ -384,8 +387,7 @@ void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const Video
std::swap(pixels[i], pixels[i + 2]); std::swap(pixels[i], pixels[i + 2]);
} }
} }
UtilFillImage(ctx, image, scratch.Data(), info.size, info.pitch, UtilFillImage(ctx, image, scratch.Data(), info.size, info.pitch, vk::ImageLayout::eGeneral);
static_cast<uint64_t>(VK_IMAGE_LAYOUT_GENERAL));
} }
GpuTextureVulkanImage* CreateDummyTexture(GraphicContext* ctx, bool uint_format, bool image_3d, GpuTextureVulkanImage* CreateDummyTexture(GraphicContext* ctx, bool uint_format, bool image_3d,
@@ -398,14 +400,14 @@ GpuTextureVulkanImage* CreateDummyTexture(GraphicContext* ctx, bool uint_format,
auto* image = storage ? static_cast<GpuTextureVulkanImage*>(new StorageTextureVulkanImage) auto* image = storage ? static_cast<GpuTextureVulkanImage*>(new StorageTextureVulkanImage)
: new TextureVulkanImage; : new TextureVulkanImage;
auto usage = storage ? TextureFormatUsage::Storage : TextureFormatUsage::Sampled; auto usage = storage ? TextureFormatUsage::Storage : TextureFormatUsage::Sampled;
auto layout = storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; auto layout = storage ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;
auto owner = storage ? "DummyStorageTexture" : "DummySampledTexture"; auto owner = storage ? "DummyStorageTexture" : "DummySampledTexture";
auto params = MakeDummyTextureParams(uint_format, image_3d, usage, owner); auto params = MakeDummyTextureParams(uint_format, image_3d, usage, owner);
auto components = TextureCreateImage(ctx, image, memory, params); auto components = TextureCreateImage(ctx, image, memory, params);
static constexpr uint32_t zero = 0; static constexpr uint32_t zero = 0;
UtilFillImage(ctx, image, &zero, sizeof(zero), 1, static_cast<uint64_t>(layout)); UtilFillImage(ctx, image, &zero, sizeof(zero), 1, layout);
TextureCreateImageViews(ctx, image, components, params.type, 0, params.base_level, TextureCreateImageViews(ctx, image, components, params.type, 0, params.base_level,
params.levels, params.depth, params.allow_cube_view, params.view_usage); params.levels, params.depth, params.allow_cube_view, params.view_usage);
return image; return image;
+2 -2
View File
@@ -102,9 +102,9 @@ namespace ImageOps {
[[nodiscard]] GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info, [[nodiscard]] GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info,
bool storage, VulkanMemory* memory, bool storage, VulkanMemory* memory,
VkComponentMapping* components); vk::ComponentMapping* components);
void CreateTextureViews(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info, void CreateTextureViews(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info,
bool storage, VkComponentMapping components); bool storage, vk::ComponentMapping components);
[[nodiscard]] RenderTextureVulkanImage* [[nodiscard]] RenderTextureVulkanImage*
CreateRenderTarget(GraphicContext* ctx, const RenderTargetInfo& info, VulkanMemory* memory); CreateRenderTarget(GraphicContext* ctx, const RenderTargetInfo& info, VulkanMemory* memory);
+131 -130
View File
@@ -4,12 +4,12 @@
#include "common/assert.h" #include "common/assert.h"
#include "graphics/guest_gpu/gpu_defs.h" #include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/host_gpu/regionDefinitions.h" #include "graphics/host_gpu/regionDefinitions.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <array> #include <array>
#include <bit> #include <bit>
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -31,34 +31,34 @@ struct ImageInfo {
}; };
struct RenderTargetInfo { struct RenderTargetInfo {
uint64_t address = 0; uint64_t address = 0;
uint64_t size = 0; uint64_t size = 0;
VkFormat format = VK_FORMAT_UNDEFINED; vk::Format format = vk::Format::eUndefined;
uint32_t width = 0; uint32_t width = 0;
uint32_t height = 0; uint32_t height = 0;
uint32_t pitch = 0; uint32_t pitch = 0;
uint32_t bytes_per_element = 0; uint32_t bytes_per_element = 0;
uint32_t tile_mode = 0; uint32_t tile_mode = 0;
uint32_t levels = 1; uint32_t levels = 1;
uint32_t layers = 1; uint32_t layers = 1;
}; };
// Common image-to-buffer copy description. Storage images and render targets keep distinct // Common image-to-buffer copy description. Storage images and render targets keep distinct
// cache records today, but downloads should consume one normalized layout just as uploads do. // cache records today, but downloads should consume one normalized layout just as uploads do.
struct ColorImageTransferInfo { struct ColorImageTransferInfo {
uint64_t address = 0; uint64_t address = 0;
uint64_t size = 0; uint64_t size = 0;
VkFormat format = VK_FORMAT_UNDEFINED; vk::Format format = vk::Format::eUndefined;
uint32_t width = 0; uint32_t width = 0;
uint32_t height = 0; uint32_t height = 0;
uint32_t pitch = 0; uint32_t pitch = 0;
uint32_t bytes_per_element = 0; uint32_t bytes_per_element = 0;
uint32_t tile_mode = 0; uint32_t tile_mode = 0;
uint32_t levels = 1; uint32_t levels = 1;
}; };
[[nodiscard]] inline ColorImageTransferInfo [[nodiscard]] inline ColorImageTransferInfo
MakeColorImageTransferInfo(const ImageInfo& info, VkFormat format, MakeColorImageTransferInfo(const ImageInfo& info, vk::Format format,
uint32_t bytes_per_element) noexcept { uint32_t bytes_per_element) noexcept {
return {info.address, info.size, format, info.width, info.height, return {info.address, info.size, format, info.width, info.height,
info.pitch, bytes_per_element, info.tile, info.levels}; info.pitch, bytes_per_element, info.tile, info.levels};
@@ -72,48 +72,48 @@ MakeColorImageTransferInfo(const RenderTargetInfo& info) noexcept {
} }
struct DepthTargetInfo { struct DepthTargetInfo {
uint64_t address = 0; uint64_t address = 0;
uint64_t size = 0; uint64_t size = 0;
uint64_t stencil_address = 0; uint64_t stencil_address = 0;
uint64_t stencil_size = 0; uint64_t stencil_size = 0;
uint64_t htile_address = 0; uint64_t htile_address = 0;
uint64_t htile_size = 0; uint64_t htile_size = 0;
VkFormat format = VK_FORMAT_UNDEFINED; vk::Format format = vk::Format::eUndefined;
uint32_t guest_format = 0; uint32_t guest_format = 0;
uint32_t width = 0; uint32_t width = 0;
uint32_t height = 0; uint32_t height = 0;
uint32_t pitch = 0; uint32_t pitch = 0;
uint32_t bytes_per_element = 0; uint32_t bytes_per_element = 0;
uint32_t tile_mode = 0; uint32_t tile_mode = 0;
uint32_t layers = 1; uint32_t layers = 1;
bool depth_load_clear = false; bool depth_load_clear = false;
bool stencil_load_clear = false; bool stencil_load_clear = false;
bool stencil_access = false; bool stencil_access = false;
bool stencil_htile_compressed = false; bool stencil_htile_compressed = false;
}; };
struct DepthFormatPolicy { struct DepthFormatPolicy {
Prospero::DepthFormat depth_format; Prospero::DepthFormat depth_format;
Prospero::BufferFormat guest_format; Prospero::BufferFormat guest_format;
uint32_t bytes_per_element; uint32_t bytes_per_element;
VkFormat sampled_view_format; vk::Format sampled_view_format;
VkFormat depth_attachment_format; vk::Format depth_attachment_format;
std::array<VkFormat, 3> stencil_attachment_formats; std::array<vk::Format, 3> stencil_attachment_formats;
}; };
inline constexpr std::array<DepthFormatPolicy, 2> DEPTH_FORMAT_POLICIES {{ inline constexpr std::array<DepthFormatPolicy, 2> DEPTH_FORMAT_POLICIES {{
{Prospero::DepthFormat::kZ16, {Prospero::DepthFormat::kZ16,
Prospero::BufferFormat::k16UNorm, Prospero::BufferFormat::k16UNorm,
2, 2,
VK_FORMAT_R16_UNORM, vk::Format::eR16Unorm,
VK_FORMAT_D16_UNORM, vk::Format::eD16Unorm,
{VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT}}, {vk::Format::eD16UnormS8Uint, vk::Format::eD24UnormS8Uint, vk::Format::eD32SfloatS8Uint}},
{Prospero::DepthFormat::kZ32F, {Prospero::DepthFormat::kZ32F,
Prospero::BufferFormat::k32Float, Prospero::BufferFormat::k32Float,
4, 4,
VK_FORMAT_R32_SFLOAT, vk::Format::eR32Sfloat,
VK_FORMAT_D32_SFLOAT, vk::Format::eD32Sfloat,
{VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED}}, {vk::Format::eD32SfloatS8Uint, vk::Format::eUndefined, vk::Format::eUndefined}},
}}; }};
[[nodiscard]] inline constexpr const DepthFormatPolicy* [[nodiscard]] inline constexpr const DepthFormatPolicy*
@@ -137,53 +137,53 @@ FindGuestDepthFormatPolicy(uint32_t guest_format) noexcept {
} }
[[nodiscard]] inline constexpr bool IsStencilAttachmentFormat(const DepthFormatPolicy& policy, [[nodiscard]] inline constexpr bool IsStencilAttachmentFormat(const DepthFormatPolicy& policy,
VkFormat format) noexcept { vk::Format format) noexcept {
for (const auto candidate: policy.stencil_attachment_formats) { for (const auto candidate: policy.stencil_attachment_formats) {
if (candidate != VK_FORMAT_UNDEFINED && candidate == format) { if (candidate != vk::Format::eUndefined && candidate == format) {
return true; return true;
} }
} }
return false; return false;
} }
[[nodiscard]] inline constexpr VkFormat DepthAttachmentFormat(const DepthFormatPolicy& policy, [[nodiscard]] inline constexpr vk::Format DepthAttachmentFormat(const DepthFormatPolicy& policy,
bool has_stencil) noexcept { bool has_stencil) noexcept {
return has_stencil ? policy.stencil_attachment_formats.front() : policy.depth_attachment_format; return has_stencil ? policy.stencil_attachment_formats.front() : policy.depth_attachment_format;
} }
[[nodiscard]] inline constexpr VkFormat DepthAttachmentFormat(uint32_t depth_format, [[nodiscard]] inline constexpr vk::Format DepthAttachmentFormat(uint32_t depth_format,
uint32_t stencil_format) noexcept { uint32_t stencil_format) noexcept {
bool has_stencil = false; bool has_stencil = false;
switch (static_cast<Prospero::StencilFormat>(stencil_format)) { switch (static_cast<Prospero::StencilFormat>(stencil_format)) {
case Prospero::StencilFormat::kInvalid: break; case Prospero::StencilFormat::kInvalid: break;
case Prospero::StencilFormat::k8UInt: has_stencil = true; break; case Prospero::StencilFormat::k8UInt: has_stencil = true; break;
default: return VK_FORMAT_UNDEFINED; default: return vk::Format::eUndefined;
} }
const auto* policy = FindDepthFormatPolicy(depth_format); const auto* policy = FindDepthFormatPolicy(depth_format);
return policy == nullptr ? VK_FORMAT_UNDEFINED : DepthAttachmentFormat(*policy, has_stencil); return policy == nullptr ? vk::Format::eUndefined : DepthAttachmentFormat(*policy, has_stencil);
} }
[[nodiscard]] inline constexpr VkImageUsageFlags DepthTargetImageUsage() noexcept { [[nodiscard]] inline constexpr vk::ImageUsageFlags DepthTargetImageUsage() noexcept {
return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | return vk::ImageUsageFlagBits::eDepthStencilAttachment | vk::ImageUsageFlagBits::eSampled |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst;
} }
[[nodiscard]] inline constexpr VkFormat DepthAspectTransferFormat(VkFormat format) noexcept { [[nodiscard]] inline constexpr vk::Format DepthAspectTransferFormat(vk::Format format) noexcept {
switch (format) { switch (format) {
case VK_FORMAT_D16_UNORM: case vk::Format::eD16Unorm:
case VK_FORMAT_D16_UNORM_S8_UINT: return VK_FORMAT_D16_UNORM; case vk::Format::eD16UnormS8Uint: return vk::Format::eD16Unorm;
case VK_FORMAT_D24_UNORM_S8_UINT: return VK_FORMAT_X8_D24_UNORM_PACK32; case vk::Format::eD24UnormS8Uint: return vk::Format::eX8D24UnormPack32;
case VK_FORMAT_D32_SFLOAT: case vk::Format::eD32Sfloat:
case VK_FORMAT_D32_SFLOAT_S8_UINT: return VK_FORMAT_D32_SFLOAT; case vk::Format::eD32SfloatS8Uint: return vk::Format::eD32Sfloat;
default: return VK_FORMAT_UNDEFINED; default: return vk::Format::eUndefined;
} }
} }
[[nodiscard]] inline constexpr uint32_t DepthAspectTransferBytes(VkFormat format) noexcept { [[nodiscard]] inline constexpr uint32_t DepthAspectTransferBytes(vk::Format format) noexcept {
switch (DepthAspectTransferFormat(format)) { switch (DepthAspectTransferFormat(format)) {
case VK_FORMAT_D16_UNORM: return 2; case vk::Format::eD16Unorm: return 2;
case VK_FORMAT_X8_D24_UNORM_PACK32: case vk::Format::eX8D24UnormPack32:
case VK_FORMAT_D32_SFLOAT: return 4; case vk::Format::eD32Sfloat: return 4;
default: return 0; default: return 0;
} }
} }
@@ -197,17 +197,17 @@ FindGuestDepthFormatPolicy(uint32_t guest_format) noexcept {
return std::bit_cast<uint32_t>(static_cast<float>(value) / 65535.0f); return std::bit_cast<uint32_t>(static_cast<float>(value) / 65535.0f);
} }
[[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(VkFormat image_format, [[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(vk::Format image_format,
uint32_t guest_format, uint32_t guest_format,
VkFormat view_format) noexcept { vk::Format view_format) noexcept {
const auto* policy = FindGuestDepthFormatPolicy(guest_format); const auto* policy = FindGuestDepthFormatPolicy(guest_format);
return policy != nullptr && view_format == policy->sampled_view_format && return policy != nullptr && view_format == policy->sampled_view_format &&
(image_format == policy->depth_attachment_format || (image_format == policy->depth_attachment_format ||
IsStencilAttachmentFormat(*policy, image_format)); IsStencilAttachmentFormat(*policy, image_format));
} }
[[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(VkFormat image_format, [[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(vk::Format image_format,
VkFormat view_format) noexcept { vk::Format view_format) noexcept {
for (const auto& policy: DEPTH_FORMAT_POLICIES) { for (const auto& policy: DEPTH_FORMAT_POLICIES) {
if (IsSupportedSampledDepthFormat(image_format, Prospero::GpuEnumValue(policy.guest_format), if (IsSupportedSampledDepthFormat(image_format, Prospero::GpuEnumValue(policy.guest_format),
view_format)) { view_format)) {
@@ -231,7 +231,7 @@ struct VideoOutInfo {
uint64_t address = 0; uint64_t address = 0;
uint64_t size = 0; uint64_t size = 0;
uint64_t metadata_address = 0; uint64_t metadata_address = 0;
VkFormat format = VK_FORMAT_UNDEFINED; vk::Format format = vk::Format::eUndefined;
uint32_t guest_format = 0; uint32_t guest_format = 0;
uint32_t width = 0; uint32_t width = 0;
uint32_t height = 0; uint32_t height = 0;
@@ -272,10 +272,10 @@ CanUseVideoOutNativeWithoutUpload(VideoOutCompression compression, bool render_t
} }
struct VideoOutPixelFormatInfo { struct VideoOutPixelFormatInfo {
VkFormat format = VK_FORMAT_UNDEFINED; vk::Format format = vk::Format::eUndefined;
uint32_t guest_format = 0; uint32_t guest_format = 0;
uint32_t bytes_per_element = 0; uint32_t bytes_per_element = 0;
bool bgra16 = false; bool bgra16 = false;
}; };
struct VideoOutFormatPolicy { struct VideoOutFormatPolicy {
@@ -285,22 +285,22 @@ struct VideoOutFormatPolicy {
inline constexpr std::array<VideoOutFormatPolicy, 6> VIDEO_OUT_FORMAT_POLICIES {{ inline constexpr std::array<VideoOutFormatPolicy, 6> VIDEO_OUT_FORMAT_POLICIES {{
{0x8000000022000000ull, {0x8000000022000000ull,
{VK_FORMAT_R8G8B8A8_SRGB, Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb), 4, {vk::Format::eR8G8B8A8Srgb, Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb), 4,
false}}, false}},
{0x8000000000000000ull, {0x8000000000000000ull,
{VK_FORMAT_B8G8R8A8_SRGB, Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb), 4, {vk::Format::eB8G8R8A8Srgb, Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8Srgb), 4,
false}}, false}},
{0x8100000022000000ull, {0x8100000022000000ull,
{VK_FORMAT_A2B10G10R10_UNORM_PACK32, {vk::Format::eA2B10G10R10UnormPack32,
Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm), 4, false}}, Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm), 4, false}},
{0x8100000000000000ull, {0x8100000000000000ull,
{VK_FORMAT_A2R10G10B10_UNORM_PACK32, {vk::Format::eA2R10G10B10UnormPack32,
Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm), 4, false}}, Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm), 4, false}},
{0xc001000622000000ull, {0xc001000622000000ull,
{VK_FORMAT_R16G16B16A16_SFLOAT, {vk::Format::eR16G16B16A16Sfloat,
Prospero::GpuEnumValue(Prospero::BufferFormat::k16_16_16_16Float), 8, false}}, Prospero::GpuEnumValue(Prospero::BufferFormat::k16_16_16_16Float), 8, false}},
{0xc001000600000000ull, {0xc001000600000000ull,
{VK_FORMAT_R16G16B16A16_SFLOAT, {vk::Format::eR16G16B16A16Sfloat,
Prospero::GpuEnumValue(Prospero::BufferFormat::k16_16_16_16Float), 8, true}}, Prospero::GpuEnumValue(Prospero::BufferFormat::k16_16_16_16Float), 8, true}},
}}; }};
@@ -384,12 +384,12 @@ enum class MetaImageOverlap : uint8_t { RetainSampled, RetireTarget, Unsupported
} }
[[nodiscard]] inline constexpr bool [[nodiscard]] inline constexpr bool
IsDepthUintTextureReinterpretation(VkFormat image_format, uint32_t guest_format, IsDepthUintTextureReinterpretation(vk::Format image_format, uint32_t guest_format,
VkFormat view_format) noexcept { vk::Format view_format) noexcept {
switch (image_format) { switch (image_format) {
case VK_FORMAT_D32_SFLOAT: case vk::Format::eD32Sfloat:
return guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) && return guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) &&
view_format == VK_FORMAT_R32_UINT; view_format == vk::Format::eR32Uint;
default: return false; default: return false;
} }
} }
@@ -479,45 +479,45 @@ SelectDepthTransitionSource(bool depth_load_clear, bool sampled_native_available
return encoded <= 0.04045f ? encoded / 12.92f : std::pow((encoded + 0.055f) / 1.055f, 2.4f); return encoded <= 0.04045f ? encoded / 12.92f : std::pow((encoded + 0.055f) / 1.055f, 2.4f);
} }
[[nodiscard]] inline bool DecodePackedColorClear(VkFormat format, uint32_t packed, [[nodiscard]] inline bool DecodePackedColorClear(vk::Format format, uint32_t packed,
VkClearColorValue* clear) { vk::ClearColorValue* clear) {
if (clear == nullptr) { if (clear == nullptr) {
return false; return false;
} }
VkClearColorValue next {}; vk::ClearColorValue next {};
const auto unorm8 = [](uint32_t value) { return static_cast<float>(value & 0xffu) / 255.0f; }; const auto unorm8 = [](uint32_t value) { return static_cast<float>(value & 0xffu) / 255.0f; };
switch (format) { switch (format) {
case VK_FORMAT_R8G8B8A8_SRGB: case vk::Format::eR8G8B8A8Srgb:
next.float32[0] = DecodeSrgbClearComponent(packed); next.float32[0] = DecodeSrgbClearComponent(packed);
next.float32[1] = DecodeSrgbClearComponent(packed >> 8u); next.float32[1] = DecodeSrgbClearComponent(packed >> 8u);
next.float32[2] = DecodeSrgbClearComponent(packed >> 16u); next.float32[2] = DecodeSrgbClearComponent(packed >> 16u);
next.float32[3] = unorm8(packed >> 24u); next.float32[3] = unorm8(packed >> 24u);
break; break;
case VK_FORMAT_B8G8R8A8_SRGB: case vk::Format::eB8G8R8A8Srgb:
next.float32[0] = DecodeSrgbClearComponent(packed >> 16u); next.float32[0] = DecodeSrgbClearComponent(packed >> 16u);
next.float32[1] = DecodeSrgbClearComponent(packed >> 8u); next.float32[1] = DecodeSrgbClearComponent(packed >> 8u);
next.float32[2] = DecodeSrgbClearComponent(packed); next.float32[2] = DecodeSrgbClearComponent(packed);
next.float32[3] = unorm8(packed >> 24u); next.float32[3] = unorm8(packed >> 24u);
break; break;
case VK_FORMAT_R8G8B8A8_UNORM: case vk::Format::eR8G8B8A8Unorm:
next.float32[0] = unorm8(packed); next.float32[0] = unorm8(packed);
next.float32[1] = unorm8(packed >> 8u); next.float32[1] = unorm8(packed >> 8u);
next.float32[2] = unorm8(packed >> 16u); next.float32[2] = unorm8(packed >> 16u);
next.float32[3] = unorm8(packed >> 24u); next.float32[3] = unorm8(packed >> 24u);
break; break;
case VK_FORMAT_B8G8R8A8_UNORM: case vk::Format::eB8G8R8A8Unorm:
next.float32[0] = unorm8(packed >> 16u); next.float32[0] = unorm8(packed >> 16u);
next.float32[1] = unorm8(packed >> 8u); next.float32[1] = unorm8(packed >> 8u);
next.float32[2] = unorm8(packed); next.float32[2] = unorm8(packed);
next.float32[3] = unorm8(packed >> 24u); next.float32[3] = unorm8(packed >> 24u);
break; break;
case VK_FORMAT_A2B10G10R10_UNORM_PACK32: case vk::Format::eA2B10G10R10UnormPack32:
next.float32[0] = static_cast<float>(packed & 0x3ffu) / 1023.0f; next.float32[0] = static_cast<float>(packed & 0x3ffu) / 1023.0f;
next.float32[1] = static_cast<float>((packed >> 10u) & 0x3ffu) / 1023.0f; next.float32[1] = static_cast<float>((packed >> 10u) & 0x3ffu) / 1023.0f;
next.float32[2] = static_cast<float>((packed >> 20u) & 0x3ffu) / 1023.0f; next.float32[2] = static_cast<float>((packed >> 20u) & 0x3ffu) / 1023.0f;
next.float32[3] = static_cast<float>((packed >> 30u) & 0x3u) / 3.0f; next.float32[3] = static_cast<float>((packed >> 30u) & 0x3u) / 3.0f;
break; break;
case VK_FORMAT_A2R10G10B10_UNORM_PACK32: case vk::Format::eA2R10G10B10UnormPack32:
next.float32[0] = static_cast<float>((packed >> 20u) & 0x3ffu) / 1023.0f; next.float32[0] = static_cast<float>((packed >> 20u) & 0x3ffu) / 1023.0f;
next.float32[1] = static_cast<float>((packed >> 10u) & 0x3ffu) / 1023.0f; next.float32[1] = static_cast<float>((packed >> 10u) & 0x3ffu) / 1023.0f;
next.float32[2] = static_cast<float>(packed & 0x3ffu) / 1023.0f; next.float32[2] = static_cast<float>(packed & 0x3ffu) / 1023.0f;
@@ -541,9 +541,9 @@ SelectDepthTransitionSource(bool depth_load_clear, bool sampled_native_available
return true; return true;
} }
[[nodiscard]] inline bool DecodePackedDepthClear(VkFormat format, uint32_t packed, float* clear) { [[nodiscard]] inline bool DecodePackedDepthClear(vk::Format format, uint32_t packed, float* clear) {
if (clear == nullptr || if (clear == nullptr ||
(format != VK_FORMAT_D32_SFLOAT && format != VK_FORMAT_D32_SFLOAT_S8_UINT)) { (format != vk::Format::eD32Sfloat && format != vk::Format::eD32SfloatS8Uint)) {
return false; return false;
} }
const auto value = std::bit_cast<float>(packed); const auto value = std::bit_cast<float>(packed);
@@ -557,7 +557,7 @@ SelectDepthTransitionSource(bool depth_load_clear, bool sampled_native_available
[[nodiscard]] inline bool CanNativeClearDepthFromBuffer(const DepthTargetInfo& target, [[nodiscard]] inline bool CanNativeClearDepthFromBuffer(const DepthTargetInfo& target,
uint64_t address, uint64_t size) { uint64_t address, uint64_t size) {
const bool d32 = const bool d32 =
target.format == VK_FORMAT_D32_SFLOAT || target.format == VK_FORMAT_D32_SFLOAT_S8_UINT; target.format == vk::Format::eD32Sfloat || target.format == vk::Format::eD32SfloatS8Uint;
return address == target.address && size == target.size && target.layers == 1 && d32 && return address == target.address && size == target.size && target.layers == 1 && d32 &&
target.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) && target.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
target.bytes_per_element == 4 && target.bytes_per_element == 4 &&
@@ -621,31 +621,32 @@ SelectDepthTransitionSource(bool depth_load_clear, bool sampled_native_available
: SampledOverlap::Unsupported; : SampledOverlap::Unsupported;
} }
[[nodiscard]] inline bool IsRgba8SrgbReinterpretation(VkFormat cached, VkFormat requested) noexcept; [[nodiscard]] inline bool IsRgba8SrgbReinterpretation(vk::Format cached,
vk::Format requested) noexcept;
[[nodiscard]] inline bool IsR32UintFloatReinterpretation(VkFormat cached, [[nodiscard]] inline bool IsR32UintFloatReinterpretation(vk::Format cached,
VkFormat requested) noexcept { vk::Format requested) noexcept {
switch (cached) { switch (cached) {
case VK_FORMAT_R32_UINT: return requested == VK_FORMAT_R32_SFLOAT; case vk::Format::eR32Uint: return requested == vk::Format::eR32Sfloat;
case VK_FORMAT_R32_SFLOAT: return requested == VK_FORMAT_R32_UINT; case vk::Format::eR32Sfloat: return requested == vk::Format::eR32Uint;
default: return false; default: return false;
} }
} }
[[nodiscard]] inline bool IsRgba16UintFloatReinterpretation(VkFormat cached, [[nodiscard]] inline bool IsRgba16UintFloatReinterpretation(vk::Format cached,
VkFormat requested) noexcept { vk::Format requested) noexcept {
switch (cached) { switch (cached) {
case VK_FORMAT_R16G16B16A16_SFLOAT: return requested == VK_FORMAT_R16G16B16A16_UINT; case vk::Format::eR16G16B16A16Sfloat: return requested == vk::Format::eR16G16B16A16Uint;
case VK_FORMAT_R16G16B16A16_UINT: return requested == VK_FORMAT_R16G16B16A16_SFLOAT; case vk::Format::eR16G16B16A16Uint: return requested == vk::Format::eR16G16B16A16Sfloat;
default: return false; default: return false;
} }
} }
[[nodiscard]] inline bool IsRgba8UnormUintReinterpretation(VkFormat cached, [[nodiscard]] inline bool IsRgba8UnormUintReinterpretation(vk::Format cached,
VkFormat requested) noexcept { vk::Format requested) noexcept {
switch (cached) { switch (cached) {
case VK_FORMAT_R8G8B8A8_UNORM: return requested == VK_FORMAT_R8G8B8A8_UINT; case vk::Format::eR8G8B8A8Unorm: return requested == vk::Format::eR8G8B8A8Uint;
case VK_FORMAT_R8G8B8A8_UINT: return requested == VK_FORMAT_R8G8B8A8_UNORM; case vk::Format::eR8G8B8A8Uint: return requested == vk::Format::eR8G8B8A8Unorm;
default: return false; default: return false;
} }
} }
@@ -658,7 +659,7 @@ SelectDepthTransitionSource(bool depth_load_clear, bool sampled_native_available
sampled.size == target.size * sampled.depth && sampled.width == target.width && sampled.size == target.size * sampled.depth && sampled.width == target.width &&
sampled.height == target.height && sampled.pitch == target.pitch; sampled.height == target.height && sampled.pitch == target.pitch;
return sampled.address == target.address && sampled.size > target.size && return sampled.address == target.address && sampled.size > target.size &&
sampled.format == target.guest_format && target.format == VK_FORMAT_D32_SFLOAT && sampled.format == target.guest_format && target.format == vk::Format::eD32Sfloat &&
target.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) && target.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
target.bytes_per_element == 4 && target.stencil_address == 0 && target.bytes_per_element == 4 && target.stencil_address == 0 &&
target.stencil_size == 0 && target.htile_address == 0 && target.htile_size == 0 && target.stencil_size == 0 && target.htile_address == 0 && target.htile_size == 0 &&
@@ -669,7 +670,7 @@ SelectDepthTransitionSource(bool depth_load_clear, bool sampled_native_available
[[nodiscard]] inline StorageSampledOverlap [[nodiscard]] inline StorageSampledOverlap
ClassifyStorageSampledOverlap(const ImageInfo& requested, const ImageInfo& cached, ClassifyStorageSampledOverlap(const ImageInfo& requested, const ImageInfo& cached,
VkFormat requested_view_format, VkFormat cached_image_format, vk::Format requested_view_format, vk::Format cached_image_format,
bool cached_gpu_modified, bool cached_cpu_dirty, bool same_context) { bool cached_gpu_modified, bool cached_cpu_dirty, bool same_context) {
if (!ImagePageRangesOverlap(requested.address, requested.size, cached.address, cached.size)) { if (!ImagePageRangesOverlap(requested.address, requested.size, cached.address, cached.size)) {
return StorageSampledOverlap::None; return StorageSampledOverlap::None;
@@ -854,7 +855,7 @@ ClassifyRenderTargetOverlap(const ImageInfo& sampled, bool sampled_gpu_modified,
} }
[[nodiscard]] inline RenderTargetOverlap [[nodiscard]] inline RenderTargetOverlap
ClassifyStorageRenderTargetOverlap(const ImageInfo& storage, VkFormat storage_format, ClassifyStorageRenderTargetOverlap(const ImageInfo& storage, vk::Format storage_format,
bool storage_gpu_modified, bool storage_buffer_modified, bool storage_gpu_modified, bool storage_buffer_modified,
bool storage_cpu_dirty, bool same_context, bool storage_cpu_dirty, bool same_context,
const RenderTargetInfo& target) { const RenderTargetInfo& target) {
@@ -875,18 +876,18 @@ ClassifyStorageRenderTargetOverlap(const ImageInfo& storage, VkFormat storage_fo
: RenderTargetOverlap::Unsupported; : RenderTargetOverlap::Unsupported;
} }
[[nodiscard]] inline bool IsRgba8SrgbViewFormat(VkFormat format) noexcept { [[nodiscard]] inline bool IsRgba8SrgbViewFormat(vk::Format format) noexcept {
return format == VK_FORMAT_R8G8B8A8_UNORM || format == VK_FORMAT_R8G8B8A8_SRGB || return format == vk::Format::eR8G8B8A8Unorm || format == vk::Format::eR8G8B8A8Srgb ||
format == VK_FORMAT_B8G8R8A8_UNORM || format == VK_FORMAT_B8G8R8A8_SRGB; format == vk::Format::eB8G8R8A8Unorm || format == vk::Format::eB8G8R8A8Srgb;
} }
[[nodiscard]] inline bool IsRgba8SrgbReinterpretation(VkFormat cached, [[nodiscard]] inline bool IsRgba8SrgbReinterpretation(vk::Format cached,
VkFormat requested) noexcept { vk::Format requested) noexcept {
switch (cached) { switch (cached) {
case VK_FORMAT_R8G8B8A8_UNORM: return requested == VK_FORMAT_R8G8B8A8_SRGB; case vk::Format::eR8G8B8A8Unorm: return requested == vk::Format::eR8G8B8A8Srgb;
case VK_FORMAT_R8G8B8A8_SRGB: return requested == VK_FORMAT_R8G8B8A8_UNORM; case vk::Format::eR8G8B8A8Srgb: return requested == vk::Format::eR8G8B8A8Unorm;
case VK_FORMAT_B8G8R8A8_UNORM: return requested == VK_FORMAT_B8G8R8A8_SRGB; case vk::Format::eB8G8R8A8Unorm: return requested == vk::Format::eB8G8R8A8Srgb;
case VK_FORMAT_B8G8R8A8_SRGB: return requested == VK_FORMAT_B8G8R8A8_UNORM; case vk::Format::eB8G8R8A8Srgb: return requested == vk::Format::eB8G8R8A8Unorm;
default: return false; default: return false;
} }
} }
+141 -128
View File
@@ -12,13 +12,13 @@ namespace Libs::Graphics {
namespace { namespace {
void CreateRenderTargetView(GraphicContext* ctx, VulkanImage* image, int index, void CreateRenderTargetView(GraphicContext* ctx, VulkanImage* image, int index,
VkComponentSwizzle r, VkComponentSwizzle g, VkComponentSwizzle b, vk::ComponentSwizzle r, vk::ComponentSwizzle g, vk::ComponentSwizzle b,
VkComponentSwizzle a, VkImageViewType type = VK_IMAGE_VIEW_TYPE_2D, vk::ComponentSwizzle a, vk::ImageViewType type = vk::ImageViewType::e2D,
VkFormat view_format = VK_FORMAT_UNDEFINED, vk::Format view_format = vk::Format::eUndefined,
VkImageUsageFlags view_usage = 0, uint32_t level_count = 0) { vk::ImageUsageFlags view_usage = {}, uint32_t level_count = 0) {
const auto layer_count = type == VK_IMAGE_VIEW_TYPE_2D_ARRAY ? image->layers : 1u; const auto layer_count = type == vk::ImageViewType::e2DArray ? image->layers : 1u;
UtilCreateImageView(ctx, image, index, type, VK_IMAGE_ASPECT_COLOR_BIT, {r, g, b, a}, 0, 0, UtilCreateImageView(ctx, image, index, type, vk::ImageAspectFlagBits::eColor, {r, g, b, a}, 0,
layer_count, level_count == 0 ? image->mip_levels : level_count, 0, layer_count, level_count == 0 ? image->mip_levels : level_count,
view_format, view_usage); view_format, view_usage);
} }
@@ -26,61 +26,67 @@ void CreateRenderTargetView(GraphicContext* ctx, VulkanImage* image, int index,
namespace ImageViewOps { namespace ImageViewOps {
VkImageAspectFlags DepthAspectMask(VkFormat format) noexcept { vk::ImageAspectFlags DepthAspectMask(vk::Format format) noexcept {
return VK_IMAGE_ASPECT_DEPTH_BIT | auto aspects = vk::ImageAspectFlags {vk::ImageAspectFlagBits::eDepth};
(format == VK_FORMAT_D16_UNORM_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT || if (format == vk::Format::eD16UnormS8Uint || format == vk::Format::eD24UnormS8Uint ||
format == VK_FORMAT_D32_SFLOAT_S8_UINT format == vk::Format::eD32SfloatS8Uint) {
? VK_IMAGE_ASPECT_STENCIL_BIT aspects |= vk::ImageAspectFlagBits::eStencil;
: 0u); }
return aspects;
} }
bool FormatSupportsStorage(GraphicContext* ctx, VkFormat format) { bool FormatSupportsStorage(GraphicContext* ctx, vk::Format format) {
const auto properties = ctx->GetFormatProperties(format); const auto properties = ctx->GetFormatProperties(format);
return (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0; return static_cast<bool>(properties.optimalTilingFeatures &
vk::FormatFeatureFlagBits::eStorageImage);
} }
void CreateRenderTargetViews(GraphicContext* ctx, RenderTextureVulkanImage* image) { void CreateRenderTargetViews(GraphicContext* ctx, RenderTextureVulkanImage* image) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT, VK_COMPONENT_SWIZZLE_IDENTITY, CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT, vk::ComponentSwizzle::eIdentity,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
VK_COMPONENT_SWIZZLE_IDENTITY); vk::ComponentSwizzle::eIdentity);
if (image->layers > 1) { if (image->layers > 1) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT_ARRAY, CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT_ARRAY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
VK_IMAGE_VIEW_TYPE_2D_ARRAY); vk::ImageViewType::e2DArray);
} }
if (FormatSupportsStorage(ctx, image->format)) { if (FormatSupportsStorage(ctx, image->format)) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE, VK_COMPONENT_SWIZZLE_IDENTITY, CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_IMAGE_VIEW_TYPE_2D, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
VK_FORMAT_UNDEFINED, 0, 1); vk::ImageViewType::e2D, vk::Format::eUndefined,
vk::ImageUsageFlags {}, 1);
if (image->layers > 1) { if (image->layers > 1) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE_ARRAY, CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE_ARRAY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_UNDEFINED, 0, 1); vk::ImageViewType::e2DArray, vk::Format::eUndefined,
vk::ImageUsageFlags {}, 1);
} }
} }
} }
void CreateDepthViews(GraphicContext* ctx, DepthStencilVulkanImage* image) { void CreateDepthViews(GraphicContext* ctx, DepthStencilVulkanImage* image) {
UtilCreateImageView(ctx, image, VulkanImage::VIEW_DEFAULT, VK_IMAGE_VIEW_TYPE_2D, UtilCreateImageView(ctx, image, VulkanImage::VIEW_DEFAULT, vk::ImageViewType::e2D,
DepthAspectMask(image->format), DepthAspectMask(image->format),
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, {vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity},
0, 0, 1, 1); 0, 0, 1, 1);
} }
void CreateVideoOutViews(GraphicContext* ctx, VideoOutVulkanImage* image) { void CreateVideoOutViews(GraphicContext* ctx, VideoOutVulkanImage* image) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT, VK_COMPONENT_SWIZZLE_IDENTITY, CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT, vk::ComponentSwizzle::eIdentity,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
VK_COMPONENT_SWIZZLE_IDENTITY); vk::ComponentSwizzle::eIdentity);
if ((image->format == VK_FORMAT_R8G8B8A8_SRGB || image->format == VK_FORMAT_B8G8R8A8_SRGB) && if ((image->format == vk::Format::eR8G8B8A8Srgb ||
FormatSupportsStorage(ctx, VK_FORMAT_R8G8B8A8_UINT)) { image->format == vk::Format::eB8G8R8A8Srgb) &&
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE, VK_COMPONENT_SWIZZLE_IDENTITY, FormatSupportsStorage(ctx, vk::Format::eR8G8B8A8Uint)) {
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_IMAGE_VIEW_TYPE_2D, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
VK_FORMAT_R8G8B8A8_UINT, VK_IMAGE_USAGE_STORAGE_BIT, 1); vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
vk::ImageViewType::e2D, vk::Format::eR8G8B8A8Uint,
vk::ImageUsageFlagBits::eStorage, 1);
} }
} }
@@ -90,14 +96,14 @@ void DestroyViews(GraphicContext* ctx, VulkanImage* image) {
for (auto& cached: image->view_cache.views) { for (auto& cached: image->view_cache.views) {
if (cached.view != nullptr) { if (cached.view != nullptr) {
vkDestroyImageView(ctx->device, cached.view, nullptr); ctx->device.destroyImageView(cached.view, nullptr);
cached.view = nullptr; cached.view = nullptr;
} }
} }
image->view_cache.views.clear(); image->view_cache.views.clear();
for (auto& view: image->image_view) { for (auto& view: image->image_view) {
if (view != nullptr) { if (view != nullptr) {
vkDestroyImageView(ctx->device, view, nullptr); ctx->device.destroyImageView(view, nullptr);
view = nullptr; view = nullptr;
} }
} }
@@ -105,12 +111,13 @@ void DestroyViews(GraphicContext* ctx, VulkanImage* image) {
} // namespace ImageViewOps } // namespace ImageViewOps
VkImageView TextureCache::GetRenderTargetAttachmentView(GraphicContext* ctx, vk::ImageView TextureCache::GetRenderTargetAttachmentView(GraphicContext* ctx,
RenderTextureVulkanImage* image, RenderTextureVulkanImage* image,
VkFormat format, uint32_t level, vk::Format format, uint32_t level,
uint32_t base_layer, uint32_t layer_count) { uint32_t base_layer,
uint32_t layer_count) {
if (ctx == nullptr || image == nullptr || image->image == nullptr || if (ctx == nullptr || image == nullptr || image->image == nullptr ||
format == VK_FORMAT_UNDEFINED || level >= image->mip_levels || level >= 16 || format == vk::Format::eUndefined || level >= image->mip_levels || level >= 16 ||
layer_count == 0 || base_layer >= image->layers || layer_count == 0 || base_layer >= image->layers ||
layer_count > image->layers - base_layer) { layer_count > image->layers - base_layer) {
EXIT("TextureCache: invalid render-target attachment view, image=%p format=%d" EXIT("TextureCache: invalid render-target attachment view, image=%p format=%d"
@@ -127,14 +134,15 @@ VkImageView TextureCache::GetRenderTargetAttachmentView(GraphicContext*
return GetImageView(ctx, image, return GetImageView(ctx, image,
{format, {format,
layer_count == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY, layer_count == 1 ? vk::ImageViewType::e2D : vk::ImageViewType::e2DArray,
VK_IMAGE_ASPECT_COLOR_BIT, level, 1, base_layer, layer_count, vk::ImageAspectFlagBits::eColor, level, 1, base_layer, layer_count,
DstSel(4, 5, 6, 7), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT}); DstSel(4, 5, 6, 7), vk::ImageUsageFlagBits::eColorAttachment});
} }
VkImageView TextureCache::GetDepthTargetAttachmentView(GraphicContext* ctx, vk::ImageView TextureCache::GetDepthTargetAttachmentView(GraphicContext* ctx,
DepthStencilVulkanImage* image, DepthStencilVulkanImage* image,
uint32_t base_layer, uint32_t layer_count) { uint32_t base_layer,
uint32_t layer_count) {
if (ctx == nullptr || image == nullptr || image->image == nullptr || layer_count == 0 || if (ctx == nullptr || image == nullptr || image->image == nullptr || layer_count == 0 ||
base_layer >= image->layers || layer_count > image->layers - base_layer) { base_layer >= image->layers || layer_count > image->layers - base_layer) {
EXIT("TextureCache: invalid depth-target attachment view, image=%p base_layer=%u " EXIT("TextureCache: invalid depth-target attachment view, image=%p base_layer=%u "
@@ -144,26 +152,26 @@ VkImageView TextureCache::GetDepthTargetAttachmentView(GraphicContext*
} }
return GetImageView( return GetImageView(
ctx, image, ctx, image,
{image->format, layer_count == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY, {image->format, layer_count == 1 ? vk::ImageViewType::e2D : vk::ImageViewType::e2DArray,
ImageViewOps::DepthAspectMask(image->format), 0, 1, base_layer, layer_count, ImageViewOps::DepthAspectMask(image->format), 0, 1, base_layer, layer_count,
DstSel(4, 5, 6, 7), VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT}); DstSel(4, 5, 6, 7), vk::ImageUsageFlagBits::eDepthStencilAttachment});
} }
VkImageView TextureCache::GetImageView(GraphicContext* ctx, VulkanImage* image, vk::ImageView TextureCache::GetImageView(GraphicContext* ctx, VulkanImage* image,
const ImageViewInfo& info) { const ImageViewInfo& info) {
const bool supported_type = info.type == VK_IMAGE_VIEW_TYPE_2D || const bool supported_type = info.type == vk::ImageViewType::e2D ||
info.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY || info.type == vk::ImageViewType::e2DArray ||
info.type == VK_IMAGE_VIEW_TYPE_3D; info.type == vk::ImageViewType::e3D;
const bool supported_usage = info.usage == VK_IMAGE_USAGE_SAMPLED_BIT || const bool supported_usage = info.usage == vk::ImageUsageFlagBits::eSampled ||
info.usage == VK_IMAGE_USAGE_STORAGE_BIT || info.usage == vk::ImageUsageFlagBits::eStorage ||
info.usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT || info.usage == vk::ImageUsageFlagBits::eColorAttachment ||
info.usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; info.usage == vk::ImageUsageFlagBits::eDepthStencilAttachment;
const bool valid_shape = const bool valid_shape =
(info.type == VK_IMAGE_VIEW_TYPE_2D && info.layer_count == 1) || (info.type == vk::ImageViewType::e2D && info.layer_count == 1) ||
info.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY || info.type == vk::ImageViewType::e2DArray ||
(info.type == VK_IMAGE_VIEW_TYPE_3D && info.base_layer == 0 && info.layer_count == 1); (info.type == vk::ImageViewType::e3D && info.base_layer == 0 && info.layer_count == 1);
if (ctx == nullptr || image == nullptr || image->image == nullptr || if (ctx == nullptr || image == nullptr || image->image == nullptr ||
info.format == VK_FORMAT_UNDEFINED || info.aspect == 0 || info.level_count == 0 || info.format == vk::Format::eUndefined || !info.aspect || info.level_count == 0 ||
info.base_level >= (image != nullptr ? image->mip_levels : 0) || info.base_level >= (image != nullptr ? image->mip_levels : 0) ||
info.level_count > image->mip_levels - info.base_level || info.layer_count == 0 || info.level_count > image->mip_levels - info.base_level || info.layer_count == 0 ||
info.base_layer >= image->layers || info.layer_count > image->layers - info.base_layer || info.base_layer >= image->layers || info.layer_count > image->layers - info.base_layer ||
@@ -171,10 +179,11 @@ VkImageView TextureCache::GetImageView(GraphicContext* ctx, VulkanImage* image,
EXIT("TextureCache: invalid dynamic image view, image=%p format=%d aspect=0x%x" EXIT("TextureCache: invalid dynamic image view, image=%p format=%d aspect=0x%x"
" swizzle=0x%03x mip=%u+%u layer=%u+%u type=%d usage=0x%x" " swizzle=0x%03x mip=%u+%u layer=%u+%u type=%d usage=0x%x"
" image_levels=%u image_layers=%u\n", " image_levels=%u image_layers=%u\n",
static_cast<const void*>(image), static_cast<int>(info.format), info.aspect, static_cast<const void*>(image), static_cast<int>(info.format),
info.swizzle, info.base_level, info.level_count, info.base_layer, info.layer_count, static_cast<vk::ImageAspectFlags::MaskType>(info.aspect), info.swizzle,
static_cast<int>(info.type), info.usage, image != nullptr ? image->mip_levels : 0, info.base_level, info.level_count, info.base_layer, info.layer_count,
image != nullptr ? image->layers : 0); static_cast<int>(info.type), static_cast<vk::ImageUsageFlags::MaskType>(info.usage),
image != nullptr ? image->mip_levels : 0, image != nullptr ? image->layers : 0);
} }
auto& cache = image->view_cache; auto& cache = image->view_cache;
@@ -185,67 +194,69 @@ VkImageView TextureCache::GetImageView(GraphicContext* ctx, VulkanImage* image,
} }
} }
VkImageViewUsageCreateInfo usage {}; vk::ImageViewUsageCreateInfo usage {};
usage.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO; usage.sType = vk::StructureType::eImageViewUsageCreateInfo;
usage.usage = info.usage; usage.usage = info.usage;
VkImageViewCreateInfo create {}; vk::ImageViewCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; create.sType = vk::StructureType::eImageViewCreateInfo;
create.pNext = &usage; create.pNext = &usage;
create.image = image->image; create.image = image->image;
create.viewType = info.type; create.viewType = info.type;
create.format = info.format; create.format = info.format;
create.components = info.usage == VK_IMAGE_USAGE_SAMPLED_BIT create.components = info.usage == vk::ImageUsageFlagBits::eSampled
? TextureGetComponentMapping(info.swizzle) ? TextureGetComponentMapping(info.swizzle)
: VkComponentMapping {}; : vk::ComponentMapping {};
create.subresourceRange.aspectMask = info.aspect; create.subresourceRange.aspectMask = info.aspect;
create.subresourceRange.baseMipLevel = info.base_level; create.subresourceRange.baseMipLevel = info.base_level;
create.subresourceRange.levelCount = info.level_count; create.subresourceRange.levelCount = info.level_count;
create.subresourceRange.baseArrayLayer = info.base_layer; create.subresourceRange.baseArrayLayer = info.base_layer;
create.subresourceRange.layerCount = info.layer_count; create.subresourceRange.layerCount = info.layer_count;
VkImageView view = nullptr; vk::ImageView view = nullptr;
const auto result = vkCreateImageView(ctx->device, &create, nullptr, &view); const auto result = ctx->device.createImageView(&create, nullptr, &view);
if (result != VK_SUCCESS || view == nullptr) { if (result != vk::Result::eSuccess || view == nullptr) {
EXIT("TextureCache: failed to create dynamic image view, result=%d format=%d" EXIT("TextureCache: failed to create dynamic image view, result=%d format=%d"
" aspect=0x%x swizzle=0x%03x mip=%u+%u layer=%u+%u type=%d usage=0x%x\n", " aspect=0x%x swizzle=0x%03x mip=%u+%u layer=%u+%u type=%d usage=0x%x\n",
static_cast<int>(result), static_cast<int>(info.format), info.aspect, info.swizzle, static_cast<int>(result), static_cast<int>(info.format),
static_cast<vk::ImageAspectFlags::MaskType>(info.aspect), info.swizzle,
info.base_level, info.level_count, info.base_layer, info.layer_count, info.base_level, info.level_count, info.base_layer, info.layer_count,
static_cast<int>(info.type), info.usage); static_cast<int>(info.type), static_cast<vk::ImageUsageFlags::MaskType>(info.usage));
} }
cache.views.push_back({info, view}); cache.views.push_back({info, view});
return view; return view;
} }
VkImageView TextureCache::GetDepthTargetSampledView(GraphicContext* ctx, vk::ImageView TextureCache::GetDepthTargetSampledView(GraphicContext* ctx,
DepthStencilVulkanImage* image, DepthStencilVulkanImage* image,
VkFormat view_format, uint32_t swizzle, vk::Format view_format, uint32_t swizzle,
uint32_t base_level, uint32_t level_count, uint32_t base_level, uint32_t level_count,
VkImageViewType type, uint32_t base_layer, vk::ImageViewType type, uint32_t base_layer,
uint32_t layer_count) { uint32_t layer_count) {
if (ctx == nullptr || image == nullptr || image->image == nullptr || if (ctx == nullptr || image == nullptr || image->image == nullptr ||
view_format == VK_FORMAT_UNDEFINED || view_format == vk::Format::eUndefined ||
!IsSupportedSampledDepthView(image->format, view_format, swizzle)) { !IsSupportedSampledDepthView(image->format, view_format, swizzle)) {
EXIT("TextureCache: invalid sampled depth-target view, image=%p image_format=%d" EXIT("TextureCache: invalid sampled depth-target view, image=%p image_format=%d"
" view_format=%d swizzle=0x%03x mip=%u+%u layer=%u+%u type=%d" " view_format=%d swizzle=0x%03x mip=%u+%u layer=%u+%u type=%d"
" image_levels=%u image_layers=%u\n", " image_levels=%u image_layers=%u\n",
static_cast<const void*>(image), static_cast<const void*>(image),
image != nullptr ? static_cast<int>(image->format) : VK_FORMAT_UNDEFINED, image != nullptr ? static_cast<int>(image->format)
: static_cast<int>(vk::Format::eUndefined),
static_cast<int>(view_format), swizzle, base_level, level_count, base_layer, static_cast<int>(view_format), swizzle, base_level, level_count, base_layer,
layer_count, static_cast<int>(type), image != nullptr ? image->mip_levels : 0, layer_count, static_cast<int>(type), image != nullptr ? image->mip_levels : 0,
image != nullptr ? image->layers : 0); image != nullptr ? image->layers : 0);
} }
return GetImageView(ctx, image, return GetImageView(ctx, image,
{image->format, type, VK_IMAGE_ASPECT_DEPTH_BIT, base_level, level_count, {image->format, type, vk::ImageAspectFlagBits::eDepth, base_level,
base_layer, layer_count, swizzle}); level_count, base_layer, layer_count, swizzle});
} }
VkImageView TextureCache::GetSampledColorView(GraphicContext* ctx, VulkanImage* image, vk::ImageView TextureCache::GetSampledColorView(GraphicContext* ctx, VulkanImage* image,
VkFormat view_format, uint32_t swizzle, vk::Format view_format, uint32_t swizzle,
uint32_t base_level, uint32_t level_count, uint32_t base_level, uint32_t level_count,
VkImageViewType type, uint32_t base_layer, vk::ImageViewType type, uint32_t base_layer,
uint32_t layer_count) { uint32_t layer_count) {
if (ctx == nullptr || image == nullptr || image->image == nullptr || if (ctx == nullptr || image == nullptr || image->image == nullptr ||
view_format == VK_FORMAT_UNDEFINED || base_level >= 16 || view_format == vk::Format::eUndefined || base_level >= 16 ||
(type != VK_IMAGE_VIEW_TYPE_2D && type != VK_IMAGE_VIEW_TYPE_2D_ARRAY) || (type != vk::ImageViewType::e2D && type != vk::ImageViewType::e2DArray) ||
!IsSupportedSampledColorView(image->format, view_format, swizzle)) { !IsSupportedSampledColorView(image->format, view_format, swizzle)) {
EXIT("TextureCache: invalid sampled color view, image=%p swizzle=0x%03x" EXIT("TextureCache: invalid sampled color view, image=%p swizzle=0x%03x"
" view_format=%d mip=%u+%u layer=%u+%u type=%d image_levels=%u image_layers=%u\n", " view_format=%d mip=%u+%u layer=%u+%u type=%d image_levels=%u image_layers=%u\n",
@@ -253,29 +264,29 @@ VkImageView TextureCache::GetSampledColorView(GraphicContext* ctx, VulkanImage*
level_count, base_layer, layer_count, static_cast<int>(type), level_count, base_layer, layer_count, static_cast<int>(type),
image != nullptr ? image->mip_levels : 0, image != nullptr ? image->layers : 0); image != nullptr ? image->mip_levels : 0, image != nullptr ? image->layers : 0);
} }
const auto precreated_view = type == VK_IMAGE_VIEW_TYPE_2D_ARRAY const auto precreated_view = type == vk::ImageViewType::e2DArray
? VulkanImage::VIEW_DEFAULT_ARRAY ? VulkanImage::VIEW_DEFAULT_ARRAY
: VulkanImage::VIEW_DEFAULT; : VulkanImage::VIEW_DEFAULT;
const bool full_view = const bool full_view =
base_level == 0 && level_count == image->mip_levels && base_layer == 0 && base_level == 0 && level_count == image->mip_levels && base_layer == 0 &&
layer_count == (type == VK_IMAGE_VIEW_TYPE_2D_ARRAY ? image->layers : 1u); layer_count == (type == vk::ImageViewType::e2DArray ? image->layers : 1u);
if (view_format == image->format && swizzle == DstSel(4, 5, 6, 7) && full_view && if (view_format == image->format && swizzle == DstSel(4, 5, 6, 7) && full_view &&
image->image_view[precreated_view] != nullptr) { image->image_view[precreated_view] != nullptr) {
return image->image_view[precreated_view]; return image->image_view[precreated_view];
} }
return GetImageView(ctx, image, return GetImageView(ctx, image,
{view_format, type, VK_IMAGE_ASPECT_COLOR_BIT, base_level, level_count, {view_format, type, vk::ImageAspectFlagBits::eColor, base_level,
base_layer, layer_count, swizzle}); level_count, base_layer, layer_count, swizzle});
} }
VkImageView TextureCache::GetRenderTargetStorageView(GraphicContext* ctx, vk::ImageView TextureCache::GetRenderTargetStorageView(GraphicContext* ctx,
RenderTextureVulkanImage* image, RenderTextureVulkanImage* image,
VkFormat view_format, uint32_t base_level, vk::Format view_format, uint32_t base_level,
uint32_t level_count, VkImageViewType type, uint32_t level_count, vk::ImageViewType type,
uint32_t base_layer, uint32_t layer_count) { uint32_t base_layer, uint32_t layer_count) {
if (ctx == nullptr || image == nullptr || image->image == nullptr || if (ctx == nullptr || image == nullptr || image->image == nullptr ||
view_format == VK_FORMAT_UNDEFINED || view_format == vk::Format::eUndefined ||
(type != VK_IMAGE_VIEW_TYPE_2D && type != VK_IMAGE_VIEW_TYPE_2D_ARRAY)) { (type != vk::ImageViewType::e2D && type != vk::ImageViewType::e2DArray)) {
EXIT("TextureCache: invalid render-target storage view, image=%p view_format=%d" EXIT("TextureCache: invalid render-target storage view, image=%p view_format=%d"
" mip=%u+%u layer=%u+%u type=%d image_levels=%u image_layers=%u\n", " mip=%u+%u layer=%u+%u type=%d image_levels=%u image_layers=%u\n",
static_cast<const void*>(image), static_cast<int>(view_format), base_level, static_cast<const void*>(image), static_cast<int>(view_format), base_level,
@@ -291,11 +302,11 @@ VkImageView TextureCache::GetRenderTargetStorageView(GraphicContext* c
level_count); level_count);
} }
if (exact) { if (exact) {
const auto index = type == VK_IMAGE_VIEW_TYPE_2D_ARRAY ? VulkanImage::VIEW_STORAGE_ARRAY const auto index = type == vk::ImageViewType::e2DArray ? VulkanImage::VIEW_STORAGE_ARRAY
: VulkanImage::VIEW_STORAGE; : VulkanImage::VIEW_STORAGE;
const bool full_view = const bool full_view =
base_level == 0 && level_count == 1 && base_layer == 0 && base_level == 0 && level_count == 1 && base_layer == 0 &&
layer_count == (type == VK_IMAGE_VIEW_TYPE_2D_ARRAY ? image->layers : 1u); layer_count == (type == vk::ImageViewType::e2DArray ? image->layers : 1u);
if (full_view && image->image_view[index] != nullptr) { if (full_view && image->image_view[index] != nullptr) {
return image->image_view[index]; return image->image_view[index];
} }
@@ -308,13 +319,14 @@ VkImageView TextureCache::GetRenderTargetStorageView(GraphicContext* c
level_count); level_count);
} }
return GetImageView(ctx, image, return GetImageView(ctx, image,
{view_format, type, VK_IMAGE_ASPECT_COLOR_BIT, base_level, level_count, {view_format, type, vk::ImageAspectFlagBits::eColor, base_level,
base_layer, layer_count, DstSel(4, 5, 6, 7), VK_IMAGE_USAGE_STORAGE_BIT}); level_count, base_layer, layer_count, DstSel(4, 5, 6, 7),
vk::ImageUsageFlagBits::eStorage});
} }
VkImageView TextureCache::GetStorageTextureSampledView(GraphicContext* ctx, vk::ImageView TextureCache::GetStorageTextureSampledView(GraphicContext* ctx,
StorageTextureVulkanImage* image, StorageTextureVulkanImage* image,
const ImageInfo& info) { const ImageInfo& info) {
const auto shape = const auto shape =
SelectStorageSampledViewShape(info.type, info.depth, image != nullptr ? image->layers : 0); SelectStorageSampledViewShape(info.type, info.depth, image != nullptr ? image->layers : 0);
if (ctx == nullptr || image == nullptr || image->image == nullptr || if (ctx == nullptr || image == nullptr || image->image == nullptr ||
@@ -334,23 +346,23 @@ VkImageView TextureCache::GetStorageTextureSampledView(GraphicContext*
static_cast<int>(image->format), static_cast<int>(view_format), info.swizzle); static_cast<int>(image->format), static_cast<int>(view_format), info.swizzle);
} }
VkImageViewType type = VK_IMAGE_VIEW_TYPE_MAX_ENUM; vk::ImageViewType type = static_cast<vk::ImageViewType>(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
switch (shape) { switch (shape) {
case StorageSampledViewShape::Image2D: type = VK_IMAGE_VIEW_TYPE_2D; break; case StorageSampledViewShape::Image2D: type = vk::ImageViewType::e2D; break;
case StorageSampledViewShape::Image2DArray: type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; break; case StorageSampledViewShape::Image2DArray: type = vk::ImageViewType::e2DArray; break;
case StorageSampledViewShape::Image3D: type = VK_IMAGE_VIEW_TYPE_3D; break; case StorageSampledViewShape::Image3D: type = vk::ImageViewType::e3D; break;
case StorageSampledViewShape::Unsupported: case StorageSampledViewShape::Unsupported:
EXIT("TextureCache: unsupported sampled storage-image view shape\n"); EXIT("TextureCache: unsupported sampled storage-image view shape\n");
} }
const auto layer_count = shape == StorageSampledViewShape::Image2DArray ? info.depth : 1u; const auto layer_count = shape == StorageSampledViewShape::Image2DArray ? info.depth : 1u;
return GetImageView(ctx, image, return GetImageView(ctx, image,
{view_format, type, VK_IMAGE_ASPECT_COLOR_BIT, info.base_level, {view_format, type, vk::ImageAspectFlagBits::eColor, info.base_level,
info.view_levels, 0, layer_count, info.swizzle}); info.view_levels, 0, layer_count, info.swizzle});
} }
VkImageView TextureCache::GetStorageTextureStorageView(GraphicContext* ctx, vk::ImageView TextureCache::GetStorageTextureStorageView(GraphicContext* ctx,
StorageTextureVulkanImage* image, StorageTextureVulkanImage* image,
uint32_t base_level) { uint32_t base_level) {
if (ctx == nullptr || image == nullptr || image->image == nullptr || if (ctx == nullptr || image == nullptr || image->image == nullptr ||
base_level >= (image != nullptr ? image->mip_levels : 0)) { base_level >= (image != nullptr ? image->mip_levels : 0)) {
EXIT("TextureCache: invalid storage-texture mip view, image=%p level=%u levels=%u\n", EXIT("TextureCache: invalid storage-texture mip view, image=%p level=%u levels=%u\n",
@@ -360,8 +372,9 @@ VkImageView TextureCache::GetStorageTextureStorageView(GraphicContext*
return image->image_view[VulkanImage::VIEW_DEFAULT]; return image->image_view[VulkanImage::VIEW_DEFAULT];
} }
return GetImageView(ctx, image, return GetImageView(ctx, image,
{image->format, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, {image->format, vk::ImageViewType::e2D, vk::ImageAspectFlagBits::eColor,
base_level, 1, 0, 1, DstSel(4, 5, 6, 7), VK_IMAGE_USAGE_STORAGE_BIT}); base_level, 1, 0, 1, DstSel(4, 5, 6, 7),
vk::ImageUsageFlagBits::eStorage});
} }
} // namespace Libs::Graphics } // namespace Libs::Graphics
+41 -38
View File
@@ -40,47 +40,48 @@ namespace Libs::Graphics {
height != 0 && depth == 1); height != 0 && depth == 1);
} }
[[noreturn]] inline void UnsupportedColorView(const char* usage, VkFormat image_format, [[noreturn]] inline void UnsupportedColorView(const char* usage, vk::Format image_format,
VkFormat view_format, uint32_t swizzle) noexcept { vk::Format view_format, uint32_t swizzle) noexcept {
EXIT("unsupported %s color image view: image_format=%d view_format=%d swizzle=0x%03x\n", usage, EXIT("unsupported %s color image view: image_format=%d view_format=%d swizzle=0x%03x\n", usage,
static_cast<int>(image_format), static_cast<int>(view_format), swizzle); static_cast<int>(image_format), static_cast<int>(view_format), swizzle);
} }
[[nodiscard]] inline VkFormat BgraToRgbaSampledViewFormat(VkFormat image_format) noexcept { [[nodiscard]] inline vk::Format BgraToRgbaSampledViewFormat(vk::Format image_format) noexcept {
switch (image_format) { switch (image_format) {
case VK_FORMAT_B8G8R8A8_UNORM: return VK_FORMAT_R8G8B8A8_UNORM; case vk::Format::eB8G8R8A8Unorm: return vk::Format::eR8G8B8A8Unorm;
case VK_FORMAT_B8G8R8A8_SRGB: return VK_FORMAT_R8G8B8A8_SRGB; case vk::Format::eB8G8R8A8Srgb: return vk::Format::eR8G8B8A8Srgb;
case VK_FORMAT_A2R10G10B10_UNORM_PACK32: return VK_FORMAT_A2B10G10R10_UNORM_PACK32; case vk::Format::eA2R10G10B10UnormPack32: return vk::Format::eA2B10G10R10UnormPack32;
default: return VK_FORMAT_UNDEFINED; default: return vk::Format::eUndefined;
} }
} }
[[nodiscard]] inline bool IsBgraToRgbaSampledView(VkFormat image_format, [[nodiscard]] inline bool IsBgraToRgbaSampledView(vk::Format image_format,
VkFormat view_format) noexcept { vk::Format view_format) noexcept {
switch (image_format) { switch (image_format) {
case VK_FORMAT_B8G8R8A8_UNORM: case vk::Format::eB8G8R8A8Unorm:
case VK_FORMAT_B8G8R8A8_SRGB: case vk::Format::eB8G8R8A8Srgb:
switch (view_format) { switch (view_format) {
case VK_FORMAT_R8G8B8A8_UNORM: case vk::Format::eR8G8B8A8Unorm:
case VK_FORMAT_R8G8B8A8_SRGB: return true; case vk::Format::eR8G8B8A8Srgb: return true;
default: return false; default: return false;
} }
case VK_FORMAT_A2R10G10B10_UNORM_PACK32: case vk::Format::eA2R10G10B10UnormPack32:
return view_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32; return view_format == vk::Format::eA2B10G10R10UnormPack32;
default: return false; default: return false;
} }
} }
[[nodiscard]] inline VkFormat BgraSrgbStorageViewFormat(VkFormat image_format) noexcept { [[nodiscard]] inline vk::Format BgraSrgbStorageViewFormat(vk::Format image_format) noexcept {
return image_format == VK_FORMAT_B8G8R8A8_SRGB ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED; return image_format == vk::Format::eB8G8R8A8Srgb ? vk::Format::eR8G8B8A8Unorm
: vk::Format::eUndefined;
} }
[[nodiscard]] inline VkFormat SrgbStorageViewFormat(VkFormat image_format) noexcept { [[nodiscard]] inline vk::Format SrgbStorageViewFormat(vk::Format image_format) noexcept {
return image_format == VK_FORMAT_R8G8B8A8_SRGB ? VK_FORMAT_R8G8B8A8_UNORM return image_format == vk::Format::eR8G8B8A8Srgb ? vk::Format::eR8G8B8A8Unorm
: BgraSrgbStorageViewFormat(image_format); : BgraSrgbStorageViewFormat(image_format);
} }
[[nodiscard]] inline bool IsBgraSrgbStorageView(VkFormat image_format, VkFormat view_format, [[nodiscard]] inline bool IsBgraSrgbStorageView(vk::Format image_format, vk::Format view_format,
uint32_t swizzle) noexcept { uint32_t swizzle) noexcept {
return view_format == BgraSrgbStorageViewFormat(image_format) && swizzle == DstSel(6, 5, 4, 7); return view_format == BgraSrgbStorageViewFormat(image_format) && swizzle == DstSel(6, 5, 4, 7);
} }
@@ -103,8 +104,9 @@ namespace Libs::Graphics {
return true; return true;
} }
[[nodiscard]] inline bool IsSupportedSampledColorView(VkFormat image_format, VkFormat view_format, [[nodiscard]] inline bool IsSupportedSampledColorView(vk::Format image_format,
uint32_t swizzle) noexcept { vk::Format view_format,
uint32_t swizzle) noexcept {
if (!IsValidSampledColorSwizzle(swizzle)) { if (!IsValidSampledColorSwizzle(swizzle)) {
return false; return false;
} }
@@ -119,16 +121,17 @@ namespace Libs::Graphics {
return IsBgraToRgbaSampledView(image_format, view_format) && swizzle == DstSel(6, 5, 4, 7); return IsBgraToRgbaSampledView(image_format, view_format) && swizzle == DstSel(6, 5, 4, 7);
} }
[[nodiscard]] inline uint32_t SelectSampledColorView(VkFormat image_format, VkFormat view_format, [[nodiscard]] inline uint32_t
uint32_t swizzle) noexcept { SelectSampledColorView(vk::Format image_format, vk::Format view_format, uint32_t swizzle) noexcept {
if (IsSupportedSampledColorView(image_format, view_format, swizzle)) { if (IsSupportedSampledColorView(image_format, view_format, swizzle)) {
return swizzle; return swizzle;
} }
UnsupportedColorView("sampled", image_format, view_format, swizzle); UnsupportedColorView("sampled", image_format, view_format, swizzle);
} }
[[nodiscard]] inline bool IsSupportedSampledDepthView(VkFormat image_format, VkFormat view_format, [[nodiscard]] inline bool IsSupportedSampledDepthView(vk::Format image_format,
uint32_t swizzle) noexcept { vk::Format view_format,
uint32_t swizzle) noexcept {
if (!IsSupportedSampledDepthFormat(image_format, view_format)) { if (!IsSupportedSampledDepthFormat(image_format, view_format)) {
return false; return false;
} }
@@ -140,8 +143,8 @@ namespace Libs::Graphics {
} }
} }
[[nodiscard]] inline uint32_t SelectSampledDepthView(VkFormat image_format, VkFormat view_format, [[nodiscard]] inline uint32_t
uint32_t swizzle) noexcept { SelectSampledDepthView(vk::Format image_format, vk::Format view_format, uint32_t swizzle) noexcept {
if (IsSupportedSampledDepthView(image_format, view_format, swizzle)) { if (IsSupportedSampledDepthView(image_format, view_format, swizzle)) {
return swizzle; return swizzle;
} }
@@ -166,20 +169,20 @@ IsSupportedSampledDepthUintResource(const ShaderRecompiler::IR::ImageResource& r
!resource.written && !resource.atomic && !resource.depth_compare; !resource.written && !resource.atomic && !resource.depth_compare;
} }
[[nodiscard]] inline int SelectStorageColorView(VkFormat image_format, VkFormat view_format, [[nodiscard]] inline int SelectStorageColorView(vk::Format image_format, vk::Format view_format,
uint32_t swizzle) noexcept { uint32_t swizzle) noexcept {
const bool single_channel = const bool single_channel =
view_format == VK_FORMAT_R8_UNORM || view_format == VK_FORMAT_R8_UINT || view_format == vk::Format::eR8Unorm || view_format == vk::Format::eR8Uint ||
view_format == VK_FORMAT_R16_UINT || view_format == VK_FORMAT_R32_UINT || view_format == vk::Format::eR16Uint || view_format == vk::Format::eR32Uint ||
view_format == VK_FORMAT_R16_SFLOAT || view_format == VK_FORMAT_R32_SFLOAT; view_format == vk::Format::eR16Sfloat || view_format == vk::Format::eR32Sfloat;
const bool swizzle_ok = const bool swizzle_ok =
swizzle == DstSel(4, 5, 6, 7) || swizzle == DstSel(4, 5, 6, 7) ||
(single_channel && (swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1) || (single_channel && (swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1) ||
swizzle == DstSel(4, 4, 4, 4))) || swizzle == DstSel(4, 4, 4, 4))) ||
(view_format == VK_FORMAT_R32G32_UINT && swizzle == DstSel(4, 5, 0, 1)) || (view_format == vk::Format::eR32G32Uint && swizzle == DstSel(4, 5, 0, 1)) ||
((view_format == VK_FORMAT_R8G8B8A8_UNORM || view_format == VK_FORMAT_R8G8B8A8_UINT) && ((view_format == vk::Format::eR8G8B8A8Unorm || view_format == vk::Format::eR8G8B8A8Uint) &&
(swizzle == DstSel(4, 5, 6, 1) || swizzle == DstSel(6, 5, 4, 7))) || (swizzle == DstSel(4, 5, 6, 1) || swizzle == DstSel(6, 5, 4, 7))) ||
(view_format == VK_FORMAT_R32G32B32A32_SFLOAT && swizzle == DstSel(5, 6, 7, 4)); (view_format == vk::Format::eR32G32B32A32Sfloat && swizzle == DstSel(5, 6, 7, 4));
if ((image_format != view_format && if ((image_format != view_format &&
!IsBgraSrgbStorageView(image_format, view_format, swizzle)) || !IsBgraSrgbStorageView(image_format, view_format, swizzle)) ||
!swizzle_ok) { !swizzle_ok) {
@@ -212,8 +215,8 @@ ValidateStorageImageResource(const ShaderRecompiler::IR::ImageResource& resource
namespace ImageViewOps { namespace ImageViewOps {
[[nodiscard]] VkImageAspectFlags DepthAspectMask(VkFormat format) noexcept; [[nodiscard]] vk::ImageAspectFlags DepthAspectMask(vk::Format format) noexcept;
[[nodiscard]] bool FormatSupportsStorage(GraphicContext* ctx, VkFormat format); [[nodiscard]] bool FormatSupportsStorage(GraphicContext* ctx, vk::Format format);
void CreateRenderTargetViews(GraphicContext* ctx, RenderTextureVulkanImage* image); void CreateRenderTargetViews(GraphicContext* ctx, RenderTextureVulkanImage* image);
void CreateDepthViews(GraphicContext* ctx, DepthStencilVulkanImage* image); void CreateDepthViews(GraphicContext* ctx, DepthStencilVulkanImage* image);
@@ -57,8 +57,8 @@ void PipelineCache::DeletePipelineInternal(Pipeline* p) {
EXIT_IF(gctx == nullptr); EXIT_IF(gctx == nullptr);
VulkanDeviceWaitIdle(gctx); VulkanDeviceWaitIdle(gctx);
vkDestroyPipeline(gctx->device, p->pipeline, nullptr); gctx->device.destroyPipeline(p->pipeline, nullptr);
vkDestroyPipelineLayout(gctx->device, p->pipeline_layout, nullptr); gctx->device.destroyPipelineLayout(p->pipeline_layout, nullptr);
p->pipeline = nullptr; p->pipeline = nullptr;
p->pipeline_layout = nullptr; p->pipeline_layout = nullptr;
@@ -67,7 +67,7 @@ void PipelineCache::DeletePipelineInternal(Pipeline* p) {
PipelineCache::GraphicsPipeline* PipelineCache::CreateGraphicsPipeline( PipelineCache::GraphicsPipeline* PipelineCache::CreateGraphicsPipeline(
VulkanFramebuffer* framebuffer, RenderColorInfo* colors, uint32_t color_count, VulkanFramebuffer* framebuffer, RenderColorInfo* colors, uint32_t color_count,
RenderDepthInfo* depth, ShaderVertexInputInfo* vs_input_info, HW::Context* ctx, RenderDepthInfo* depth, ShaderVertexInputInfo* vs_input_info, HW::Context* ctx,
HW::Shader* sh_ctx, ShaderPixelInputInfo* ps_input_info, VkPrimitiveTopology topology, HW::Shader* sh_ctx, ShaderPixelInputInfo* ps_input_info, vk::PrimitiveTopology topology,
bool ps_active, std::span<const uint32_t> vs_spirv, std::span<const uint32_t> ps_spirv) { bool ps_active, std::span<const uint32_t> vs_spirv, std::span<const uint32_t> ps_spirv) {
KYTY_PROFILER_BLOCK("PipelineCache::CreatePipeline(Gfx)", profiler::colors::DeepOrangeA200); KYTY_PROFILER_BLOCK("PipelineCache::CreatePipeline(Gfx)", profiler::colors::DeepOrangeA200);
@@ -116,7 +116,7 @@ PipelineCache::GraphicsPipeline* PipelineCache::CreateGraphicsPipeline(
static_params.negative_one_to_one = !ctx->GetClipControl().dx_clip_space; static_params.negative_one_to_one = !ctx->GetClipControl().dx_clip_space;
static_params.topology = topology; static_params.topology = topology;
static_params.with_depth = static_params.with_depth =
(depth->format != VK_FORMAT_UNDEFINED && depth->vulkan_buffer != nullptr); (depth->format != vk::Format::eUndefined && depth->vulkan_buffer != nullptr);
static_params.depth_test_enable = depth->depth_test_enable; static_params.depth_test_enable = depth->depth_test_enable;
static_params.depth_write_enable = (depth->depth_write_enable && !depth->depth_clear_enable); static_params.depth_write_enable = (depth->depth_write_enable && !depth->depth_clear_enable);
static_params.depth_compare_op = depth->depth_compare_op; static_params.depth_compare_op = depth->depth_compare_op;
@@ -7,6 +7,7 @@
#include "common/file.h" #include "common/file.h"
#include "common/threads.h" #include "common/threads.h"
#include "graphics/host_gpu/renderer/renderTarget.h" #include "graphics/host_gpu/renderer/renderTarget.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/shader.h" #include "graphics/shader/shader.h"
#include <cstddef> #include <cstddef>
@@ -15,7 +16,6 @@
#include <type_traits> #include <type_traits>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -36,11 +36,11 @@ struct PipelineStaticParameters {
float viewport_offset[3] = {}; float viewport_offset[3] = {};
bool negative_one_to_one = false; bool negative_one_to_one = false;
int scissor_ltrb[4] = {0}; int scissor_ltrb[4] = {0};
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; vk::PrimitiveTopology topology = vk::PrimitiveTopology::ePointList;
bool with_depth = false; bool with_depth = false;
bool depth_test_enable = false; bool depth_test_enable = false;
bool depth_write_enable = false; bool depth_write_enable = false;
VkCompareOp depth_compare_op = VK_COMPARE_OP_NEVER; vk::CompareOp depth_compare_op = vk::CompareOp::eNever;
bool depth_bounds_test_enable = false; bool depth_bounds_test_enable = false;
float depth_min_bounds = 0.0f; float depth_min_bounds = 0.0f;
float depth_max_bounds = 0.0f; float depth_max_bounds = 0.0f;
@@ -76,7 +76,7 @@ static_assert(std::is_standard_layout_v<PipelineStaticParameters>);
static_assert(alignof(PipelineStaticParameters) == 1); static_assert(alignof(PipelineStaticParameters) == 1);
static_assert(sizeof(PipelineStaticParameters) == static_assert(sizeof(PipelineStaticParameters) ==
sizeof(float[3]) + sizeof(float[3]) + sizeof(bool) + sizeof(int[4]) + sizeof(float[3]) + sizeof(float[3]) + sizeof(bool) + sizeof(int[4]) +
sizeof(VkPrimitiveTopology) + sizeof(bool) * 3 + sizeof(VkCompareOp) + sizeof(vk::PrimitiveTopology) + sizeof(bool) * 3 + sizeof(vk::CompareOp) +
sizeof(bool) + sizeof(float) * 2 + sizeof(bool) + sizeof(bool) + sizeof(float) * 2 + sizeof(bool) +
sizeof(PipelineStencilStaticState) * 2 + sizeof(uint32_t) + sizeof(PipelineStencilStaticState) * 2 + sizeof(uint32_t) +
sizeof(uint32_t[RENDER_COLOR_ATTACHMENTS_MAX]) + sizeof(bool) * 3 + sizeof(uint32_t[RENDER_COLOR_ATTACHMENTS_MAX]) + sizeof(bool) * 3 +
@@ -90,8 +90,8 @@ public:
KYTY_CLASS_NO_COPY(PipelineCache); KYTY_CLASS_NO_COPY(PipelineCache);
struct Pipeline { struct Pipeline {
VkPipelineLayout pipeline_layout = nullptr; vk::PipelineLayout pipeline_layout = nullptr;
VkPipeline pipeline = nullptr; vk::Pipeline pipeline = nullptr;
}; };
struct GraphicsPipeline: Pipeline { struct GraphicsPipeline: Pipeline {
@@ -107,7 +107,7 @@ public:
GraphicsPipeline* CreateGraphicsPipeline( GraphicsPipeline* CreateGraphicsPipeline(
VulkanFramebuffer* framebuffer, RenderColorInfo* colors, uint32_t color_count, VulkanFramebuffer* framebuffer, RenderColorInfo* colors, uint32_t color_count,
RenderDepthInfo* depth, ShaderVertexInputInfo* vs_input_info, HW::Context* ctx, RenderDepthInfo* depth, ShaderVertexInputInfo* vs_input_info, HW::Context* ctx,
HW::Shader* sh_ctx, ShaderPixelInputInfo* ps_input_info, VkPrimitiveTopology topology, HW::Shader* sh_ctx, ShaderPixelInputInfo* ps_input_info, vk::PrimitiveTopology topology,
bool ps_active, std::span<const uint32_t> vs_spirv, std::span<const uint32_t> ps_spirv); bool ps_active, std::span<const uint32_t> vs_spirv, std::span<const uint32_t> ps_spirv);
ComputePipeline* CreateComputePipeline(ShaderComputeInputInfo* input_info, ComputePipeline* CreateComputePipeline(ShaderComputeInputInfo* input_info,
const HW::ComputeShaderInfo* cs_regs, const HW::ComputeShaderInfo* cs_regs,
@@ -192,7 +192,7 @@ private:
void LogPipelineTrace(const char* phase, uint32_t vs_hash0, uint32_t vs_crc32, uint32_t ps_hash0, void LogPipelineTrace(const char* phase, uint32_t vs_hash0, uint32_t vs_crc32, uint32_t ps_hash0,
uint32_t ps_crc32); uint32_t ps_crc32);
void CreatePipelineInternal(PipelineCache::GraphicsPipeline* pipeline, VkRenderPass render_pass, void CreatePipelineInternal(PipelineCache::GraphicsPipeline* pipeline, vk::RenderPass render_pass,
const ShaderVertexInputInfo* vs_input_info, const ShaderVertexInputInfo* vs_input_info,
std::span<const uint32_t> vs_shader, std::span<const uint32_t> vs_shader,
const ShaderPixelInputInfo* ps_input_info, const ShaderPixelInputInfo* ps_input_info,
+4 -4
View File
@@ -4,10 +4,10 @@
#include "common/abi.h" #include "common/abi.h"
#include "common/common.h" #include "common/common.h"
#include "graphics/host_gpu/renderer/streamBuffer.h" #include "graphics/host_gpu/renderer/streamBuffer.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -80,9 +80,9 @@ public:
void Begin() const; void Begin() const;
void End() const; void End() const;
void Execute(); void Execute();
void ExecuteWithSemaphore(VkSemaphore signal_semaphore = nullptr); void ExecuteWithSemaphore(vk::Semaphore signal_semaphore = nullptr);
void ExecuteWithSemaphore(VkSemaphore wait_semaphore, VkPipelineStageFlags wait_stage, void ExecuteWithSemaphore(vk::Semaphore wait_semaphore, vk::PipelineStageFlags wait_stage,
VkSemaphore signal_semaphore); vk::Semaphore signal_semaphore);
void SetDebugInfo(uint32_t op, uint64_t submit_id, uint32_t arg0 = 0, uint32_t arg1 = 0, void SetDebugInfo(uint32_t op, uint64_t submit_id, uint32_t arg0 = 0, uint32_t arg1 = 0,
uint32_t arg2 = 0, uint32_t arg3 = 0, uint64_t arg4 = 0); uint32_t arg2 = 0, uint32_t arg3 = 0, uint64_t arg4 = 0);
void BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorInfo* colors, void BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorInfo* colors,
@@ -23,6 +23,7 @@
#include "graphics/host_gpu/renderer/shaderResourceBarrier.h" #include "graphics/host_gpu/renderer/shaderResourceBarrier.h"
#include "graphics/host_gpu/renderer/shaderSubgroup.h" #include "graphics/host_gpu/renderer/shaderSubgroup.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/recompiler/ResourceMaterialization.h" #include "graphics/shader/recompiler/ResourceMaterialization.h"
#include "graphics/shader/recompiler/ShaderIR.h" #include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/shader.h" #include "graphics/shader/shader.h"
@@ -38,9 +39,6 @@
#include <span> #include <span>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <vulkan/vk_enum_string_helper.h>
// IWYU pragma: no_forward_declare VkImageView_T
namespace Libs::Graphics { namespace Libs::Graphics {
static uint64_t BufferDescriptorSize(const ShaderBufferResource& descriptor) { static uint64_t BufferDescriptorSize(const ShaderBufferResource& descriptor) {
@@ -530,20 +528,20 @@ void RenderDispatchDirect(uint64_t submit_id, CommandBuffer* buffer, HW::Context
for (;;) { for (;;) {
const auto recording_generation = buffer->GetRecordingGeneration(); const auto recording_generation = buffer->GetRecordingGeneration();
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; auto vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
auto* pipeline = g_render_ctx->GetPipelineCache()->CreateComputePipeline( auto* pipeline = g_render_ctx->GetPipelineCache()->CreateComputePipeline(
&input_info, &sh_ctx->GetCs(), cs_shader); &input_info, &sh_ctx->GetCs(), cs_shader);
vkCmdBindPipeline(vk_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->pipeline); vk_buffer.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->pipeline);
const auto address_writes = BindDescriptors( const auto address_writes = BindDescriptors(
submit_id, buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->pipeline_layout, submit_id, buffer, vk::PipelineBindPoint::eCompute, pipeline->pipeline_layout,
input_info.stage, VK_SHADER_STAGE_COMPUTE_BIT, DescriptorCache::Stage::Compute); input_info.stage, vk::ShaderStageFlagBits::eCompute, DescriptorCache::Stage::Compute);
if (buffer->GetRecordingGeneration() != recording_generation) { if (buffer->GetRecordingGeneration() != recording_generation) {
continue; continue;
} }
vkCmdDispatch(vk_buffer, thread_group_x, thread_group_y, thread_group_z); vk_buffer.dispatch(thread_group_x, thread_group_y, thread_group_z);
bool has_storage_writes = HasShaderBufferWrites(input_info.stage); bool has_storage_writes = HasShaderBufferWrites(input_info.stage);
has_storage_writes = MarkShaderAddressWrites(address_writes) || has_storage_writes; has_storage_writes = MarkShaderAddressWrites(address_writes) || has_storage_writes;
@@ -557,7 +555,7 @@ void RenderDispatchDirect(uint64_t submit_id, CommandBuffer* buffer, HW::Context
}) || }) ||
has_storage_writes; has_storage_writes;
if (has_storage_writes) { if (has_storage_writes) {
ShaderWriteBarrier(vk_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); ShaderWriteBarrier(vk_buffer, vk::PipelineStageFlagBits::eComputeShader);
} }
break; break;
} }
+102 -105
View File
@@ -27,6 +27,7 @@
#include "graphics/host_gpu/renderer/shaderResourceBarrier.h" #include "graphics/host_gpu/renderer/shaderResourceBarrier.h"
#include "graphics/host_gpu/renderer/shaderSubgroup.h" #include "graphics/host_gpu/renderer/shaderSubgroup.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/recompiler/ResourceMaterialization.h" #include "graphics/shader/recompiler/ResourceMaterialization.h"
#include "graphics/shader/recompiler/ShaderIR.h" #include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/shader.h" #include "graphics/shader/shader.h"
@@ -43,9 +44,6 @@
#include <span> #include <span>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <vulkan/vk_enum_string_helper.h>
// IWYU pragma: no_forward_declare VkImageView_T
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -88,7 +86,7 @@ static void LogFramebufferSkip(const char* draw_name, const RenderColorInfo& col
" color_image=%s depth_format=%s depth_image=%s depth_vaddr_num=%d target_mask=0x%08" PRIx32 " color_image=%s depth_format=%s depth_image=%s depth_vaddr_num=%d target_mask=0x%08" PRIx32
" prim=%u index_count=%u flags=0x%08" PRIx32 "\n", " prim=%u index_count=%u flags=0x%08" PRIx32 "\n",
log_id, draw_name, RenderColorTypeName(color.type), color.base_addr, color.buffer_size, log_id, draw_name, RenderColorTypeName(color.type), color.base_addr, color.buffer_size,
color.vulkan_buffer != nullptr ? "yes" : "no", string_VkFormat(depth.format), color.vulkan_buffer != nullptr ? "yes" : "no", VulkanToString(depth.format).c_str(),
depth.vulkan_buffer != nullptr ? "yes" : "no", depth.vaddr_num, depth.vulkan_buffer != nullptr ? "yes" : "no", depth.vaddr_num,
ctx != nullptr ? ctx->GetRenderTargetMask() : 0, ucfg != nullptr ? ucfg->GetPrimType() : 0, ctx != nullptr ? ctx->GetRenderTargetMask() : 0, ucfg != nullptr ? ucfg->GetPrimType() : 0,
index_count, flags); index_count, flags);
@@ -184,8 +182,8 @@ static void LogDrawTargetState(const char* draw_name, const RenderColorInfo& col
image.kind == ShaderRecompiler::IR::ResourceKind::ImageUint; image.kind == ShaderRecompiler::IR::ResourceKind::ImageUint;
}); });
VkExtent2D extent = color.vulkan_buffer != nullptr ? color.extent : VkExtent2D {}; vk::Extent2D extent = color.vulkan_buffer != nullptr ? color.extent : vk::Extent2D {};
auto sc = calc_final_scissor(vp, ctx->GetScanModeControl(), extent); auto sc = calc_final_scissor(vp, ctx->GetScanModeControl(), extent);
LOGF( LOGF(
"DrawTargetState[%u]: frame=%d %s target=%s addr=0x%010" PRIx64 "DrawTargetState[%u]: frame=%d %s target=%s addr=0x%010" PRIx64
@@ -350,20 +348,16 @@ static void LogDrawInputState(const RenderColorInfo& color,
} }
} }
static void VulkanCmdSetColorWriteEnableEXT(GraphicContext* ctx, VkCommandBuffer command_buffer, static void VulkanCmdSetColorWriteEnableEXT(GraphicContext* ctx, vk::CommandBuffer command_buffer,
uint32_t attachment_count, uint32_t attachment_count,
const VkBool32* p_color_write_enables) { const vk::Bool32* p_color_write_enables) {
EXIT_IF(ctx == nullptr); EXIT_IF(ctx == nullptr);
EXIT_IF(ctx->instance == nullptr); EXIT_IF(ctx->device == nullptr);
static auto func = reinterpret_cast<PFN_vkCmdSetColorWriteEnableEXT>( if (VULKAN_HPP_DEFAULT_DISPATCHER.vkCmdSetColorWriteEnableEXT == nullptr) {
vkGetInstanceProcAddr(ctx->instance, "vkCmdSetColorWriteEnableEXT"));
if (func != nullptr) {
func(command_buffer, attachment_count, p_color_write_enables);
} else {
EXIT("vkCmdSetColorWriteEnableEXT not present\n"); EXIT("vkCmdSetColorWriteEnableEXT not present\n");
} }
command_buffer.setColorWriteEnableEXT(attachment_count, p_color_write_enables);
} }
static PipelineDynamicParameters BuildGraphicsDynamicParams(const HW::Context& ctx, static PipelineDynamicParameters BuildGraphicsDynamicParams(const HW::Context& ctx,
@@ -376,8 +370,8 @@ static PipelineDynamicParameters BuildGraphicsDynamicParams(const HW::Context&
ret.color_write_count = color_count; ret.color_write_count = color_count;
ret.stencil_test_enable = depth.stencil_test_enable; ret.stencil_test_enable = depth.stencil_test_enable;
const auto& vp = ctx.GetScreenViewport(); const auto& vp = ctx.GetScreenViewport();
VkExtent2D framebuffer_extent {}; vk::Extent2D framebuffer_extent {};
if (color_count > 0 && colors[0].vulkan_buffer != nullptr) { if (color_count > 0 && colors[0].vulkan_buffer != nullptr) {
framebuffer_extent = colors[0].extent; framebuffer_extent = colors[0].extent;
} else if (depth.vulkan_buffer != nullptr) { } else if (depth.vulkan_buffer != nullptr) {
@@ -411,25 +405,25 @@ static PipelineDynamicParameters BuildGraphicsDynamicParams(const HW::Context&
return ret; return ret;
} }
static void SetDynamicParams(VkCommandBuffer vk_buffer, static void SetDynamicParams(vk::CommandBuffer vk_buffer,
const PipelineDynamicParameters& dynamic_params) { const PipelineDynamicParameters& dynamic_params) {
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
VkViewport viewport {}; vk::Viewport viewport {};
viewport.x = dynamic_params.viewport_offset[0] - dynamic_params.viewport_scale[0]; viewport.x = dynamic_params.viewport_offset[0] - dynamic_params.viewport_scale[0];
viewport.y = dynamic_params.viewport_offset[1] - dynamic_params.viewport_scale[1]; viewport.y = dynamic_params.viewport_offset[1] - dynamic_params.viewport_scale[1];
viewport.width = dynamic_params.viewport_scale[0] * 2.0f; viewport.width = dynamic_params.viewport_scale[0] * 2.0f;
viewport.height = dynamic_params.viewport_scale[1] * 2.0f; viewport.height = dynamic_params.viewport_scale[1] * 2.0f;
viewport.minDepth = dynamic_params.viewport_offset[2]; viewport.minDepth = dynamic_params.viewport_offset[2];
viewport.maxDepth = dynamic_params.viewport_scale[2] + dynamic_params.viewport_offset[2]; viewport.maxDepth = dynamic_params.viewport_scale[2] + dynamic_params.viewport_offset[2];
vkCmdSetViewport(vk_buffer, 0, 1, &viewport); vk_buffer.setViewport(0, 1, &viewport);
VkRect2D scissor {}; vk::Rect2D scissor {};
scissor.offset = {dynamic_params.scissor_ltrb[0], dynamic_params.scissor_ltrb[1]}; scissor.offset = {dynamic_params.scissor_ltrb[0], dynamic_params.scissor_ltrb[1]};
scissor.extent = { scissor.extent = {
static_cast<uint32_t>(dynamic_params.scissor_ltrb[2] - dynamic_params.scissor_ltrb[0]), static_cast<uint32_t>(dynamic_params.scissor_ltrb[2] - dynamic_params.scissor_ltrb[0]),
static_cast<uint32_t>(dynamic_params.scissor_ltrb[3] - dynamic_params.scissor_ltrb[1])}; static_cast<uint32_t>(dynamic_params.scissor_ltrb[3] - dynamic_params.scissor_ltrb[1])};
vkCmdSetScissor(vk_buffer, 0, 1, &scissor); vk_buffer.setScissor(0, 1, &scissor);
float line_width = dynamic_params.line_width; float line_width = dynamic_params.line_width;
if (line_width != 1.0f) { if (line_width != 1.0f) {
@@ -442,24 +436,24 @@ static void SetDynamicParams(VkCommandBuffer vk_buffer,
} }
line_width = 1.0f; line_width = 1.0f;
} }
vkCmdSetLineWidth(vk_buffer, line_width); vk_buffer.setLineWidth(line_width);
if (dynamic_params.stencil_test_enable) { if (dynamic_params.stencil_test_enable) {
vkCmdSetStencilCompareMask(vk_buffer, VK_STENCIL_FACE_FRONT_BIT, vk_buffer.setStencilCompareMask(vk::StencilFaceFlagBits::eFront,
dynamic_params.stencil_front.compareMask); dynamic_params.stencil_front.compareMask);
vkCmdSetStencilCompareMask(vk_buffer, VK_STENCIL_FACE_BACK_BIT, vk_buffer.setStencilCompareMask(vk::StencilFaceFlagBits::eBack,
dynamic_params.stencil_back.compareMask); dynamic_params.stencil_back.compareMask);
vkCmdSetStencilWriteMask(vk_buffer, VK_STENCIL_FACE_FRONT_BIT, vk_buffer.setStencilWriteMask(vk::StencilFaceFlagBits::eFront,
dynamic_params.stencil_front.writeMask); dynamic_params.stencil_front.writeMask);
vkCmdSetStencilWriteMask(vk_buffer, VK_STENCIL_FACE_BACK_BIT, vk_buffer.setStencilWriteMask(vk::StencilFaceFlagBits::eBack,
dynamic_params.stencil_back.writeMask); dynamic_params.stencil_back.writeMask);
vkCmdSetStencilReference(vk_buffer, VK_STENCIL_FACE_FRONT_BIT, vk_buffer.setStencilReference(vk::StencilFaceFlagBits::eFront,
dynamic_params.stencil_front.reference); dynamic_params.stencil_front.reference);
vkCmdSetStencilReference(vk_buffer, VK_STENCIL_FACE_BACK_BIT, vk_buffer.setStencilReference(vk::StencilFaceFlagBits::eBack,
dynamic_params.stencil_back.reference); dynamic_params.stencil_back.reference);
} }
VkBool32 enable[RENDER_COLOR_ATTACHMENTS_MAX] = {}; vk::Bool32 enable[RENDER_COLOR_ATTACHMENTS_MAX] = {};
for (uint32_t i = 0; i < dynamic_params.color_write_count; i++) { for (uint32_t i = 0; i < dynamic_params.color_write_count; i++) {
enable[i] = (dynamic_params.color_write_enable[i] ? VK_TRUE : VK_FALSE); enable[i] = (dynamic_params.color_write_enable[i] ? VK_TRUE : VK_FALSE);
} }
@@ -544,7 +538,7 @@ struct DrawRenderState {
uint32_t color_count = 0; uint32_t color_count = 0;
bool ps_active = true; bool ps_active = true;
VulkanFramebuffer* framebuffer = nullptr; VulkanFramebuffer* framebuffer = nullptr;
VkCommandBuffer vk_buffer = nullptr; vk::CommandBuffer vk_buffer = nullptr;
ShaderVertexInputInfo vs_input_info; ShaderVertexInputInfo vs_input_info;
ShaderPixelInputInfo ps_input_info; ShaderPixelInputInfo ps_input_info;
std::span<const uint32_t> vs_shader; std::span<const uint32_t> vs_shader;
@@ -566,7 +560,7 @@ static bool DrawHasActivePixelShader(const HW::Context* ctx, const HW::Shader* s
EXIT_IF(sh_ctx == nullptr); EXIT_IF(sh_ctx == nullptr);
EXIT_IF(draw.name == nullptr); EXIT_IF(draw.name == nullptr);
const bool with_depth = (state.depth_info.format != VK_FORMAT_UNDEFINED && const bool with_depth = (state.depth_info.format != vk::Format::eUndefined &&
state.depth_info.vulkan_buffer != nullptr); state.depth_info.vulkan_buffer != nullptr);
if (state.color_count != 0 || !with_depth) { if (state.color_count != 0 || !with_depth) {
return true; return true;
@@ -607,11 +601,11 @@ struct DrawEmitInfo {
}; };
struct DrawIndexBufferSource { struct DrawIndexBufferSource {
bool enabled = false; bool enabled = false;
uint64_t address = 0; uint64_t address = 0;
const void* host_data = nullptr; const void* host_data = nullptr;
uint64_t size = 0; uint64_t size = 0;
VkIndexType type = VK_INDEX_TYPE_UINT16; vk::IndexType type = vk::IndexType::eUint16;
}; };
static uint64_t VertexBufferDescriptorSize(const ShaderVertexInputBuffer& buffer) { static uint64_t VertexBufferDescriptorSize(const ShaderVertexInputBuffer& buffer) {
@@ -629,42 +623,44 @@ static void SetDrawDebugPhase(CommandBuffer* buffer, uint64_t submit_id, const D
} }
static bool GetDrawTopology(const HW::UserConfig* ucfg, bool auto_draw, bool use_ngg_rectlist_draw, static bool GetDrawTopology(const HW::UserConfig* ucfg, bool auto_draw, bool use_ngg_rectlist_draw,
VkPrimitiveTopology* topology) { vk::PrimitiveTopology* topology) {
EXIT_IF(ucfg == nullptr); EXIT_IF(ucfg == nullptr);
EXIT_IF(topology == nullptr); EXIT_IF(topology == nullptr);
*topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; *topology = vk::PrimitiveTopology::ePointList;
switch (static_cast<Prospero::PrimitiveType>(ucfg->GetPrimType())) { switch (static_cast<Prospero::PrimitiveType>(ucfg->GetPrimType())) {
case Prospero::PrimitiveType::kNone: return false; case Prospero::PrimitiveType::kNone: return false;
case Prospero::PrimitiveType::kPointList: case Prospero::PrimitiveType::kPointList:
*topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; *topology = vk::PrimitiveTopology::ePointList;
break;
case Prospero::PrimitiveType::kLineList:
*topology = vk::PrimitiveTopology::eLineList;
break; break;
case Prospero::PrimitiveType::kLineList: *topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; break;
case Prospero::PrimitiveType::kLineStrip: case Prospero::PrimitiveType::kLineStrip:
*topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; *topology = vk::PrimitiveTopology::eLineStrip;
break; break;
case Prospero::PrimitiveType::kTriList: case Prospero::PrimitiveType::kTriList:
*topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; *topology = vk::PrimitiveTopology::eTriangleList;
break; break;
case Prospero::PrimitiveType::kTriFan: case Prospero::PrimitiveType::kTriFan:
*topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; *topology = vk::PrimitiveTopology::eTriangleFan;
break; break;
case Prospero::PrimitiveType::kTriStrip: case Prospero::PrimitiveType::kTriStrip:
*topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; *topology = vk::PrimitiveTopology::eTriangleStrip;
break; break;
case Prospero::PrimitiveType::kRectList: case Prospero::PrimitiveType::kRectList:
*topology = (auto_draw && use_ngg_rectlist_draw ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP *topology = (auto_draw && use_ngg_rectlist_draw ? vk::PrimitiveTopology::eTriangleStrip
: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); : vk::PrimitiveTopology::eTriangleList);
break; break;
case Prospero::PrimitiveType::kRectListLegacy: case Prospero::PrimitiveType::kRectListLegacy:
if (!auto_draw) { if (!auto_draw) {
EXIT("unknown primitive type: %u\n", ucfg->GetPrimType()); EXIT("unknown primitive type: %u\n", ucfg->GetPrimType());
} }
*topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; *topology = vk::PrimitiveTopology::eTriangleStrip;
break; break;
case Prospero::PrimitiveType::kQuadListLegacy: case Prospero::PrimitiveType::kQuadListLegacy:
*topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; *topology = vk::PrimitiveTopology::eTriangleFan;
break; break;
default: EXIT("unknown primitive type: %u\n", ucfg->GetPrimType()); default: EXIT("unknown primitive type: %u\n", ucfg->GetPrimType());
} }
@@ -711,7 +707,7 @@ static bool PrepareDrawRenderState(uint64_t submit_id, CommandBuffer* buffer, HW
} }
} }
const bool with_depth = (state->depth_info.format != VK_FORMAT_UNDEFINED && const bool with_depth = (state->depth_info.format != vk::Format::eUndefined &&
state->depth_info.vulkan_buffer != nullptr); state->depth_info.vulkan_buffer != nullptr);
if (state->color_count == 0 && !with_depth) { if (state->color_count == 0 && !with_depth) {
LogFramebufferSkip(draw.name, state->color_info[0], state->depth_info, ctx, ucfg, LogFramebufferSkip(draw.name, state->color_info[0], state->depth_info, ctx, ucfg,
@@ -784,7 +780,7 @@ static void RefreshShaders(HW::Context* ctx, HW::Shader* sh_ctx, const DrawCallI
} }
static void BindDrawVertexBuffers(uint64_t submit_id, CommandBuffer* buffer, static void BindDrawVertexBuffers(uint64_t submit_id, CommandBuffer* buffer,
const DrawCallInfo& draw, VkCommandBuffer vk_buffer, const DrawCallInfo& draw, vk::CommandBuffer vk_buffer,
const ShaderVertexInputInfo& vs_input_info) { const ShaderVertexInputInfo& vs_input_info) {
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
EXIT_IF(draw.name == nullptr); EXIT_IF(draw.name == nullptr);
@@ -792,11 +788,11 @@ static void BindDrawVertexBuffers(uint64_t submit_id, CommandBuffer* buffer,
LogDrawPhase(draw.name, "BindVertexBuffers"); LogDrawPhase(draw.name, "BindVertexBuffers");
for (int i = 0; i < vs_input_info.buffers_num; i++) { for (int i = 0; i < vs_input_info.buffers_num; i++) {
const auto& b = vs_input_info.buffers[i]; const auto& b = vs_input_info.buffers[i];
uint64_t addr = b.addr; uint64_t addr = b.addr;
uint64_t size = VertexBufferDescriptorSize(b); uint64_t size = VertexBufferDescriptorSize(b);
VulkanBuffer* vertices = nullptr; VulkanBuffer* vertices = nullptr;
VkDeviceSize offset = 0; vk::DeviceSize offset = 0;
if (size == 0) { if (size == 0) {
vertices = g_render_ctx->GetBufferCache()->ObtainNullBuffer( vertices = g_render_ctx->GetBufferCache()->ObtainNullBuffer(
@@ -809,21 +805,21 @@ static void BindDrawVertexBuffers(uint64_t submit_id, CommandBuffer* buffer,
} }
EXIT_NOT_IMPLEMENTED(vertices == nullptr); EXIT_NOT_IMPLEMENTED(vertices == nullptr);
vkCmdBindVertexBuffers(vk_buffer, i, 1, &vertices->buffer, &offset); vk_buffer.bindVertexBuffers(i, 1, &vertices->buffer, &offset);
} }
} }
static void BindDrawIndexBuffer(CommandBuffer* buffer, VkCommandBuffer vk_buffer, static void BindDrawIndexBuffer(CommandBuffer* buffer, vk::CommandBuffer vk_buffer,
const DrawIndexBufferSource& source) { const DrawIndexBufferSource& source) {
if (!source.enabled) { if (!source.enabled) {
return; return;
} }
EXIT_IF(source.size == 0); EXIT_IF(source.size == 0);
VulkanBuffer* index_buffer = nullptr; VulkanBuffer* index_buffer = nullptr;
VkDeviceSize index_offset = 0; vk::DeviceSize index_offset = 0;
if (source.host_data != nullptr) { if (source.host_data != nullptr) {
VkDeviceSize range = 0; vk::DeviceSize range = 0;
if (!g_render_ctx->GetBufferCache()->UploadHostData(buffer, g_render_ctx->GetGraphicCtx(), if (!g_render_ctx->GetBufferCache()->UploadHostData(buffer, g_render_ctx->GetGraphicCtx(),
source.host_data, source.size, 16, source.host_data, source.size, 16,
&index_buffer, &index_offset, &range)) { &index_buffer, &index_offset, &range)) {
@@ -836,7 +832,7 @@ static void BindDrawIndexBuffer(CommandBuffer* buffer, VkCommandBuffer vk_buffer
index_offset = binding.second; index_offset = binding.second;
} }
EXIT_IF(index_buffer == nullptr); EXIT_IF(index_buffer == nullptr);
vkCmdBindIndexBuffer(vk_buffer, index_buffer->buffer, index_offset, source.type); vk_buffer.bindIndexBuffer(index_buffer->buffer, index_offset, source.type);
} }
static void LogDrawStateIfNeeded(HW::Context* ctx, HW::UserConfig* ucfg, const DrawCallInfo& draw, static void LogDrawStateIfNeeded(HW::Context* ctx, HW::UserConfig* ucfg, const DrawCallInfo& draw,
@@ -876,7 +872,7 @@ static bool IsHostExpandedRectListDrawSupported(const ShaderVertexInputInfo& vs_
return draw.index_count == 3 || draw.index_count == emit.draw_vertex_count; return draw.index_count == 3 || draw.index_count == emit.draw_vertex_count;
} }
static void EmitDrawPrimitives(const HW::UserConfig* ucfg, VkCommandBuffer vk_buffer, static void EmitDrawPrimitives(const HW::UserConfig* ucfg, vk::CommandBuffer vk_buffer,
const ShaderVertexInputInfo& vs_input_info, const DrawCallInfo& draw, const ShaderVertexInputInfo& vs_input_info, const DrawCallInfo& draw,
const DrawEmitInfo& emit) { const DrawEmitInfo& emit) {
EXIT_IF(ucfg == nullptr); EXIT_IF(ucfg == nullptr);
@@ -890,22 +886,22 @@ static void EmitDrawPrimitives(const HW::UserConfig* ucfg, VkCommandBuffer vk_bu
case Prospero::PrimitiveType::kTriFan: case Prospero::PrimitiveType::kTriFan:
case Prospero::PrimitiveType::kTriStrip: case Prospero::PrimitiveType::kTriStrip:
if (emit.indexed) { if (emit.indexed) {
vkCmdDrawIndexed(vk_buffer, draw.index_count, draw.instance_count, 0, vk_buffer.drawIndexed(draw.index_count, draw.instance_count, 0, emit.vertex_offset,
emit.vertex_offset, draw.first_instance); draw.first_instance);
} else { } else {
vkCmdDraw(vk_buffer, draw.index_count, draw.instance_count, emit.first_vertex, vk_buffer.draw(draw.index_count, draw.instance_count, emit.first_vertex,
draw.first_instance); draw.first_instance);
} }
break; break;
case Prospero::PrimitiveType::kRectList: case Prospero::PrimitiveType::kRectList:
if (emit.indexed) { if (emit.indexed) {
vkCmdDrawIndexed(vk_buffer, draw.index_count, draw.instance_count, 0, vk_buffer.drawIndexed(draw.index_count, draw.instance_count, 0, emit.vertex_offset,
emit.vertex_offset, draw.first_instance); draw.first_instance);
} else { } else {
EXIT_NOT_IMPLEMENTED( EXIT_NOT_IMPLEMENTED(
!IsHostExpandedRectListDrawSupported(vs_input_info, draw, emit)); !IsHostExpandedRectListDrawSupported(vs_input_info, draw, emit));
vkCmdDraw(vk_buffer, emit.draw_vertex_count, draw.instance_count, emit.first_vertex, vk_buffer.draw(emit.draw_vertex_count, draw.instance_count, emit.first_vertex,
draw.first_instance); draw.first_instance);
} }
break; break;
case Prospero::PrimitiveType::kRectListLegacy: case Prospero::PrimitiveType::kRectListLegacy:
@@ -914,17 +910,17 @@ static void EmitDrawPrimitives(const HW::UserConfig* ucfg, VkCommandBuffer vk_bu
} }
// Sarah // Sarah
EXIT_NOT_IMPLEMENTED(!(draw.index_count == 3 && vs_input_info.buffers_num == 0)); EXIT_NOT_IMPLEMENTED(!(draw.index_count == 3 && vs_input_info.buffers_num == 0));
vkCmdDraw(vk_buffer, 4, draw.instance_count, emit.first_vertex, draw.first_instance); vk_buffer.draw(4, draw.instance_count, emit.first_vertex, draw.first_instance);
break; break;
case Prospero::PrimitiveType::kQuadListLegacy: case Prospero::PrimitiveType::kQuadListLegacy:
EXIT_NOT_IMPLEMENTED((draw.index_count & 0x3u) != 0); EXIT_NOT_IMPLEMENTED((draw.index_count & 0x3u) != 0);
for (uint32_t i = 0; i < draw.index_count; i += 4) { for (uint32_t i = 0; i < draw.index_count; i += 4) {
if (emit.indexed) { if (emit.indexed) {
vkCmdDrawIndexed(vk_buffer, 4, draw.instance_count, i, emit.vertex_offset, vk_buffer.drawIndexed(4, draw.instance_count, i, emit.vertex_offset,
draw.first_instance); draw.first_instance);
} else { } else {
vkCmdDraw(vk_buffer, 4, draw.instance_count, i + emit.first_vertex, vk_buffer.draw(4, draw.instance_count, i + emit.first_vertex,
draw.first_instance); draw.first_instance);
} }
} }
break; break;
@@ -934,7 +930,7 @@ static void EmitDrawPrimitives(const HW::UserConfig* ucfg, VkCommandBuffer vk_bu
static void ExecutePreparedDraw(uint64_t submit_id, CommandBuffer* buffer, HW::Context* ctx, static void ExecutePreparedDraw(uint64_t submit_id, CommandBuffer* buffer, HW::Context* ctx,
HW::UserConfig* ucfg, HW::Shader* sh_ctx, const DrawCallInfo& draw, HW::UserConfig* ucfg, HW::Shader* sh_ctx, const DrawCallInfo& draw,
DrawRenderState* state, VkPrimitiveTopology topology, DrawRenderState* state, vk::PrimitiveTopology topology,
const DrawEmitInfo& emit, const DrawIndexBufferSource& index_source, const DrawEmitInfo& emit, const DrawIndexBufferSource& index_source,
bool log_pipeline_phase, bool set_bind_debug, bool set_auto_debug) { bool log_pipeline_phase, bool set_bind_debug, bool set_auto_debug) {
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -957,7 +953,7 @@ static void ExecutePreparedDraw(uint64_t submit_id, CommandBuffer* buffer, HW::C
if (set_bind_debug) { if (set_bind_debug) {
SetDrawDebugPhase(buffer, submit_id, draw, 0x100u); SetDrawDebugPhase(buffer, submit_id, draw, 0x100u);
} }
vkCmdBindPipeline(state->vk_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); state->vk_buffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline->pipeline);
const auto dynamic_params = BuildGraphicsDynamicParams( const auto dynamic_params = BuildGraphicsDynamicParams(
*ctx, state->color_info, state->color_count, state->depth_info); *ctx, state->color_info, state->color_count, state->depth_info);
SetDynamicParams(state->vk_buffer, dynamic_params); SetDynamicParams(state->vk_buffer, dynamic_params);
@@ -969,9 +965,10 @@ static void ExecutePreparedDraw(uint64_t submit_id, CommandBuffer* buffer, HW::C
if (set_auto_debug) { if (set_auto_debug) {
SetDrawDebugPhase(buffer, submit_id, draw, 0x200u); SetDrawDebugPhase(buffer, submit_id, draw, 0x200u);
} }
const auto vs_address_writes = BindDescriptors( const auto vs_address_writes =
submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout, BindDescriptors(submit_id, buffer, vk::PipelineBindPoint::eGraphics,
state->vs_input_info.stage, VK_SHADER_STAGE_VERTEX_BIT, DescriptorCache::Stage::Vertex); pipeline->pipeline_layout, state->vs_input_info.stage,
vk::ShaderStageFlagBits::eVertex, DescriptorCache::Stage::Vertex);
std::vector<ShaderAddressWriteRange> ps_address_writes; std::vector<ShaderAddressWriteRange> ps_address_writes;
if (state->ps_active) { if (state->ps_active) {
@@ -980,9 +977,9 @@ static void ExecutePreparedDraw(uint64_t submit_id, CommandBuffer* buffer, HW::C
SetDrawDebugPhase(buffer, submit_id, draw, 0x300u); SetDrawDebugPhase(buffer, submit_id, draw, 0x300u);
} }
ps_address_writes = ps_address_writes =
BindDescriptors(submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, BindDescriptors(submit_id, buffer, vk::PipelineBindPoint::eGraphics,
pipeline->pipeline_layout, state->ps_input_info.stage, pipeline->pipeline_layout, state->ps_input_info.stage,
VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel); vk::ShaderStageFlagBits::eFragment, DescriptorCache::Stage::Pixel);
} }
if (buffer->GetRecordingGeneration() != recording_generation) { if (buffer->GetRecordingGeneration() != recording_generation) {
continue; continue;
@@ -1010,20 +1007,20 @@ static void ExecutePreparedDraw(uint64_t submit_id, CommandBuffer* buffer, HW::C
SetDrawDebugPhase(buffer, submit_id, draw, 0x600u); SetDrawDebugPhase(buffer, submit_id, draw, 0x600u);
} }
buffer->EndRenderPass(); buffer->EndRenderPass();
VkPipelineStageFlags shader_write_stages = 0; vk::PipelineStageFlags shader_write_stages = {};
const bool vs_wrote_buffers = HasShaderBufferWrites(state->vs_input_info.stage); const bool vs_wrote_buffers = HasShaderBufferWrites(state->vs_input_info.stage);
const bool vs_wrote_addresses = MarkShaderAddressWrites(vs_address_writes); const bool vs_wrote_addresses = MarkShaderAddressWrites(vs_address_writes);
if (vs_wrote_buffers || vs_wrote_addresses) { if (vs_wrote_buffers || vs_wrote_addresses) {
shader_write_stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; shader_write_stages |= vk::PipelineStageFlagBits::eVertexShader;
} }
if (state->ps_active) { if (state->ps_active) {
const bool ps_wrote_buffers = HasShaderBufferWrites(state->ps_input_info.stage); const bool ps_wrote_buffers = HasShaderBufferWrites(state->ps_input_info.stage);
const bool ps_wrote_addresses = MarkShaderAddressWrites(ps_address_writes); const bool ps_wrote_addresses = MarkShaderAddressWrites(ps_address_writes);
if (ps_wrote_buffers || ps_wrote_addresses) { if (ps_wrote_buffers || ps_wrote_addresses) {
shader_write_stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; shader_write_stages |= vk::PipelineStageFlagBits::eFragmentShader;
} }
} }
if (shader_write_stages != 0) { if (shader_write_stages) {
ShaderWriteBarrier(state->vk_buffer, shader_write_stages); ShaderWriteBarrier(state->vk_buffer, shader_write_stages);
} }
LogDrawPhase(draw.name, "EndRenderPass"); LogDrawPhase(draw.name, "EndRenderPass");
@@ -1094,27 +1091,27 @@ void RenderDrawIndex(uint64_t submit_id, CommandBuffer* buffer, HW::Context* ctx
hw_check(*ctx); hw_check(*ctx);
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; vk::PrimitiveTopology topology = vk::PrimitiveTopology::ePointList;
if (!GetDrawTopology(ucfg, false, false, &topology)) { if (!GetDrawTopology(ucfg, false, false, &topology)) {
return; return;
} }
VkIndexType index_type = VK_INDEX_TYPE_UINT16; vk::IndexType index_type = vk::IndexType::eUint16;
uint64_t index_size = 0; uint64_t index_size = 0;
bool expand_index8_to_u16 = false; bool expand_index8_to_u16 = false;
switch (static_cast<Prospero::IndexType>(index_type_and_size)) { switch (static_cast<Prospero::IndexType>(index_type_and_size)) {
case Prospero::IndexType::kIndex16: case Prospero::IndexType::kIndex16:
index_type = VK_INDEX_TYPE_UINT16; index_type = vk::IndexType::eUint16;
index_size = 2 * static_cast<uint64_t>(index_count); index_size = 2 * static_cast<uint64_t>(index_count);
break; break;
case Prospero::IndexType::kIndex32: case Prospero::IndexType::kIndex32:
index_type = VK_INDEX_TYPE_UINT32; index_type = vk::IndexType::eUint32;
index_size = 4 * static_cast<uint64_t>(index_count); index_size = 4 * static_cast<uint64_t>(index_count);
break; break;
// Some games use it - need vulkan extension // Some games use it - need vulkan extension
case Prospero::IndexType::kIndex8: case Prospero::IndexType::kIndex8:
index_type = VK_INDEX_TYPE_UINT16; index_type = vk::IndexType::eUint16;
index_size = static_cast<uint64_t>(index_count); index_size = static_cast<uint64_t>(index_count);
expand_index8_to_u16 = true; expand_index8_to_u16 = true;
break; break;
@@ -1238,8 +1235,8 @@ void RenderDrawIndexAuto(uint64_t submit_id, CommandBuffer* buffer, HW::Context*
return; return;
} }
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; vk::PrimitiveTopology topology = vk::PrimitiveTopology::ePointList;
const bool use_ngg_rectlist_draw = Config::NggRectlistDrawEnabled(); const bool use_ngg_rectlist_draw = Config::NggRectlistDrawEnabled();
if (!GetDrawTopology(ucfg, true, use_ngg_rectlist_draw, &topology)) { if (!GetDrawTopology(ucfg, true, use_ngg_rectlist_draw, &topology)) {
return; return;
+11 -9
View File
@@ -1,9 +1,10 @@
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_RENDERTARGET_H_ #ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_RENDERTARGET_H_
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_RENDERTARGET_H_ #define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_RENDERTARGET_H_
#include "graphics/host_gpu/vulkanCommon.h"
#include <cstdint> #include <cstdint>
#include <type_traits> #include <type_traits>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -40,10 +41,10 @@ inline constexpr TargetViewInfo ResolveTargetViewInfo(uint32_t base_layer, uint3
#pragma pack(push, 1) #pragma pack(push, 1)
struct PipelineStencilStaticState { struct PipelineStencilStaticState {
VkStencilOp failOp = VK_STENCIL_OP_KEEP; vk::StencilOp failOp = vk::StencilOp::eKeep;
VkStencilOp passOp = VK_STENCIL_OP_KEEP; vk::StencilOp passOp = vk::StencilOp::eKeep;
VkStencilOp depthFailOp = VK_STENCIL_OP_KEEP; vk::StencilOp depthFailOp = vk::StencilOp::eKeep;
VkCompareOp compareOp = VK_COMPARE_OP_NEVER; vk::CompareOp compareOp = vk::CompareOp::eNever;
}; };
struct PipelineStencilDynamicState { struct PipelineStencilDynamicState {
@@ -56,16 +57,17 @@ struct PipelineStencilDynamicState {
inline constexpr bool stencil_face_accesses_attachment(const PipelineStencilStaticState& state, inline constexpr bool stencil_face_accesses_attachment(const PipelineStencilStaticState& state,
const PipelineStencilDynamicState& dynamic) { const PipelineStencilDynamicState& dynamic) {
return state.compareOp != VK_COMPARE_OP_ALWAYS || return state.compareOp != vk::CompareOp::eAlways ||
(dynamic.writeMask != 0 && (dynamic.writeMask != 0 &&
(state.failOp != VK_STENCIL_OP_KEEP || state.passOp != VK_STENCIL_OP_KEEP || (state.failOp != vk::StencilOp::eKeep || state.passOp != vk::StencilOp::eKeep ||
state.depthFailOp != VK_STENCIL_OP_KEEP)); state.depthFailOp != vk::StencilOp::eKeep));
} }
static_assert(std::is_trivially_copyable_v<PipelineStencilStaticState>); static_assert(std::is_trivially_copyable_v<PipelineStencilStaticState>);
static_assert(std::is_standard_layout_v<PipelineStencilStaticState>); static_assert(std::is_standard_layout_v<PipelineStencilStaticState>);
static_assert(alignof(PipelineStencilStaticState) == 1); static_assert(alignof(PipelineStencilStaticState) == 1);
static_assert(sizeof(PipelineStencilStaticState) == sizeof(VkStencilOp) * 3 + sizeof(VkCompareOp)); static_assert(sizeof(PipelineStencilStaticState) ==
sizeof(vk::StencilOp) * 3 + sizeof(vk::CompareOp));
static_assert(std::is_trivially_copyable_v<PipelineStencilDynamicState>); static_assert(std::is_trivially_copyable_v<PipelineStencilDynamicState>);
static_assert(std::is_standard_layout_v<PipelineStencilDynamicState>); static_assert(std::is_standard_layout_v<PipelineStencilDynamicState>);
static_assert(alignof(PipelineStencilDynamicState) == 1); static_assert(alignof(PipelineStencilDynamicState) == 1);
@@ -16,6 +16,7 @@
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/displayBuffer.h" #include "graphics/presentation/displayBuffer.h"
#include <algorithm> #include <algorithm>
@@ -24,7 +25,6 @@
#include <cstdarg> #include <cstdarg>
#include <cstdio> #include <cstdio>
#include <limits> #include <limits>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -34,123 +34,127 @@ void GraphicsRenderMemoryBarrier(CommandBuffer* buffer) {
Common::LockGuard lock(g_render_ctx->GetMutex()); Common::LockGuard lock(g_render_ctx->GetMutex());
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; auto vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
VkMemoryBarrier mem_barrier {}; VulkanMemoryBarrier mem_barrier {};
mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; mem_barrier.sType = vk::StructureType::eMemoryBarrier;
mem_barrier.pNext = nullptr; mem_barrier.pNext = nullptr;
mem_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; mem_barrier.srcAccessMask = vk::AccessFlagBits::eMemoryWrite;
mem_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; mem_barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1, &mem_barrier, 0, nullptr, 0, vk::PipelineStageFlagBits::eAllCommands, vk::DependencyFlags {}, 1,
nullptr); &mem_barrier, 0, nullptr, 0, nullptr);
} }
void GraphicsRenderTextureBarrier(VkCommandBuffer vk_buffer, VulkanImage* image) { void GraphicsRenderTextureBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image) {
EXIT_IF(image == nullptr); EXIT_IF(image == nullptr);
VkImageMemoryBarrier image_memory_barrier {}; vk::ImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; image_memory_barrier.sType = vk::StructureType::eImageMemoryBarrier;
image_memory_barrier.pNext = nullptr; image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | image_memory_barrier.srcAccessMask =
VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT | vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eTransferWrite |
VK_ACCESS_MEMORY_READ_BIT; vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eMemoryRead;
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
image_memory_barrier.oldLayout = image->layout; image_memory_barrier.oldLayout = image->layout;
image_memory_barrier.newLayout = RENDER_COLOR_IMAGE_LAYOUT; image_memory_barrier.newLayout = RENDER_COLOR_IMAGE_LAYOUT;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = image->image; image_memory_barrier.image = image->image;
image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_memory_barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
image_memory_barrier.subresourceRange.baseMipLevel = 0; image_memory_barrier.subresourceRange.baseMipLevel = 0;
image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
image_memory_barrier.subresourceRange.baseArrayLayer = 0; image_memory_barrier.subresourceRange.baseArrayLayer = 0;
image_memory_barrier.subresourceRange.layerCount = image->layers; image_memory_barrier.subresourceRange.layerCount = image->layers;
vkCmdPipelineBarrier( vk_buffer.pipelineBarrier(
vk_buffer, vk::PipelineStageFlagBits::eColorAttachmentOutput |
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eTransfer |
VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::PipelineStageFlagBits::eFragmentShader,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eFragmentShader |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::PipelineStageFlagBits::eComputeShader,
0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
image->layout = image_memory_barrier.newLayout; image->layout = image_memory_barrier.newLayout;
} }
void GraphicsRenderColorImageBarrier(VkCommandBuffer vk_buffer, VulkanImage* image, void GraphicsRenderColorImageBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image,
VkImageLayout new_layout) { vk::ImageLayout new_layout) {
EXIT_IF(image == nullptr); EXIT_IF(image == nullptr);
if (image->layout != new_layout) { if (image->layout != new_layout) {
if (image->type == VulkanImageType::VideoOut && if (image->type == VulkanImageType::VideoOut &&
image->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { image->layout == vk::ImageLayout::eTransferDstOptimal) {
static std::atomic<uint32_t> log_count {0}; static std::atomic<uint32_t> log_count {0};
if (log_count.fetch_add(1, std::memory_order_relaxed) < 128) { if (log_count.fetch_add(1, std::memory_order_relaxed) < 128) {
LOGF("GraphicsRenderColorImageBarrier: image=%p type=%d layout=%s -> %s\n", LOGF("GraphicsRenderColorImageBarrier: image=%p type=%d layout=%s -> %s\n",
reinterpret_cast<void*>(image->image), static_cast<int>(image->type), VulkanHandleToPointer(image->image), static_cast<int>(image->type),
string_VkImageLayout(image->layout), string_VkImageLayout(new_layout)); VulkanToString(image->layout).c_str(), VulkanToString(new_layout).c_str());
} }
} }
VkImageMemoryBarrier image_memory_barrier {}; vk::ImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; image_memory_barrier.sType = vk::StructureType::eImageMemoryBarrier;
image_memory_barrier.pNext = nullptr; image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT; image_memory_barrier.srcAccessMask =
image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT; vk::AccessFlagBits::eMemoryWrite | vk::AccessFlagBits::eMemoryRead;
image_memory_barrier.oldLayout = image->layout; image_memory_barrier.dstAccessMask =
image_memory_barrier.newLayout = new_layout; vk::AccessFlagBits::eMemoryWrite | vk::AccessFlagBits::eMemoryRead;
image_memory_barrier.oldLayout = image->layout;
image_memory_barrier.newLayout = new_layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = image->image; image_memory_barrier.image = image->image;
image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_memory_barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
image_memory_barrier.subresourceRange.baseMipLevel = 0; image_memory_barrier.subresourceRange.baseMipLevel = 0;
image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
image_memory_barrier.subresourceRange.baseArrayLayer = 0; image_memory_barrier.subresourceRange.baseArrayLayer = 0;
image_memory_barrier.subresourceRange.layerCount = image->layers; image_memory_barrier.subresourceRange.layerCount = image->layers;
const auto stages = static_cast<VkPipelineStageFlags>(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | const auto stages = static_cast<vk::PipelineStageFlags>(
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader |
VK_PIPELINE_STAGE_TRANSFER_BIT); vk::PipelineStageFlagBits::eTransfer);
vkCmdPipelineBarrier(vk_buffer, stages, stages, 0, 0, nullptr, 0, nullptr, 1, vk_buffer.pipelineBarrier(stages, stages, vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1,
&image_memory_barrier); &image_memory_barrier);
image->layout = image_memory_barrier.newLayout; image->layout = image_memory_barrier.newLayout;
} }
} }
VkImageAspectFlags DepthStencilAspectMask(VkFormat format); vk::ImageAspectFlags DepthStencilAspectMask(vk::Format format);
void GraphicsRenderDepthStencilImageBarrier(VkCommandBuffer vk_buffer, VulkanImage* image, void GraphicsRenderDepthStencilImageBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image,
VkImageLayout new_layout) { vk::ImageLayout new_layout) {
EXIT_IF(image == nullptr); EXIT_IF(image == nullptr);
EXIT_IF(image->type != VulkanImageType::DepthStencil); EXIT_IF(image->type != VulkanImageType::DepthStencil);
if (new_layout == VK_IMAGE_LAYOUT_UNDEFINED || new_layout == VK_IMAGE_LAYOUT_PREINITIALIZED) { if (new_layout == vk::ImageLayout::eUndefined ||
new_layout == vk::ImageLayout::ePreinitialized) {
EXIT("invalid destination depth/stencil image layout: %s\n", EXIT("invalid destination depth/stencil image layout: %s\n",
string_VkImageLayout(new_layout)); VulkanToString(new_layout).c_str());
} }
if (image->layout == new_layout) { if (image->layout == new_layout) {
return; return;
} }
VkImageMemoryBarrier barrier {}; vk::ImageMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.sType = vk::StructureType::eImageMemoryBarrier;
barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; barrier.srcAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
barrier.oldLayout = image->layout; barrier.oldLayout = image->layout;
barrier.newLayout = new_layout; barrier.newLayout = new_layout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image->image; barrier.image = image->image;
barrier.subresourceRange = {DepthStencilAspectMask(image->format), 0, VK_REMAINING_MIP_LEVELS, barrier.subresourceRange = {DepthStencilAspectMask(image->format), 0, VK_REMAINING_MIP_LEVELS,
0, image->layers}; 0, image->layers};
const auto stages = static_cast<VkPipelineStageFlags>(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | const auto stages = static_cast<vk::PipelineStageFlags>(
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader |
VK_PIPELINE_STAGE_TRANSFER_BIT); vk::PipelineStageFlagBits::eTransfer);
vkCmdPipelineBarrier(vk_buffer, stages, stages, 0, 0, nullptr, 0, nullptr, 1, &barrier); vk_buffer.pipelineBarrier(stages, stages, vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1,
&barrier);
image->layout = new_layout; image->layout = new_layout;
} }
void GraphicsRenderDepthStencilBarrier(VkCommandBuffer vk_buffer, VulkanImage* image) { void GraphicsRenderDepthStencilBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image) {
EXIT_IF(image == nullptr); EXIT_IF(image == nullptr);
EXIT_IF(image->type != VulkanImageType::DepthStencil); EXIT_IF(image->type != VulkanImageType::DepthStencil);
@@ -161,35 +165,35 @@ void GraphicsRenderDepthStencilBarrier(VkCommandBuffer vk_buffer, VulkanImage* i
if (log_count.fetch_add(1, std::memory_order_relaxed) < 16) { if (log_count.fetch_add(1, std::memory_order_relaxed) < 16) {
LOGF( LOGF(
"DepthTexture: decompressing depth target for shader read format=%s extent=%ux%u\n", "DepthTexture: decompressing depth target for shader read format=%s extent=%ux%u\n",
string_VkFormat(depth->format), depth->extent.width, depth->extent.height); VulkanToString(depth->format).c_str(), depth->extent.width, depth->extent.height);
} }
depth->compressed = false; depth->compressed = false;
} }
if (image->layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) { if (image->layout != vk::ImageLayout::eDepthStencilReadOnlyOptimal) {
VkImageMemoryBarrier image_memory_barrier {}; vk::ImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; image_memory_barrier.sType = vk::StructureType::eImageMemoryBarrier;
image_memory_barrier.pNext = nullptr; image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; image_memory_barrier.srcAccessMask =
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
image_memory_barrier.oldLayout = image->layout; image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; image_memory_barrier.oldLayout = image->layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = image->image; image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = image->image;
image_memory_barrier.subresourceRange.aspectMask = DepthStencilAspectMask(image->format); image_memory_barrier.subresourceRange.aspectMask = DepthStencilAspectMask(image->format);
image_memory_barrier.subresourceRange.baseMipLevel = 0; image_memory_barrier.subresourceRange.baseMipLevel = 0;
image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
image_memory_barrier.subresourceRange.baseArrayLayer = 0; image_memory_barrier.subresourceRange.baseArrayLayer = 0;
image_memory_barrier.subresourceRange.layerCount = image->layers; image_memory_barrier.subresourceRange.layerCount = image->layers;
vkCmdPipelineBarrier( vk_buffer.pipelineBarrier(
vk_buffer, vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader |
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | vk::PipelineStageFlagBits::eTransfer,
VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eFragmentShader |
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | vk::PipelineStageFlagBits::eComputeShader,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
image->layout = image_memory_barrier.newLayout; image->layout = image_memory_barrier.newLayout;
} }
@@ -201,7 +205,7 @@ void GraphicsRenderTextureBarrier(CommandBuffer* buffer, uint64_t vaddr, uint64_
Common::LockGuard lock(g_render_ctx->GetMutex()); Common::LockGuard lock(g_render_ctx->GetMutex());
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; auto vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
auto* native = g_render_ctx->GetTextureCache()->FindRenderTargetByRange(buffer, vaddr, size); auto* native = g_render_ctx->GetTextureCache()->FindRenderTargetByRange(buffer, vaddr, size);
if (native == nullptr) { if (native == nullptr) {
@@ -216,7 +220,7 @@ void GraphicsRenderDepthStencilBarrier(CommandBuffer* buffer, uint64_t vaddr, ui
Common::LockGuard lock(g_render_ctx->GetMutex()); Common::LockGuard lock(g_render_ctx->GetMutex());
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; auto vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
auto* native = g_render_ctx->GetTextureCache()->FindDepthTargetByRange(buffer, vaddr, size); auto* native = g_render_ctx->GetTextureCache()->FindDepthTargetByRange(buffer, vaddr, size);
if (native == nullptr) { if (native == nullptr) {
EXIT("depth-target barrier range has no cached image\n"); EXIT("depth-target barrier range has no cached image\n");
@@ -1,18 +1,18 @@
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_RENDERTARGETBARRIERS_H_ #ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_RENDERTARGETBARRIERS_H_
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_RENDERTARGETBARRIERS_H_ #define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_RENDERTARGETBARRIERS_H_
#include <vulkan/vulkan_core.h> #include "graphics/host_gpu/vulkanCommon.h"
namespace Libs::Graphics { namespace Libs::Graphics {
struct VulkanImage; struct VulkanImage;
void GraphicsRenderTextureBarrier(VkCommandBuffer vk_buffer, VulkanImage* image); void GraphicsRenderTextureBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image);
void GraphicsRenderColorImageBarrier(VkCommandBuffer vk_buffer, VulkanImage* image, void GraphicsRenderColorImageBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image,
VkImageLayout new_layout); vk::ImageLayout new_layout);
void GraphicsRenderDepthStencilImageBarrier(VkCommandBuffer vk_buffer, VulkanImage* image, void GraphicsRenderDepthStencilImageBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image,
VkImageLayout new_layout); vk::ImageLayout new_layout);
void GraphicsRenderDepthStencilBarrier(VkCommandBuffer vk_buffer, VulkanImage* image); void GraphicsRenderDepthStencilBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image);
} // namespace Libs::Graphics } // namespace Libs::Graphics
+30 -30
View File
@@ -7,7 +7,7 @@
namespace Libs::Graphics { namespace Libs::Graphics {
VkSampler SamplerCache::GetSampler(const ShaderSamplerResource& r) { vk::Sampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
Common::LockGuard lock(m_mutex); Common::LockGuard lock(m_mutex);
const SamplerKey key {r.fields[0], r.fields[1], r.fields[2], r.fields[3]}; const SamplerKey key {r.fields[0], r.fields[1], r.fields[2], r.fields[3]};
@@ -33,12 +33,12 @@ VkSampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
auto to_vk_filter = [](uint8_t filter) { auto to_vk_filter = [](uint8_t filter) {
switch (static_cast<Prospero::SamplerFilter>(filter)) { switch (static_cast<Prospero::SamplerFilter>(filter)) {
case Prospero::SamplerFilter::kPoint: case Prospero::SamplerFilter::kPoint:
case Prospero::SamplerFilter::kAnisoPoint: return VK_FILTER_NEAREST; case Prospero::SamplerFilter::kAnisoPoint: return vk::Filter::eNearest;
case Prospero::SamplerFilter::kBilinear: case Prospero::SamplerFilter::kBilinear:
case Prospero::SamplerFilter::kAnisoLinear: return VK_FILTER_LINEAR; case Prospero::SamplerFilter::kAnisoLinear: return vk::Filter::eLinear;
default: EXIT("unknown sampler filter: %u\n", filter); default: EXIT("unknown sampler filter: %u\n", filter);
} }
return VK_FILTER_NEAREST; return vk::Filter::eNearest;
}; };
const bool aniso = is_aniso_filter(mag_filter) || is_aniso_filter(min_filter); const bool aniso = is_aniso_filter(mag_filter) || is_aniso_filter(min_filter);
@@ -61,60 +61,60 @@ VkSampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
max_lod = static_cast<float>(r.MaxLod()) / 256.0f; max_lod = static_cast<float>(r.MaxLod()) / 256.0f;
} }
VkSamplerCreateInfo sampler_info {}; vk::SamplerCreateInfo sampler_info {};
auto to_vk_address_mode = [](uint8_t clamp) { auto to_vk_address_mode = [](uint8_t clamp) {
switch (static_cast<Prospero::SamplerClampMode>(clamp)) { switch (static_cast<Prospero::SamplerClampMode>(clamp)) {
case Prospero::SamplerClampMode::kWrap: return VK_SAMPLER_ADDRESS_MODE_REPEAT; case Prospero::SamplerClampMode::kWrap: return vk::SamplerAddressMode::eRepeat;
case Prospero::SamplerClampMode::kMirror: case Prospero::SamplerClampMode::kMirror:
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; return vk::SamplerAddressMode::eMirroredRepeat;
case Prospero::SamplerClampMode::kClampLastTexel: case Prospero::SamplerClampMode::kClampLastTexel:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; return vk::SamplerAddressMode::eClampToEdge;
case Prospero::SamplerClampMode::kMirrorOnceLastTexel: case Prospero::SamplerClampMode::kMirrorOnceLastTexel:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; return vk::SamplerAddressMode::eMirrorClampToEdge;
case Prospero::SamplerClampMode::kClampHalfBorder: case Prospero::SamplerClampMode::kClampHalfBorder:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; return vk::SamplerAddressMode::eClampToBorder;
case Prospero::SamplerClampMode::kMirrorOnceHalfBorder: case Prospero::SamplerClampMode::kMirrorOnceHalfBorder:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; return vk::SamplerAddressMode::eMirrorClampToEdge;
case Prospero::SamplerClampMode::kClampBorder: case Prospero::SamplerClampMode::kClampBorder:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; return vk::SamplerAddressMode::eClampToBorder;
case Prospero::SamplerClampMode::kMirrorOnceBorder: case Prospero::SamplerClampMode::kMirrorOnceBorder:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; return vk::SamplerAddressMode::eMirrorClampToEdge;
default: EXIT("unknown clamp: %u\n", clamp); default: EXIT("unknown clamp: %u\n", clamp);
} }
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; return vk::SamplerAddressMode::eClampToBorder;
}; };
VkBorderColor border = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK; vk::BorderColor border = vk::BorderColor::eIntTransparentBlack;
switch (static_cast<Prospero::SamplerBorderColor>(r.BorderColorType())) { switch (static_cast<Prospero::SamplerBorderColor>(r.BorderColorType())) {
case Prospero::SamplerBorderColor::kTransBlack: case Prospero::SamplerBorderColor::kTransBlack:
border = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK; border = vk::BorderColor::eIntTransparentBlack;
break; break;
case Prospero::SamplerBorderColor::kOpaqueBlack: case Prospero::SamplerBorderColor::kOpaqueBlack:
border = VK_BORDER_COLOR_INT_OPAQUE_BLACK; border = vk::BorderColor::eIntOpaqueBlack;
break; break;
case Prospero::SamplerBorderColor::kOpaqueWhite: case Prospero::SamplerBorderColor::kOpaqueWhite:
border = VK_BORDER_COLOR_INT_OPAQUE_WHITE; border = vk::BorderColor::eIntOpaqueWhite;
break; break;
case Prospero::SamplerBorderColor::kFromTable: case Prospero::SamplerBorderColor::kFromTable:
LOGF( LOGF(
"temporary: approximating table border color as transparent black, index = %" PRIu16 "temporary: approximating table border color as transparent black, index = %" PRIu16
"\n", "\n",
r.BorderColorPtr()); r.BorderColorPtr());
border = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK; border = vk::BorderColor::eIntTransparentBlack;
break; break;
default: EXIT("unknown border color: %d", static_cast<int>(r.BorderColorType())); default: EXIT("unknown border color: %d", static_cast<int>(r.BorderColorType()));
} }
sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; sampler_info.sType = vk::StructureType::eSamplerCreateInfo;
sampler_info.pNext = nullptr; sampler_info.pNext = nullptr;
sampler_info.flags = 0; sampler_info.flags = {};
sampler_info.magFilter = to_vk_filter(mag_filter); sampler_info.magFilter = to_vk_filter(mag_filter);
sampler_info.minFilter = to_vk_filter(min_filter); sampler_info.minFilter = to_vk_filter(min_filter);
sampler_info.mipmapMode = sampler_info.mipmapMode =
(static_cast<Prospero::SamplerMipFilter>(mip_filter) == Prospero::SamplerMipFilter::kLinear (static_cast<Prospero::SamplerMipFilter>(mip_filter) == Prospero::SamplerMipFilter::kLinear
? VK_SAMPLER_MIPMAP_MODE_LINEAR ? vk::SamplerMipmapMode::eLinear
: VK_SAMPLER_MIPMAP_MODE_NEAREST); : vk::SamplerMipmapMode::eNearest);
sampler_info.addressModeU = to_vk_address_mode(r.ClampX()); sampler_info.addressModeU = to_vk_address_mode(r.ClampX());
sampler_info.addressModeV = to_vk_address_mode(r.ClampY()); sampler_info.addressModeV = to_vk_address_mode(r.ClampY());
sampler_info.addressModeW = to_vk_address_mode(r.ClampZ()); sampler_info.addressModeW = to_vk_address_mode(r.ClampZ());
@@ -123,17 +123,17 @@ VkSampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
sampler_info.anisotropyEnable = (aniso ? VK_TRUE : VK_FALSE); sampler_info.anisotropyEnable = (aniso ? VK_TRUE : VK_FALSE);
sampler_info.maxAnisotropy = aniso_ratio; sampler_info.maxAnisotropy = aniso_ratio;
sampler_info.compareEnable = (r.DepthCompareFunc() != 0 ? VK_TRUE : VK_FALSE); sampler_info.compareEnable = (r.DepthCompareFunc() != 0 ? VK_TRUE : VK_FALSE);
sampler_info.compareOp = static_cast<VkCompareOp>(r.DepthCompareFunc()); sampler_info.compareOp = static_cast<vk::CompareOp>(r.DepthCompareFunc());
sampler_info.minLod = min_lod; sampler_info.minLod = min_lod;
sampler_info.maxLod = max_lod; sampler_info.maxLod = max_lod;
sampler_info.borderColor = border; sampler_info.borderColor = border;
sampler_info.unnormalizedCoordinates = (r.ForceUnormCoords() ? VK_TRUE : VK_FALSE); sampler_info.unnormalizedCoordinates = (r.ForceUnormCoords() ? VK_TRUE : VK_FALSE);
if (r.ForceUnormCoords()) { if (r.ForceUnormCoords()) {
sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; sampler_info.addressModeU = vk::SamplerAddressMode::eClampToEdge;
sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; sampler_info.addressModeV = vk::SamplerAddressMode::eClampToEdge;
sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; sampler_info.addressModeW = vk::SamplerAddressMode::eClampToEdge;
sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; sampler_info.mipmapMode = vk::SamplerMipmapMode::eNearest;
sampler_info.minLod = 0.0f; sampler_info.minLod = 0.0f;
sampler_info.maxLod = 0.0f; sampler_info.maxLod = 0.0f;
sampler_info.anisotropyEnable = VK_FALSE; sampler_info.anisotropyEnable = VK_FALSE;
@@ -142,8 +142,8 @@ VkSampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
sampler_info.mipLodBias = 0.0f; sampler_info.mipLodBias = 0.0f;
} }
VkSampler vk_sampler = nullptr; vk::Sampler vk_sampler = nullptr;
vkCreateSampler(g_render_ctx->GetGraphicCtx()->device, &sampler_info, nullptr, &vk_sampler); g_render_ctx->GetGraphicCtx()->device.createSampler(&sampler_info, nullptr, &vk_sampler);
EXIT_NOT_IMPLEMENTED(vk_sampler == nullptr); EXIT_NOT_IMPLEMENTED(vk_sampler == nullptr);
m_samplers.emplace(key, vk_sampler); m_samplers.emplace(key, vk_sampler);
@@ -5,12 +5,12 @@
#include "common/assert.h" #include "common/assert.h"
#include "common/common.h" #include "common/common.h"
#include "common/threads.h" #include "common/threads.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/shaderBindings.h" #include "graphics/shader/shaderBindings.h"
#include <array> #include <array>
#include <cstddef> #include <cstddef>
#include <unordered_map> #include <unordered_map>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -20,7 +20,7 @@ public:
virtual ~SamplerCache() { KYTY_NOT_IMPLEMENTED; } virtual ~SamplerCache() { KYTY_NOT_IMPLEMENTED; }
KYTY_CLASS_NO_COPY(SamplerCache); KYTY_CLASS_NO_COPY(SamplerCache);
VkSampler GetSampler(const ShaderSamplerResource& r); vk::Sampler GetSampler(const ShaderSamplerResource& r);
private: private:
using SamplerKey = std::array<uint32_t, 4>; using SamplerKey = std::array<uint32_t, 4>;
@@ -37,8 +37,8 @@ private:
} }
}; };
Common::Mutex m_mutex; Common::Mutex m_mutex;
std::unordered_map<SamplerKey, VkSampler, SamplerKeyHash> m_samplers; std::unordered_map<SamplerKey, vk::Sampler, SamplerKeyHash> m_samplers;
}; };
} // namespace Libs::Graphics } // namespace Libs::Graphics
@@ -9,63 +9,70 @@
namespace Libs::Graphics { namespace Libs::Graphics {
VkPipelineStageFlags ShaderPipelineStages(VkShaderStageFlags stages) { vk::PipelineStageFlags ShaderPipelineStages(vk::ShaderStageFlags stages) {
VkPipelineStageFlags result = 0; vk::PipelineStageFlags result = {};
if ((stages & VK_SHADER_STAGE_VERTEX_BIT) != 0) { if (stages & vk::ShaderStageFlagBits::eVertex) {
result |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; result |= vk::PipelineStageFlagBits::eVertexShader;
} }
if ((stages & VK_SHADER_STAGE_FRAGMENT_BIT) != 0) { if (stages & vk::ShaderStageFlagBits::eFragment) {
result |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; result |= vk::PipelineStageFlagBits::eFragmentShader;
} }
if ((stages & VK_SHADER_STAGE_COMPUTE_BIT) != 0) { if (stages & vk::ShaderStageFlagBits::eCompute) {
result |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; result |= vk::PipelineStageFlagBits::eComputeShader;
} }
EXIT_IF(result == 0); EXIT_IF(!result);
return result; return result;
} }
VkMemoryBarrier MakeShaderWriteDependency() { VulkanMemoryBarrier MakeShaderWriteDependency() {
VkMemoryBarrier barrier {}; VulkanMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; barrier.sType = vk::StructureType::eMemoryBarrier;
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; barrier.srcAccessMask = vk::AccessFlagBits::eShaderWrite;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite |
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDEX_READ_BIT | vk::AccessFlagBits::eVertexAttributeRead |
VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | vk::AccessFlagBits::eIndexRead | vk::AccessFlagBits::eUniformRead |
VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; vk::AccessFlagBits::eColorAttachmentRead |
vk::AccessFlagBits::eColorAttachmentWrite;
return barrier; return barrier;
} }
VkImageMemoryBarrier MakeStorageImageDependency(const VulkanImage& image, bool read, bool written) { vk::ImageMemoryBarrier MakeStorageImageDependency(const VulkanImage& image, bool read,
bool written) {
EXIT_IF(image.image == nullptr || image.type == VulkanImageType::DepthStencil); EXIT_IF(image.image == nullptr || image.type == VulkanImageType::DepthStencil);
VkImageMemoryBarrier barrier {}; vk::ImageMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.sType = vk::StructureType::eImageMemoryBarrier;
barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; barrier.srcAccessMask = vk::AccessFlagBits::eMemoryWrite;
barrier.dstAccessMask = barrier.dstAccessMask = {};
(read ? VK_ACCESS_SHADER_READ_BIT : 0) | (written ? VK_ACCESS_SHADER_WRITE_BIT : 0); if (read) {
barrier.dstAccessMask |= vk::AccessFlagBits::eShaderRead;
}
if (written) {
barrier.dstAccessMask |= vk::AccessFlagBits::eShaderWrite;
}
barrier.oldLayout = image.layout; barrier.oldLayout = image.layout;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; barrier.newLayout = vk::ImageLayout::eGeneral;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image.image; barrier.image = image.image;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
barrier.subresourceRange.baseMipLevel = 0; barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = image.layers; barrier.subresourceRange.layerCount = image.layers;
EXIT_IF(barrier.dstAccessMask == 0 || barrier.subresourceRange.layerCount == 0); EXIT_IF(!barrier.dstAccessMask || barrier.subresourceRange.layerCount == 0);
return barrier; return barrier;
} }
VkBufferMemoryBarrier MakeGdsDependency(const VulkanBuffer& buffer) { vk::BufferMemoryBarrier MakeGdsDependency(const VulkanBuffer& buffer) {
EXIT_IF(buffer.buffer == nullptr); EXIT_IF(buffer.buffer == nullptr);
VkBufferMemoryBarrier barrier {}; vk::BufferMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; barrier.sType = vk::StructureType::eBufferMemoryBarrier;
barrier.srcAccessMask = barrier.srcAccessMask = vk::AccessFlagBits::eHostWrite | vk::AccessFlagBits::eTransferWrite |
VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT; vk::AccessFlagBits::eShaderWrite;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.buffer = buffer.buffer; barrier.buffer = buffer.buffer;
@@ -113,15 +120,16 @@ bool HasShaderBufferWrites(const ShaderStageRuntime& runtime) {
return !CollectShaderBufferWrites(*runtime.program, *runtime.resources).empty(); return !CollectShaderBufferWrites(*runtime.program, *runtime.resources).empty();
} }
void ShaderWriteBarrier(VkCommandBuffer vk_buffer, VkPipelineStageFlags source_stages) { void ShaderWriteBarrier(vk::CommandBuffer vk_buffer, vk::PipelineStageFlags source_stages) {
EXIT_IF(vk_buffer == nullptr || source_stages == 0); EXIT_IF(vk_buffer == nullptr || !source_stages);
const auto barrier = MakeShaderWriteDependency(); const auto barrier = MakeShaderWriteDependency();
vkCmdPipelineBarrier( vk_buffer.pipelineBarrier(
vk_buffer, source_stages, source_stages,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eVertexInput |
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eFragmentShader |
VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::PipelineStageFlagBits::eTransfer |
0, 1, &barrier, 0, nullptr, 0, nullptr); vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::DependencyFlags {}, 1, &barrier, 0, nullptr, 0, nullptr);
} }
} // namespace Libs::Graphics } // namespace Libs::Graphics
@@ -18,16 +18,17 @@ struct ShaderBufferWriteRange {
bool operator==(const ShaderBufferWriteRange& other) const = default; bool operator==(const ShaderBufferWriteRange& other) const = default;
}; };
VkPipelineStageFlags ShaderPipelineStages(VkShaderStageFlags stages); vk::PipelineStageFlags ShaderPipelineStages(vk::ShaderStageFlags stages);
VkMemoryBarrier MakeShaderWriteDependency(); VulkanMemoryBarrier MakeShaderWriteDependency();
VkImageMemoryBarrier MakeStorageImageDependency(const VulkanImage& image, bool read, bool written); vk::ImageMemoryBarrier MakeStorageImageDependency(const VulkanImage& image, bool read,
VkBufferMemoryBarrier MakeGdsDependency(const VulkanBuffer& buffer); bool written);
vk::BufferMemoryBarrier MakeGdsDependency(const VulkanBuffer& buffer);
std::vector<ShaderBufferWriteRange> std::vector<ShaderBufferWriteRange>
CollectShaderBufferWrites(const ShaderRecompiler::IR::Program& program, CollectShaderBufferWrites(const ShaderRecompiler::IR::Program& program,
const ShaderRecompiler::IR::ResourceSnapshot& resources); const ShaderRecompiler::IR::ResourceSnapshot& resources);
bool MarkShaderAddressWrites(const std::vector<ShaderAddressWriteRange>& writes); bool MarkShaderAddressWrites(const std::vector<ShaderAddressWriteRange>& writes);
bool HasShaderBufferWrites(const ShaderStageRuntime& runtime); bool HasShaderBufferWrites(const ShaderStageRuntime& runtime);
void ShaderWriteBarrier(VkCommandBuffer vk_buffer, VkPipelineStageFlags source_stages); void ShaderWriteBarrier(vk::CommandBuffer vk_buffer, vk::PipelineStageFlags source_stages);
} // namespace Libs::Graphics } // namespace Libs::Graphics
@@ -17,13 +17,13 @@ ShaderLaneMaskMode SelectGraphicsLaneMaskMode(const GraphicContext& context,
} }
ShaderSubgroupConfiguration ConfigureShaderSubgroup(const GraphicContext& context, ShaderSubgroupConfiguration ConfigureShaderSubgroup(const GraphicContext& context,
VkShaderStageFlagBits stage, vk::ShaderStageFlagBits stage,
const ShaderRecompiler::IR::Program& program) { const ShaderRecompiler::IR::Program& program) {
const auto guest_wave_size = program.wave_size; const auto guest_wave_size = program.wave_size;
if (guest_wave_size != 32u && guest_wave_size != 64u) { if (guest_wave_size != 32u && guest_wave_size != 64u) {
return {}; return {};
} }
if (stage != VK_SHADER_STAGE_COMPUTE_BIT) { if (stage != vk::ShaderStageFlagBits::eCompute) {
const auto expected = SelectGraphicsLaneMaskMode(context, guest_wave_size); const auto expected = SelectGraphicsLaneMaskMode(context, guest_wave_size);
if (program.lane_mask_mode != expected || (context.subgroup_size != guest_wave_size && if (program.lane_mask_mode != expected || (context.subgroup_size != guest_wave_size &&
expected != ShaderLaneMaskMode::PerInvocation)) { expected != ShaderLaneMaskMode::PerInvocation)) {
@@ -40,8 +40,7 @@ ShaderSubgroupConfiguration ConfigureShaderSubgroup(const GraphicContext&
if (context.subgroup_size == guest_wave_size) { if (context.subgroup_size == guest_wave_size) {
return {ShaderSubgroupMode::Natural, 0}; return {ShaderSubgroupMode::Natural, 0};
} }
if (context.subgroup_size_control_enabled && if (context.subgroup_size_control_enabled && (context.required_subgroup_size_stages & stage) &&
(context.required_subgroup_size_stages & stage) != 0 &&
guest_wave_size >= context.min_subgroup_size && guest_wave_size >= context.min_subgroup_size &&
guest_wave_size <= context.max_subgroup_size) { guest_wave_size <= context.max_subgroup_size) {
return {ShaderSubgroupMode::Controlled, guest_wave_size}; return {ShaderSubgroupMode::Controlled, guest_wave_size};
@@ -23,7 +23,7 @@ ShaderLaneMaskMode SelectGraphicsLaneMaskMode(const GraphicContext& context,
uint32_t guest_wave_size); uint32_t guest_wave_size);
ShaderSubgroupConfiguration ConfigureShaderSubgroup(const GraphicContext& context, ShaderSubgroupConfiguration ConfigureShaderSubgroup(const GraphicContext& context,
VkShaderStageFlagBits stage, vk::ShaderStageFlagBits stage,
const ShaderRecompiler::IR::Program& program); const ShaderRecompiler::IR::Program& program);
} // namespace Libs::Graphics } // namespace Libs::Graphics
File diff suppressed because it is too large. Load diff
@@ -32,12 +32,13 @@ void HostStreamBuffer::EnsureBuffer(GraphicContext* ctx) {
KYTY_PROFILER_BLOCK("HostStreamBuffer::create"); KYTY_PROFILER_BLOCK("HostStreamBuffer::create");
m_ctx = ctx; m_ctx = ctx;
m_buffer = std::make_unique<VulkanBuffer>(); m_buffer = std::make_unique<VulkanBuffer>();
m_buffer->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | m_buffer->usage = vk::BufferUsageFlagBits::eStorageBuffer |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::BufferUsageFlagBits::eVertexBuffer |
VK_BUFFER_USAGE_TRANSFER_DST_BIT; vk::BufferUsageFlagBits::eIndexBuffer |
m_buffer->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) | vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst;
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | m_buffer->memory.property = vk::MemoryPropertyFlagBits::eHostVisible |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT; vk::MemoryPropertyFlagBits::eHostCoherent |
vk::MemoryPropertyFlagBits::eHostCached;
VulkanCreateBuffer(ctx, CAPACITY, m_buffer.get()); VulkanCreateBuffer(ctx, CAPACITY, m_buffer.get());
VulkanMapMemory(ctx, &m_buffer->memory, &m_mapped); VulkanMapMemory(ctx, &m_buffer->memory, &m_mapped);
const auto count = g_stream_buffer_count.fetch_add(1, std::memory_order_relaxed) + 1; const auto count = g_stream_buffer_count.fetch_add(1, std::memory_order_relaxed) + 1;
+39 -40
View File
@@ -251,7 +251,7 @@ VulkanImage* TextureCache::PublishImage(CommandBuffer* command,
image != nullptr ? static_cast<const void*>(image->image) : nullptr, image != nullptr ? static_cast<const void*>(image->image) : nullptr,
image != nullptr && image->registered); image != nullptr && image->registered);
} }
auto* result = image->image; auto result = image->image;
command->RetainResourceUntilFence(image); command->RetainResourceUntilFence(image);
m_images.push_back(std::move(image)); m_images.push_back(std::move(image));
RegisterImageLocked(*m_images.back()); RegisterImageLocked(*m_images.back());
@@ -397,10 +397,10 @@ struct TextureCache::ReadbackWorker {
size <= info.address + info.size - vaddr; size <= info.address + info.size - vaddr;
const bool d16 = const bool d16 =
info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) && info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) &&
info.format == VK_FORMAT_D16_UNORM && info.bytes_per_element == 2; info.format == vk::Format::eD16Unorm && info.bytes_per_element == 2;
const bool d32 = const bool d32 =
info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) && info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
info.format == VK_FORMAT_D32_SFLOAT && info.bytes_per_element == 4; info.format == vk::Format::eD32Sfloat && info.bytes_per_element == 4;
TileSizeAlign expected_stencil {}; TileSizeAlign expected_stencil {};
TileSizeAlign expected_htile {}; TileSizeAlign expected_htile {};
TileSizeAlign expected_depth {}; TileSizeAlign expected_depth {};
@@ -466,7 +466,7 @@ struct TextureCache::ReadbackWorker {
std::fill(download.begin(), download.end(), 0); std::fill(download.begin(), download.end(), 0);
const auto regions = const auto regions =
MakeLayeredImageBufferCopies(info.layers, slice_size, info.pitch, info.width, MakeLayeredImageBufferCopies(info.layers, slice_size, info.pitch, info.width,
info.height, VK_IMAGE_ASPECT_DEPTH_BIT); info.height, vk::ImageAspectFlagBits::eDepth);
UtilFillBuffer(cached.ctx, download.data(), info.size, regions, cached.image, UtilFillBuffer(cached.ctx, download.data(), info.size, regions, cached.image,
cached.image->layout); cached.image->layout);
guest.resize(info.size); guest.resize(info.size);
@@ -820,7 +820,7 @@ bool Equal(const DepthTargetInfo& left, const DepthTargetInfo& right) {
} }
void AppendLayerCopies(std::vector<ImageImageCopy>& regions, VulkanImage* source, void AppendLayerCopies(std::vector<ImageImageCopy>& regions, VulkanImage* source,
VkImageAspectFlags aspect) { vk::ImageAspectFlags aspect) {
for (uint32_t layer = 0; layer < source->layers; layer++) { for (uint32_t layer = 0; layer < source->layers; layer++) {
for (uint32_t level = 0; level < source->mip_levels; level++) { for (uint32_t level = 0; level < source->mip_levels; level++) {
ImageImageCopy region {}; ImageImageCopy region {};
@@ -1060,7 +1060,7 @@ void TextureCache::RetireStorageDepthAliasLocked(GraphicContext* ctx, const Imag
cached.ctx == ctx && cached.gpu_modified && !cached.buffer_modified && cached.ctx == ctx && cached.gpu_modified && !cached.buffer_modified &&
depth.address == requested.address && depth.size == requested.size && depth.address == requested.address && depth.size == requested.size &&
depth.stencil_address == 0 && depth.stencil_size == 0 && depth.htile_address == 0 && depth.stencil_address == 0 && depth.stencil_size == 0 && depth.htile_address == 0 &&
depth.htile_size == 0 && depth.layers == 1 && depth.format == VK_FORMAT_D32_SFLOAT && depth.htile_size == 0 && depth.layers == 1 && depth.format == vk::Format::eD32Sfloat &&
depth.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) && depth.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
depth.bytes_per_element == 4 && depth.width == requested.width && depth.bytes_per_element == 4 && depth.width == requested.width &&
depth.height == requested.height && depth.pitch == requested.pitch && depth.height == requested.height && depth.pitch == requested.pitch &&
@@ -1265,7 +1265,7 @@ VulkanImage* TextureCache::FindTexture(CommandBuffer* command, GraphicContext* c
cached->kind = CachedImage::Kind::Texture; cached->kind = CachedImage::Kind::Texture;
cached->info = info; cached->info = info;
cached->ctx = ctx; cached->ctx = ctx;
VkComponentMapping components {}; vk::ComponentMapping components {};
cached->image = ImageOps::CreateTexture(ctx, info, false, &cached->memory, &components); cached->image = ImageOps::CreateTexture(ctx, info, false, &cached->memory, &components);
m_memory_tracker.ForEachUploadRange( m_memory_tracker.ForEachUploadRange(
info.address, info.size, false, [](uint64_t, uint64_t) noexcept {}, info.address, info.size, false, [](uint64_t, uint64_t) noexcept {},
@@ -1401,7 +1401,7 @@ StorageTextureVulkanImage* TextureCache::FindStorageTexture(CommandBuffer* com
cached->kind = CachedImage::Kind::StorageTexture; cached->kind = CachedImage::Kind::StorageTexture;
cached->info = info; cached->info = info;
cached->ctx = ctx; cached->ctx = ctx;
VkComponentMapping components {}; vk::ComponentMapping components {};
cached->image = ImageOps::CreateTexture(ctx, info, true, &cached->memory, &components); cached->image = ImageOps::CreateTexture(ctx, info, true, &cached->memory, &components);
m_memory_tracker.ForEachUploadRange( m_memory_tracker.ForEachUploadRange(
info.address, info.size, true, [](uint64_t, uint64_t) noexcept {}, info.address, info.size, true, [](uint64_t, uint64_t) noexcept {},
@@ -1420,7 +1420,7 @@ RenderTextureVulkanImage* TextureCache::FindRenderTarget(CommandBuffer*
const RenderTargetInfo& info) { const RenderTargetInfo& info) {
const bool standard64 = IsSupportedStandard64RenderTarget(info); const bool standard64 = IsSupportedStandard64RenderTarget(info);
if (info.address == 0 || info.size == 0 || info.address >= TRACKER_ADDRESS_SIZE || if (info.address == 0 || info.size == 0 || info.address >= TRACKER_ADDRESS_SIZE ||
info.size > TRACKER_ADDRESS_SIZE - info.address || info.format == VK_FORMAT_UNDEFINED || info.size > TRACKER_ADDRESS_SIZE - info.address || info.format == vk::Format::eUndefined ||
info.width == 0 || info.height == 0 || info.pitch < info.width || info.width == 0 || info.height == 0 || info.pitch < info.width ||
info.bytes_per_element == 0 || info.levels == 0 || info.levels > 16 || info.layers == 0 || info.bytes_per_element == 0 || info.levels == 0 || info.levels > 16 || info.layers == 0 ||
info.size % info.layers != 0 || info.size % info.layers != 0 ||
@@ -1635,9 +1635,8 @@ RenderTextureVulkanImage* TextureCache::FindRenderTarget(CommandBuffer*
std::vector<ImageImageCopy> regions; std::vector<ImageImageCopy> regions;
regions.reserve(static_cast<size_t>(native_image_source->image->layers) * regions.reserve(static_cast<size_t>(native_image_source->image->layers) *
native_image_source->image->mip_levels); native_image_source->image->mip_levels);
AppendLayerCopies(regions, native_image_source->image, VK_IMAGE_ASPECT_COLOR_BIT); AppendLayerCopies(regions, native_image_source->image, vk::ImageAspectFlagBits::eColor);
UtilImageToImage(command, regions, cached->image, UtilImageToImage(command, regions, cached->image, RENDER_COLOR_IMAGE_LAYOUT);
static_cast<uint64_t>(RENDER_COLOR_IMAGE_LAYOUT));
} else { } else {
m_memory_tracker.ForEachUploadRange( m_memory_tracker.ForEachUploadRange(
info.address, info.size, false, [](uint64_t, uint64_t) noexcept {}, info.address, info.size, false, [](uint64_t, uint64_t) noexcept {},
@@ -1935,12 +1934,13 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
} }
std::vector<ImageImageCopy> regions; std::vector<ImageImageCopy> regions;
regions.reserve(native_depth_source->image->layers * (has_stencil ? 2u : 1u)); regions.reserve(native_depth_source->image->layers * (has_stencil ? 2u : 1u));
AppendLayerCopies(regions, native_depth_source->image, VK_IMAGE_ASPECT_DEPTH_BIT); AppendLayerCopies(regions, native_depth_source->image, vk::ImageAspectFlagBits::eDepth);
if (has_stencil) { if (has_stencil) {
AppendLayerCopies(regions, native_depth_source->image, VK_IMAGE_ASPECT_STENCIL_BIT); AppendLayerCopies(regions, native_depth_source->image,
vk::ImageAspectFlagBits::eStencil);
} }
UtilImageToImage(command, regions, cached->image, UtilImageToImage(command, regions, cached->image,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); vk::ImageLayout::eDepthStencilAttachmentOptimal);
cached->gpu_modified = true; cached->gpu_modified = true;
} else { } else {
if (sampled_depth_source != nullptr && if (sampled_depth_source != nullptr &&
@@ -1967,11 +1967,11 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
break; break;
case DepthTransitionSource::Native: case DepthTransitionSource::Native:
command->RetainResourceUntilFence(sampled_depth_source); command->RetainResourceUntilFence(sampled_depth_source);
UtilCopyImageWithBuffer( UtilCopyImageWithBuffer(command, ctx, sampled_depth_source->image,
command, ctx, sampled_depth_source->image, VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageAspectFlagBits::eColor, cached->image,
cached->image, VK_IMAGE_ASPECT_DEPTH_BIT, info.bytes_per_element, vk::ImageAspectFlagBits::eDepth,
static_cast<uint64_t>( info.bytes_per_element,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); vk::ImageLayout::eDepthStencilAttachmentOptimal);
break; break;
} }
}); });
@@ -2269,18 +2269,17 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer* command, uint64_t vaddr,
image_cpu_modified); image_cpu_modified);
} }
auto* vk_buffer = command->GetPool()->buffers[command->GetIndex()]; auto vk_buffer = command->GetPool()->buffers[command->GetIndex()];
if (aspect == ClearAspect::Color) { if (aspect == ClearAspect::Color) {
VkClearColorValue clear {}; vk::ClearColorValue clear {};
if (!DecodePackedColorClear(match->image->format, packed_clear, &clear)) { if (!DecodePackedColorClear(match->image->format, packed_clear, &clear)) {
return false; return false;
} }
GraphicsRenderColorImageBarrier(vk_buffer, match->image, GraphicsRenderColorImageBarrier(vk_buffer, match->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vk::ImageLayout::eTransferDstOptimal);
const VkImageSubresourceRange range {VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, const vk::ImageSubresourceRange range {vk::ImageAspectFlagBits::eColor, 0,
0, match->image->layers}; VK_REMAINING_MIP_LEVELS, 0, match->image->layers};
vkCmdClearColorImage(vk_buffer, match->image->image, match->image->layout, &clear, 1, vk_buffer.clearColorImage(match->image->image, match->image->layout, &clear, 1, &range);
&range);
GraphicsRenderColorImageBarrier(vk_buffer, match->image, RENDER_COLOR_IMAGE_LAYOUT); GraphicsRenderColorImageBarrier(vk_buffer, match->image, RENDER_COLOR_IMAGE_LAYOUT);
if (!match->gpu_modified) { if (!match->gpu_modified) {
m_memory_tracker.MarkRegionAsGpuModified(vaddr, size); m_memory_tracker.MarkRegionAsGpuModified(vaddr, size);
@@ -2290,22 +2289,22 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer* command, uint64_t vaddr,
return true; return true;
} }
if (match->image->layout == VK_IMAGE_LAYOUT_UNDEFINED || if (match->image->layout == vk::ImageLayout::eUndefined ||
match->image->layout == VK_IMAGE_LAYOUT_PREINITIALIZED) { match->image->layout == vk::ImageLayout::ePreinitialized) {
EXIT("TextureCache: compute %s clear has invalid source layout %u\n", EXIT("TextureCache: compute %s clear has invalid source layout %u\n",
aspect == ClearAspect::Depth ? "depth" : "stencil", aspect == ClearAspect::Depth ? "depth" : "stencil",
static_cast<uint32_t>(match->image->layout)); static_cast<uint32_t>(match->image->layout));
} }
const auto old_layout = match->image->layout; const auto old_layout = match->image->layout;
GraphicsRenderDepthStencilImageBarrier(vk_buffer, match->image, GraphicsRenderDepthStencilImageBarrier(vk_buffer, match->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vk::ImageLayout::eTransferDstOptimal);
const VkClearDepthStencilValue clear {depth_clear, stencil_clear}; const vk::ClearDepthStencilValue clear {depth_clear, stencil_clear};
const auto clear_aspect = static_cast<VkImageAspectFlags>( const auto clear_aspect = static_cast<vk::ImageAspectFlags>(
aspect == ClearAspect::Depth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT); aspect == ClearAspect::Depth ? vk::ImageAspectFlagBits::eDepth
const VkImageSubresourceRange range {clear_aspect, 0, VK_REMAINING_MIP_LEVELS, 0, : vk::ImageAspectFlagBits::eStencil);
match->image->layers}; const vk::ImageSubresourceRange range {clear_aspect, 0, VK_REMAINING_MIP_LEVELS, 0,
vkCmdClearDepthStencilImage(vk_buffer, match->image->image, match->image->layout, &clear, 1, match->image->layers};
&range); vk_buffer.clearDepthStencilImage(match->image->image, match->image->layout, &clear, 1, &range);
GraphicsRenderDepthStencilImageBarrier(vk_buffer, match->image, old_layout); GraphicsRenderDepthStencilImageBarrier(vk_buffer, match->image, old_layout);
if (aspect == ClearAspect::Stencil) { if (aspect == ClearAspect::Stencil) {
match->stencil_initialized = true; match->stencil_initialized = true;
@@ -2575,10 +2574,10 @@ void TextureCache::SynchronizeDepthImageToBufferLocked(CachedImage& cached, uint
TileSizeAlign expected_depth {}; TileSizeAlign expected_depth {};
const bool d16 = const bool d16 =
info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) && info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) &&
info.format == VK_FORMAT_D16_UNORM && info.bytes_per_element == 2; info.format == vk::Format::eD16Unorm && info.bytes_per_element == 2;
const bool d32 = const bool d32 =
info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) && info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
info.format == VK_FORMAT_D32_SFLOAT && info.bytes_per_element == 4; info.format == vk::Format::eD32Sfloat && info.bytes_per_element == 4;
const bool layout = const bool layout =
(d16 || d32) && (d16 || d32) &&
TileGetDepthSize(info.width, info.height, 0, TileGetDepthSize(info.width, info.height, 0,
@@ -2604,7 +2603,7 @@ void TextureCache::SynchronizeDepthImageToBufferLocked(CachedImage& cached, uint
m_buffer_transition_linear.resize(info.size); m_buffer_transition_linear.resize(info.size);
std::fill(m_buffer_transition_linear.begin(), m_buffer_transition_linear.end(), 0); std::fill(m_buffer_transition_linear.begin(), m_buffer_transition_linear.end(), 0);
const auto regions = MakeLayeredImageBufferCopies(1, info.size, info.pitch, info.width, const auto regions = MakeLayeredImageBufferCopies(1, info.size, info.pitch, info.width,
info.height, VK_IMAGE_ASPECT_DEPTH_BIT); info.height, vk::ImageAspectFlagBits::eDepth);
UtilFillBuffer(cached.ctx, m_buffer_transition_linear.data(), info.size, regions, cached.image, UtilFillBuffer(cached.ctx, m_buffer_transition_linear.data(), info.size, regions, cached.image,
cached.image->layout); cached.image->layout);
m_buffer_transition_guest.resize(info.size); m_buffer_transition_guest.resize(info.size);
+36 -38
View File
@@ -8,12 +8,12 @@
#include "graphics/host_gpu/renderer/imageInfo.h" #include "graphics/host_gpu/renderer/imageInfo.h"
#include "graphics/host_gpu/renderer/multiLevelPageTable.h" #include "graphics/host_gpu/renderer/multiLevelPageTable.h"
#include "graphics/host_gpu/renderer/tiler.h" #include "graphics/host_gpu/renderer/tiler.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <map> #include <map>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <vector> #include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -68,37 +68,35 @@ public:
bool formatted_buffer_write = false); bool formatted_buffer_write = false);
[[nodiscard]] RenderTextureVulkanImage* FindRenderTargetByRange(CommandBuffer* command, [[nodiscard]] RenderTextureVulkanImage* FindRenderTargetByRange(CommandBuffer* command,
uint64_t vaddr, uint64_t size); uint64_t vaddr, uint64_t size);
[[nodiscard]] VkImageView GetRenderTargetAttachmentView(GraphicContext* ctx, [[nodiscard]] vk::ImageView GetRenderTargetAttachmentView(GraphicContext* ctx,
RenderTextureVulkanImage* image, RenderTextureVulkanImage* image,
VkFormat format, uint32_t level, vk::Format format, uint32_t level,
uint32_t base_layer, uint32_t base_layer,
uint32_t layer_count); uint32_t layer_count);
[[nodiscard]] VkImageView GetDepthTargetAttachmentView(GraphicContext* ctx, [[nodiscard]] vk::ImageView GetDepthTargetAttachmentView(GraphicContext* ctx,
DepthStencilVulkanImage* image, DepthStencilVulkanImage* image,
uint32_t base_layer, uint32_t base_layer,
uint32_t layer_count); uint32_t layer_count);
[[nodiscard]] VkImageView GetDepthTargetSampledView(GraphicContext* ctx, [[nodiscard]] vk::ImageView
DepthStencilVulkanImage* image, GetDepthTargetSampledView(GraphicContext* ctx, DepthStencilVulkanImage* image,
VkFormat view_format, uint32_t swizzle, vk::Format view_format, uint32_t swizzle, uint32_t base_level,
uint32_t base_level, uint32_t level_count, uint32_t level_count, vk::ImageViewType type, uint32_t base_layer,
VkImageViewType type, uint32_t base_layer, uint32_t layer_count);
uint32_t layer_count); [[nodiscard]] vk::ImageView GetSampledColorView(GraphicContext* ctx, VulkanImage* image,
[[nodiscard]] VkImageView GetSampledColorView(GraphicContext* ctx, VulkanImage* image, vk::Format view_format, uint32_t swizzle,
VkFormat view_format, uint32_t swizzle, uint32_t base_level, uint32_t level_count,
uint32_t base_level, uint32_t level_count, vk::ImageViewType type, uint32_t base_layer,
VkImageViewType type, uint32_t base_layer, uint32_t layer_count);
uint32_t layer_count); [[nodiscard]] vk::ImageView
[[nodiscard]] VkImageView GetRenderTargetStorageView(GraphicContext* ctx, GetRenderTargetStorageView(GraphicContext* ctx, RenderTextureVulkanImage* image,
RenderTextureVulkanImage* image, vk::Format view_format, uint32_t base_level, uint32_t level_count,
VkFormat view_format, uint32_t base_level, vk::ImageViewType type, uint32_t base_layer, uint32_t layer_count);
uint32_t level_count, VkImageViewType type, [[nodiscard]] vk::ImageView GetStorageTextureSampledView(GraphicContext* ctx,
uint32_t base_layer, uint32_t layer_count); StorageTextureVulkanImage* image,
[[nodiscard]] VkImageView GetStorageTextureSampledView(GraphicContext* ctx, const ImageInfo& info);
StorageTextureVulkanImage* image, [[nodiscard]] vk::ImageView GetStorageTextureStorageView(GraphicContext* ctx,
const ImageInfo& info); StorageTextureVulkanImage* image,
[[nodiscard]] VkImageView GetStorageTextureStorageView(GraphicContext* ctx, uint32_t base_level);
StorageTextureVulkanImage* image,
uint32_t base_level);
[[nodiscard]] DepthStencilVulkanImage* [[nodiscard]] DepthStencilVulkanImage*
FindDepthTargetByRange(CommandBuffer* command, uint64_t vaddr, uint64_t size, FindDepthTargetByRange(CommandBuffer* command, uint64_t vaddr, uint64_t size,
bool allow_containing_sampled = false); bool allow_containing_sampled = false);
@@ -126,12 +124,12 @@ private:
uint32_t clear_mask = 0; uint32_t clear_mask = 0;
bool gpu_modified = false; bool gpu_modified = false;
}; };
[[nodiscard]] VkImageView GetImageView(GraphicContext* ctx, VulkanImage* image, [[nodiscard]] vk::ImageView GetImageView(GraphicContext* ctx, VulkanImage* image,
const ImageViewInfo& info); const ImageViewInfo& info);
[[nodiscard]] bool HasMetaOverlapLocked(uint64_t vaddr, uint64_t size) const; [[nodiscard]] bool HasMetaOverlapLocked(uint64_t vaddr, uint64_t size) const;
[[nodiscard]] CachedImage* FindGpuReadbackPageCandidateLocked(uint64_t vaddr, uint64_t size); [[nodiscard]] CachedImage* FindGpuReadbackPageCandidateLocked(uint64_t vaddr, uint64_t size);
void RequireNoMetaOverlapLocked(uint64_t vaddr, uint64_t size) const; void RequireNoMetaOverlapLocked(uint64_t vaddr, uint64_t size) const;
void MarkSampledAliasesCpuDirtyLocked(uint64_t vaddr, uint64_t size); void MarkSampledAliasesCpuDirtyLocked(uint64_t vaddr, uint64_t size);
void RetireSampledTargetAliases(GraphicContext* ctx, const ImageInfo& requested); void RetireSampledTargetAliases(GraphicContext* ctx, const ImageInfo& requested);
void ResolveStorageImageOverlaps(GraphicContext* ctx, const ImageInfo& requested); void ResolveStorageImageOverlaps(GraphicContext* ctx, const ImageInfo& requested);
void RetireStorageDepthAliasLocked(GraphicContext* ctx, const ImageInfo& requested); void RetireStorageDepthAliasLocked(GraphicContext* ctx, const ImageInfo& requested);
+9 -10
View File
@@ -45,11 +45,11 @@ static void UploadPromotedD16Depth(GraphicContext* ctx, DepthStencilVulkanImage*
region.width = info.width; region.width = info.width;
region.height = info.height; region.height = info.height;
region.dst_layer = base_layer + layer; region.dst_layer = base_layer + layer;
region.aspect = VK_IMAGE_ASPECT_DEPTH_BIT; region.aspect = vk::ImageAspectFlagBits::eDepth;
regions.push_back(region); regions.push_back(region);
} }
UtilFillImage(ctx, image, host_linear.Data(), host_upload_size, regions, UtilFillImage(ctx, image, host_linear.Data(), host_upload_size, regions,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); vk::ImageLayout::eDepthStencilAttachmentOptimal);
} }
void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info, void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info,
@@ -70,8 +70,7 @@ void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image, const
ctx, image, reinterpret_cast<const void*>(source.address), info.size, regions, layout, ctx, image, reinterpret_cast<const void*>(source.address), info.size, regions, layout,
info.format, info.width, info.height, info.depth, info.levels, slice_layout, info.format, info.width, info.height, info.depth, info.levels, slice_layout,
storage ? "StorageTextureCache" : "TextureCache", storage ? "StorageTextureCache" : "TextureCache",
static_cast<uint64_t>(storage ? VK_IMAGE_LAYOUT_GENERAL storage ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal);
: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
} }
void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image, void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
@@ -82,10 +81,10 @@ void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
} }
if (DepthAspectTransferBytes(info.format) != info.bytes_per_element) { if (DepthAspectTransferBytes(info.format) != info.bytes_per_element) {
switch (info.format) { switch (info.format) {
case VK_FORMAT_D24_UNORM_S8_UINT: case vk::Format::eD24UnormS8Uint:
UploadPromotedD16Depth<EncodeD16AsD24>(ctx, image, info, source, base_layer); UploadPromotedD16Depth<EncodeD16AsD24>(ctx, image, info, source, base_layer);
return; return;
case VK_FORMAT_D32_SFLOAT_S8_UINT: case vk::Format::eD32SfloatS8Uint:
UploadPromotedD16Depth<EncodeD16AsD32>(ctx, image, info, source, base_layer); UploadPromotedD16Depth<EncodeD16AsD32>(ctx, image, info, source, base_layer);
return; return;
default: default:
@@ -108,11 +107,11 @@ void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
region.width = info.width; region.width = info.width;
region.height = info.height; region.height = info.height;
region.dst_layer = base_layer + layer; region.dst_layer = base_layer + layer;
region.aspect = VK_IMAGE_ASPECT_DEPTH_BIT; region.aspect = vk::ImageAspectFlagBits::eDepth;
regions.push_back(region); regions.push_back(region);
} }
UtilFillImage(ctx, image, linear.Data(), info.size, regions, UtilFillImage(ctx, image, linear.Data(), info.size, regions,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); vk::ImageLayout::eDepthStencilAttachmentOptimal);
} }
void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image, void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
@@ -139,11 +138,11 @@ void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
region.width = info.width; region.width = info.width;
region.height = info.height; region.height = info.height;
region.dst_layer = base_layer + layer; region.dst_layer = base_layer + layer;
region.aspect = VK_IMAGE_ASPECT_STENCIL_BIT; region.aspect = vk::ImageAspectFlagBits::eStencil;
regions.push_back(region); regions.push_back(region);
} }
UtilFillImage(ctx, image, linear.Data(), info.stencil_size, regions, UtilFillImage(ctx, image, linear.Data(), info.stencil_size, regions,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); vk::ImageLayout::eDepthStencilAttachmentOptimal);
} }
void Tiler::TileImage(void* dst, const void* src, const RenderTargetInfo& info) const { void Tiler::TileImage(void* dst, const void* src, const RenderTargetInfo& info) const {
File diff suppressed because it is too large. Load diff
+60 -59
View File
@@ -3,11 +3,11 @@
#include "common/abi.h" #include "common/abi.h"
#include "common/common.h" #include "common/common.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <span> #include <span>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -20,55 +20,55 @@ struct DepthStencilVulkanImage;
struct VulkanSwapchain; struct VulkanSwapchain;
struct BufferImageCopy { struct BufferImageCopy {
uint32_t offset; uint32_t offset;
uint32_t pitch; uint32_t pitch;
uint32_t dst_level; uint32_t dst_level;
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
uint32_t copy_height = 0; uint32_t copy_height = 0;
uint32_t dst_layer = 0; uint32_t dst_layer = 0;
int dst_x; int dst_x;
int dst_y; int dst_y;
int dst_z = 0; int dst_z = 0;
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT; vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor;
}; };
struct ImageBufferCopy { struct ImageBufferCopy {
uint32_t offset; uint32_t offset;
uint32_t pitch; uint32_t pitch;
uint32_t src_level; uint32_t src_level;
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
uint32_t copy_height = 0; uint32_t copy_height = 0;
uint32_t src_layer = 0; uint32_t src_layer = 0;
int src_x; int src_x;
int src_y; int src_y;
int src_z = 0; int src_z = 0;
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT; vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor;
}; };
struct ImageImageCopy { struct ImageImageCopy {
VulkanImage* src_image; VulkanImage* src_image;
uint32_t src_level; uint32_t src_level;
uint32_t dst_level; uint32_t dst_level;
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
uint32_t src_layer = 0; uint32_t src_layer = 0;
uint32_t dst_layer = 0; uint32_t dst_layer = 0;
VkImageAspectFlags src_aspect = VK_IMAGE_ASPECT_COLOR_BIT; vk::ImageAspectFlags src_aspect = vk::ImageAspectFlagBits::eColor;
VkImageAspectFlags dst_aspect = VK_IMAGE_ASPECT_COLOR_BIT; vk::ImageAspectFlags dst_aspect = vk::ImageAspectFlagBits::eColor;
int src_x; int src_x;
int src_y; int src_y;
int src_z = 0; int src_z = 0;
int dst_x; int dst_x;
int dst_y; int dst_y;
int dst_z = 0; int dst_z = 0;
}; };
[[nodiscard]] std::vector<ImageBufferCopy> [[nodiscard]] std::vector<ImageBufferCopy>
MakeLayeredImageBufferCopies(uint32_t layers, uint64_t slice_size, uint32_t pitch, uint32_t width, MakeLayeredImageBufferCopies(uint32_t layers, uint64_t slice_size, uint32_t pitch, uint32_t width,
uint32_t height, uint32_t height,
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT); vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor);
enum class StagingBufferType { Texture, Vertex, ReadBack }; enum class StagingBufferType { Texture, Vertex, ReadBack };
@@ -85,28 +85,29 @@ private:
}; };
void UtilImageToImage(CommandBuffer* buffer, std::span<const ImageImageCopy> regions, void UtilImageToImage(CommandBuffer* buffer, std::span<const ImageImageCopy> regions,
VulkanImage* dst_image, uint64_t dst_layout); VulkanImage* dst_image, vk::ImageLayout dst_layout);
void UtilCopyImageWithBuffer(CommandBuffer* buffer, GraphicContext* ctx, VulkanImage* src_image, void UtilCopyImageWithBuffer(CommandBuffer* buffer, GraphicContext* ctx, VulkanImage* src_image,
VkImageAspectFlags src_aspect, VulkanImage* dst_image, vk::ImageAspectFlags src_aspect, VulkanImage* dst_image,
VkImageAspectFlags dst_aspect, uint32_t bytes_per_element, vk::ImageAspectFlags dst_aspect, uint32_t bytes_per_element,
uint64_t dst_layout); vk::ImageLayout dst_layout);
void UtilBlitPreparedImage(CommandBuffer* buffer, VulkanImage* src_image, void UtilBlitPreparedImage(CommandBuffer* buffer, VulkanImage* src_image,
VulkanSwapchain* dst_swapchain); VulkanSwapchain* dst_swapchain);
void UtilClearColorImage(CommandBuffer* buffer, VulkanImage* image, const VkClearColorValue& color); void UtilClearColorImage(CommandBuffer* buffer, VulkanImage* image,
const vk::ClearColorValue& color);
void UtilFillImage(GraphicContext* ctx, VulkanImage* dst_image, const void* src_data, uint64_t size, void UtilFillImage(GraphicContext* ctx, VulkanImage* dst_image, const void* src_data, uint64_t size,
uint32_t src_pitch, uint64_t dst_layout); uint32_t src_pitch, vk::ImageLayout dst_layout);
void UtilFillImage(GraphicContext* ctx, DepthStencilVulkanImage* dst_image, const void* src_data, void UtilFillImage(GraphicContext* ctx, DepthStencilVulkanImage* dst_image, const void* src_data,
uint64_t size, uint32_t src_pitch, VkImageAspectFlags aspect); uint64_t size, uint32_t src_pitch, vk::ImageAspectFlags aspect);
void UtilFillImage(GraphicContext* ctx, VulkanImage* dst_image, const void* src_data, uint64_t size, void UtilFillImage(GraphicContext* ctx, VulkanImage* dst_image, const void* src_data, uint64_t size,
std::span<const BufferImageCopy> regions, uint64_t dst_layout); std::span<const BufferImageCopy> regions, vk::ImageLayout dst_layout);
void UtilFillImage(GraphicContext* ctx, std::span<const ImageImageCopy> regions, void UtilFillImage(GraphicContext* ctx, std::span<const ImageImageCopy> regions,
VulkanImage* dst_image, uint64_t dst_layout); VulkanImage* dst_image, vk::ImageLayout dst_layout);
void UtilFillBuffer(GraphicContext* ctx, void* dst_data, uint64_t size, uint32_t dst_pitch, void UtilFillBuffer(GraphicContext* ctx, void* dst_data, uint64_t size, uint32_t dst_pitch,
VulkanImage* src_image, uint64_t src_layout, VulkanImage* src_image, vk::ImageLayout src_layout,
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT); vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor);
void UtilFillBuffer(GraphicContext* ctx, void* dst_data, uint64_t size, void UtilFillBuffer(GraphicContext* ctx, void* dst_data, uint64_t size,
std::span<const ImageBufferCopy> regions, VulkanImage* src_image, std::span<const ImageBufferCopy> regions, VulkanImage* src_image,
uint64_t src_layout); vk::ImageLayout src_layout);
void UtilUploadBuffer(GraphicContext* ctx, StagingBufferType type, VulkanBuffer* dst_buffer, void UtilUploadBuffer(GraphicContext* ctx, StagingBufferType type, VulkanBuffer* dst_buffer,
uint64_t dst_offset, const void* src_data, uint64_t size); uint64_t dst_offset, const void* src_data, uint64_t size);
void UtilReleaseCachedResources(GraphicContext* ctx); void UtilReleaseCachedResources(GraphicContext* ctx);
@@ -117,17 +118,17 @@ bool UtilBufferIsTiled(uint64_t vaddr, uint64_t size);
void UtilSetImageLayoutOptimal(VulkanImage* image); void UtilSetImageLayoutOptimal(VulkanImage* image);
void UtilResetImageViews(VulkanImage* image); void UtilResetImageViews(VulkanImage* image);
void UtilCreateImageView(GraphicContext* ctx, VulkanImage* image, int view_index, void UtilCreateImageView(GraphicContext* ctx, VulkanImage* image, int view_index,
VkImageViewType view_type, VkImageAspectFlags aspect_mask, vk::ImageViewType view_type, vk::ImageAspectFlags aspect_mask,
VkComponentMapping components, uint32_t base_array_layer, vk::ComponentMapping components, uint32_t base_array_layer,
uint32_t base_mip_level, uint32_t layer_count, uint32_t level_count, uint32_t base_mip_level, uint32_t layer_count, uint32_t level_count,
VkFormat view_format = VK_FORMAT_UNDEFINED, vk::Format view_format = vk::Format::eUndefined,
VkImageUsageFlags view_usage = 0); vk::ImageUsageFlags view_usage = {});
bool UtilIsBcFormat(VkFormat format); bool UtilIsBcFormat(vk::Format format);
uint32_t UtilGetBcBlockSize(VkFormat format); uint32_t UtilGetBcBlockSize(vk::Format format);
void VulkanCreateBuffer(GraphicContext* gctx, uint64_t size, VulkanBuffer* buffer); void VulkanCreateBuffer(GraphicContext* gctx, uint64_t size, VulkanBuffer* buffer);
void VulkanDeleteBuffer(GraphicContext* gctx, VulkanBuffer* buffer); void VulkanDeleteBuffer(GraphicContext* gctx, VulkanBuffer* buffer);
bool VulkanCreateImage(GraphicContext* gctx, const VkImageCreateInfo* image_info, bool VulkanCreateImage(GraphicContext* gctx, const vk::ImageCreateInfo* image_info,
VulkanImage* image, VulkanMemory* memory); VulkanImage* image, VulkanMemory* memory);
void VulkanDeleteImage(GraphicContext* gctx, VulkanImage* image, VulkanMemory* memory); void VulkanDeleteImage(GraphicContext* gctx, VulkanImage* image, VulkanMemory* memory);
void VulkanDeviceWaitIdle(GraphicContext* ctx); void VulkanDeviceWaitIdle(GraphicContext* ctx);
+25 -14
View File
@@ -1,3 +1,5 @@
#include "graphics/host_gpu/vulkanCommon.h"
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnullability-completeness" #pragma clang diagnostic ignored "-Wnullability-completeness"
@@ -24,7 +26,6 @@
#include <fmt/format.h> #include <fmt/format.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -66,16 +67,21 @@ bool VulkanCreateAllocator(GraphicContext* ctx) {
EXIT_IF(ctx == nullptr || ctx->instance == nullptr || ctx->physical_device == nullptr || EXIT_IF(ctx == nullptr || ctx->instance == nullptr || ctx->physical_device == nullptr ||
ctx->device == nullptr || ctx->allocator != nullptr); ctx->device == nullptr || ctx->allocator != nullptr);
VmaVulkanFunctions functions {};
functions.vkGetInstanceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetInstanceProcAddr;
functions.vkGetDeviceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetDeviceProcAddr;
VmaAllocatorCreateInfo info {}; VmaAllocatorCreateInfo info {};
info.instance = ctx->instance; info.instance = ctx->instance;
info.physicalDevice = ctx->physical_device; info.physicalDevice = ctx->physical_device;
info.device = ctx->device; info.device = ctx->device;
info.pVulkanFunctions = &functions;
info.vulkanApiVersion = VULKAN_TARGET_API_VERSION; info.vulkanApiVersion = VULKAN_TARGET_API_VERSION;
info.flags = ctx->memory_budget_ext_enabled ? VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT : 0; info.flags = ctx->memory_budget_ext_enabled ? VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT : 0;
const auto result = vmaCreateAllocator(&info, &ctx->allocator); const auto result = static_cast<vk::Result>(vmaCreateAllocator(&info, &ctx->allocator));
if (result != VK_SUCCESS) { if (result != vk::Result::eSuccess) {
LOGF("vmaCreateAllocator failed: %s\n", string_VkResult(result)); LOGF("vmaCreateAllocator failed: %s\n", VulkanToString(result).c_str());
return false; return false;
} }
return true; return true;
@@ -127,11 +133,13 @@ bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* memory) {
} }
VmaAllocationCreateInfo info {}; VmaAllocationCreateInfo info {};
info.requiredFlags = memory->property; info.requiredFlags = static_cast<vk::MemoryPropertyFlags::MaskType>(memory->property);
memory->unique_id = VulkanNextMemoryUniqueId(); memory->unique_id = VulkanNextMemoryUniqueId();
const auto result = vmaAllocateMemory(ctx->allocator, &memory->requirements, &info, const auto result = static_cast<vk::Result>(vmaAllocateMemory(
&memory->allocation, &memory->allocation_info); ctx->allocator,
if (result == VK_SUCCESS) { static_cast<const vk::MemoryRequirements::NativeType*>(memory->requirements), &info,
&memory->allocation, &memory->allocation_info));
if (result == vk::Result::eSuccess) {
memory->type = memory->allocation_info.memoryType; memory->type = memory->allocation_info.memoryType;
memory->memory = memory->allocation_info.deviceMemory; memory->memory = memory->allocation_info.deviceMemory;
memory->offset = memory->allocation_info.offset; memory->offset = memory->allocation_info.offset;
@@ -146,7 +154,7 @@ bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* memory) {
g_memory_stats.allocated[i].load())); g_memory_stats.allocated[i].load()));
} }
EXIT("size = %" PRIu64 ", index = %u, error: %s:%s\n", memory->requirements.size, index, EXIT("size = %" PRIu64 ", index = %u, error: %s:%s\n", memory->requirements.size, index,
string_VkResult(result), Common::Concat(stats, '\n').c_str()); VulkanToString(result).c_str(), Common::Concat(stats, '\n').c_str());
return false; return false;
} }
@@ -166,7 +174,8 @@ void VulkanMapMemory(GraphicContext* ctx, VulkanMemory* memory, void** data) {
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
EXIT_IF(ctx == nullptr || memory == nullptr || data == nullptr || ctx->allocator == nullptr || EXIT_IF(ctx == nullptr || memory == nullptr || data == nullptr || ctx->allocator == nullptr ||
memory->allocation == nullptr); memory->allocation == nullptr);
EXIT_NOT_IMPLEMENTED(vmaMapMemory(ctx->allocator, memory->allocation, data) != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(static_cast<vk::Result>(vmaMapMemory(ctx->allocator, memory->allocation,
data)) != vk::Result::eSuccess);
} }
void VulkanUnmapMemory(GraphicContext* ctx, VulkanMemory* memory) { void VulkanUnmapMemory(GraphicContext* ctx, VulkanMemory* memory) {
@@ -180,16 +189,18 @@ void VulkanBindImageMemory(GraphicContext* ctx, VulkanImage* image, VulkanMemory
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
EXIT_IF(ctx == nullptr || image == nullptr || memory == nullptr || ctx->allocator == nullptr || EXIT_IF(ctx == nullptr || image == nullptr || memory == nullptr || ctx->allocator == nullptr ||
memory->allocation == nullptr); memory->allocation == nullptr);
EXIT_NOT_IMPLEMENTED(vmaBindImageMemory(ctx->allocator, memory->allocation, image->image) != EXIT_NOT_IMPLEMENTED(
VK_SUCCESS); static_cast<vk::Result>(vmaBindImageMemory(ctx->allocator, memory->allocation,
image->image)) != vk::Result::eSuccess);
} }
void VulkanBindBufferMemory(GraphicContext* ctx, VulkanBuffer* buffer, VulkanMemory* memory) { void VulkanBindBufferMemory(GraphicContext* ctx, VulkanBuffer* buffer, VulkanMemory* memory) {
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
EXIT_IF(ctx == nullptr || buffer == nullptr || memory == nullptr || ctx->allocator == nullptr || EXIT_IF(ctx == nullptr || buffer == nullptr || memory == nullptr || ctx->allocator == nullptr ||
memory->allocation == nullptr); memory->allocation == nullptr);
EXIT_NOT_IMPLEMENTED(vmaBindBufferMemory(ctx->allocator, memory->allocation, buffer->buffer) != EXIT_NOT_IMPLEMENTED(
VK_SUCCESS); static_cast<vk::Result>(vmaBindBufferMemory(ctx->allocator, memory->allocation,
buffer->buffer)) != vk::Result::eSuccess);
} }
} // namespace Libs::Graphics } // namespace Libs::Graphics
+23
View File
@@ -0,0 +1,23 @@
#include "graphics/host_gpu/vulkanCommon.h"
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
namespace Libs::Graphics {
std::string VulkanToString(vk::Result value) {
return vk::to_string(value);
}
std::string VulkanToString(vk::Format value) {
return vk::to_string(value);
}
std::string VulkanToString(vk::ImageLayout value) {
return vk::to_string(value);
}
std::string VulkanToString(vk::QueueFlags value) {
return vk::to_string(value);
}
} // namespace Libs::Graphics
+33
View File
@@ -0,0 +1,33 @@
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_VULKANCOMMON_H_
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_VULKANCOMMON_H_
#define VK_NO_PROTOTYPES
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
#define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 1
#define VULKAN_HPP_NO_CONSTRUCTORS
#define VULKAN_HPP_NO_EXCEPTIONS
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#include <string>
#include <vulkan/vulkan.hpp>
#include <vulkan/vulkan_hash.hpp>
namespace Libs::Graphics {
using VulkanMemoryBarrier = vk::MemoryBarrier;
template <typename Handle>
[[nodiscard]] void* VulkanHandleToPointer(Handle handle) {
return reinterpret_cast<void*>(static_cast<typename Handle::CType>(handle));
}
std::string VulkanToString(vk::Result value);
std::string VulkanToString(vk::Format value);
std::string VulkanToString(vk::ImageLayout value);
std::string VulkanToString(vk::QueueFlags value);
} // namespace Libs::Graphics
#endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_VULKANCOMMON_H_
+37 -35
View File
@@ -4,12 +4,12 @@
#include "common/abi.h" #include "common/abi.h"
#include "common/common.h" #include "common/common.h"
#include "common/threads.h" #include "common/threads.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <map> #include <map>
#include <mutex> #include <mutex>
#include <tuple> #include <tuple>
#include <vk_mem_alloc.h> #include <vk_mem_alloc.h>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -19,7 +19,7 @@ struct VulkanQueueInfo {
Common::Mutex* mutex = nullptr; Common::Mutex* mutex = nullptr;
uint32_t family = static_cast<uint32_t>(-1); uint32_t family = static_cast<uint32_t>(-1);
uint32_t index = static_cast<uint32_t>(-1); uint32_t index = static_cast<uint32_t>(-1);
VkQueue vk_queue = nullptr; vk::Queue vk_queue = nullptr;
}; };
struct VulkanInstance { struct VulkanInstance {
@@ -33,51 +33,53 @@ struct VulkanInstance {
static constexpr int QUEUE_COMPUTE_START = 0; static constexpr int QUEUE_COMPUTE_START = 0;
static constexpr int QUEUE_COMPUTE_NUM = 8; static constexpr int QUEUE_COMPUTE_NUM = 8;
VkInstance instance = nullptr; vk::Instance instance = nullptr;
VkDebugUtilsMessengerEXT debug_messenger = nullptr; vk::DebugUtilsMessengerEXT debug_messenger = nullptr;
VkPhysicalDevice physical_device = nullptr; vk::PhysicalDevice physical_device = nullptr;
VkPhysicalDeviceProperties physical_device_properties = {}; vk::PhysicalDeviceProperties physical_device_properties = {};
VkPhysicalDeviceMemoryProperties physical_device_memory_properties = {}; vk::PhysicalDeviceMemoryProperties physical_device_memory_properties = {};
VkDevice device = nullptr; vk::Device device = nullptr;
VmaAllocator allocator = nullptr; VmaAllocator allocator = nullptr;
bool memory_budget_ext_enabled = false; bool memory_budget_ext_enabled = false;
bool subgroup_size_control_enabled = false; bool rt_extensions_enabled = false;
uint32_t subgroup_size = 0; bool subgroup_size_control_enabled = false;
uint32_t min_subgroup_size = 0; uint32_t subgroup_size = 0;
uint32_t max_subgroup_size = 0; uint32_t min_subgroup_size = 0;
VkShaderStageFlags required_subgroup_size_stages = 0; uint32_t max_subgroup_size = 0;
VulkanQueueInfo queues[QUEUES_NUM]; vk::ShaderStageFlags required_subgroup_size_stages = {};
VulkanQueueInfo queues[QUEUES_NUM];
[[nodiscard]] const VkPhysicalDeviceProperties& GetPhysicalDeviceProperties() const { [[nodiscard]] const vk::PhysicalDeviceProperties& GetPhysicalDeviceProperties() const {
return physical_device_properties; return physical_device_properties;
} }
[[nodiscard]] const VkPhysicalDeviceMemoryProperties& [[nodiscard]] const vk::PhysicalDeviceMemoryProperties&
GetPhysicalDeviceMemoryProperties() const { GetPhysicalDeviceMemoryProperties() const {
return physical_device_memory_properties; return physical_device_memory_properties;
} }
[[nodiscard]] VkFormatProperties GetFormatProperties(VkFormat format) const { [[nodiscard]] vk::FormatProperties GetFormatProperties(vk::Format format) const {
std::scoped_lock lock(m_format_properties_mutex); std::scoped_lock lock(m_format_properties_mutex);
auto [it, inserted] = m_format_properties.try_emplace(format); auto [it, inserted] = m_format_properties.try_emplace(format);
if (inserted) { if (inserted) {
vkGetPhysicalDeviceFormatProperties(physical_device, format, &it->second); physical_device.getFormatProperties(format, &it->second);
} }
return it->second; return it->second;
} }
[[nodiscard]] VkResult GetImageFormatProperties(VkFormat format, VkImageType type, [[nodiscard]] vk::Result GetImageFormatProperties(vk::Format format, vk::ImageType type,
VkImageTiling tiling, VkImageUsageFlags usage, vk::ImageTiling tiling,
VkImageCreateFlags flags, vk::ImageUsageFlags usage,
VkImageFormatProperties* properties) const { vk::ImageCreateFlags flags,
using Key = vk::ImageFormatProperties* properties) const {
std::tuple<VkFormat, VkImageType, VkImageTiling, VkImageUsageFlags, VkImageCreateFlags>; using Key = std::tuple<vk::Format, vk::ImageType, vk::ImageTiling, vk::ImageUsageFlags,
vk::ImageCreateFlags>;
std::scoped_lock lock(m_image_format_properties_mutex); std::scoped_lock lock(m_image_format_properties_mutex);
auto [it, inserted] = auto [it, inserted] =
m_image_format_properties.try_emplace(Key {format, type, tiling, usage, flags}); m_image_format_properties.try_emplace(Key {format, type, tiling, usage, flags});
if (inserted) { if (inserted) {
it->second.first = vkGetPhysicalDeviceImageFormatProperties( it->second.first = physical_device.getImageFormatProperties(format, type, tiling, usage,
physical_device, format, type, tiling, usage, flags, &it->second.second); flags, &it->second.second);
} }
if (properties != nullptr) { if (properties != nullptr) {
*properties = it->second.second; *properties = it->second.second;
@@ -85,18 +87,18 @@ struct VulkanInstance {
return it->second.first; return it->second.first;
} }
[[nodiscard]] VkDeviceSize StorageMinAlignment() const { [[nodiscard]] vk::DeviceSize StorageMinAlignment() const {
const auto alignment = physical_device_properties.limits.minStorageBufferOffsetAlignment; const auto alignment = physical_device_properties.limits.minStorageBufferOffsetAlignment;
return alignment != 0 ? alignment : 1; return alignment != 0 ? alignment : 1;
} }
private: private:
mutable std::mutex m_format_properties_mutex; mutable std::mutex m_format_properties_mutex;
mutable std::map<VkFormat, VkFormatProperties> m_format_properties; mutable std::map<vk::Format, vk::FormatProperties> m_format_properties;
mutable std::mutex m_image_format_properties_mutex; mutable std::mutex m_image_format_properties_mutex;
mutable std::map< mutable std::map<std::tuple<vk::Format, vk::ImageType, vk::ImageTiling, vk::ImageUsageFlags,
std::tuple<VkFormat, VkImageType, VkImageTiling, VkImageUsageFlags, VkImageCreateFlags>, vk::ImageCreateFlags>,
std::pair<VkResult, VkImageFormatProperties>> std::pair<vk::Result, vk::ImageFormatProperties>>
m_image_format_properties; m_image_format_properties;
}; };
+4 -4
View File
@@ -99,12 +99,12 @@ static std::atomic<RenderDocState> g_state = RenderDocState::Idle;
static std::atomic_bool g_init_done = false; static std::atomic_bool g_init_done = false;
static std::atomic_bool g_unavailable_log = false; static std::atomic_bool g_unavailable_log = false;
static RenderDocDevicePointer GetRenderDocDevicePointer(VkInstance instance) { static RenderDocDevicePointer GetRenderDocDevicePointer(vk::Instance instance) {
if (instance == nullptr) { if (instance == nullptr) {
return nullptr; return nullptr;
} }
return reinterpret_cast<void*>(instance); return VulkanHandleToPointer(instance);
} }
static bool BindRenderDocApi(HMODULE module) { static bool BindRenderDocApi(HMODULE module) {
@@ -191,7 +191,7 @@ bool RenderDocIsLoaded() {
return g_api != nullptr; return g_api != nullptr;
} }
void RenderDocSetActiveWindow(VkInstance instance, SDL_Window* window) { void RenderDocSetActiveWindow(vk::Instance instance, SDL_Window* window) {
if (g_api == nullptr) { if (g_api == nullptr) {
return; return;
} }
@@ -284,7 +284,7 @@ void RenderDocInit() {}
bool RenderDocIsLoaded() { bool RenderDocIsLoaded() {
return false; return false;
} }
void RenderDocSetActiveWindow(VkInstance /*instance*/, SDL_Window* /*window*/) {} void RenderDocSetActiveWindow(vk::Instance /*instance*/, SDL_Window* /*window*/) {}
void RenderDocRequestCapture() {} void RenderDocRequestCapture() {}
void RenderDocOnPresent() {} void RenderDocOnPresent() {}
+2 -3
View File
@@ -2,8 +2,7 @@
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_RENDERDOC_H_ #define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_RENDERDOC_H_
#include "common/common.h" #include "common/common.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <vulkan/vulkan_core.h>
struct SDL_Window; struct SDL_Window;
@@ -11,7 +10,7 @@ namespace Libs::Graphics {
void RenderDocInit(); void RenderDocInit();
bool RenderDocIsLoaded(); bool RenderDocIsLoaded();
void RenderDocSetActiveWindow(VkInstance instance, SDL_Window* window); void RenderDocSetActiveWindow(vk::Instance instance, SDL_Window* window);
void RenderDocRequestCapture(); void RenderDocRequestCapture();
void RenderDocOnPresent(); void RenderDocOnPresent();
+2 -3
View File
@@ -3,8 +3,7 @@
#include "common/abi.h" #include "common/abi.h"
#include "common/common.h" #include "common/common.h"
#include "graphics/host_gpu/vulkanCommon.h"
struct VkSurfaceCapabilitiesKHR;
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -13,7 +12,7 @@ class CommandBuffer;
struct VideoOutVulkanImage; struct VideoOutVulkanImage;
struct PreparedFrame; struct PreparedFrame;
VkSurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities(); vk::SurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities();
GraphicContext* WindowGetGraphicContext(); GraphicContext* WindowGetGraphicContext();
+103 -98
View File
@@ -31,6 +31,7 @@
#include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h" #include "graphics/host_gpu/vma.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/renderDoc.h" #include "graphics/presentation/renderDoc.h"
#include "graphics/presentation/videoOut.h" #include "graphics/presentation/videoOut.h"
#include "graphics/presentation/window.h" #include "graphics/presentation/window.h"
@@ -48,7 +49,6 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include <vulkan/vk_enum_string_helper.h>
#include <vulkan/vk_platform.h> #include <vulkan/vk_platform.h>
// IWYU pragma: no_include <intrin.h> // IWYU pragma: no_include <intrin.h>
@@ -66,8 +66,8 @@ struct PreparedFrame {
class PreparedFramePool { class PreparedFramePool {
public: public:
void EnsureCapacity(uint32_t count, VkFormat format) { void EnsureCapacity(uint32_t count, vk::Format format) {
if (count == 0 || format == VK_FORMAT_UNDEFINED) { if (count == 0 || format == vk::Format::eUndefined) {
EXIT("prepared-frame pool requires at least one frame\n"); EXIT("prepared-frame pool requires at least one frame\n");
} }
Common::LockGuard lock(m_mutex); Common::LockGuard lock(m_mutex);
@@ -79,9 +79,9 @@ public:
} }
} }
VkFormat GetFormat() { vk::Format GetFormat() {
Common::LockGuard lock(m_mutex); Common::LockGuard lock(m_mutex);
if (m_format == VK_FORMAT_UNDEFINED) { if (m_format == vk::Format::eUndefined) {
EXIT("prepared-frame pool has no presentation format\n"); EXIT("prepared-frame pool has no presentation format\n");
} }
return m_format; return m_format;
@@ -130,7 +130,7 @@ private:
Common::CondVar m_available; Common::CondVar m_available;
std::vector<std::unique_ptr<PreparedFrame>> m_frames; std::vector<std::unique_ptr<PreparedFrame>> m_frames;
std::deque<PreparedFrame*> m_free; std::deque<PreparedFrame*> m_free;
VkFormat m_format = VK_FORMAT_UNDEFINED; vk::Format m_format = vk::Format::eUndefined;
}; };
static PreparedFramePool* GetPreparedFramePool() { static PreparedFramePool* GetPreparedFramePool() {
@@ -138,10 +138,10 @@ static PreparedFramePool* GetPreparedFramePool() {
return pool; return pool;
} }
static void ConfigurePreparedFrame(PreparedFrame* frame, VkExtent2D extent, VkFormat format) { static void ConfigurePreparedFrame(PreparedFrame* frame, vk::Extent2D extent, vk::Format format) {
EXIT_IF(frame == nullptr); EXIT_IF(frame == nullptr);
EXIT_IF(g_window_ctx == nullptr); EXIT_IF(g_window_ctx == nullptr);
if (extent.width == 0 || extent.height == 0 || format == VK_FORMAT_UNDEFINED) { if (extent.width == 0 || extent.height == 0 || format == vk::Format::eUndefined) {
EXIT("unsupported prepared frame, extent=%ux%u format=%d\n", extent.width, extent.height, EXIT("unsupported prepared frame, extent=%ux%u format=%d\n", extent.width, extent.height,
static_cast<int>(format)); static_cast<int>(format));
} }
@@ -163,21 +163,21 @@ static void ConfigurePreparedFrame(PreparedFrame* frame, VkExtent2D extent, VkFo
dst.format = format; dst.format = format;
dst.layers = 1; dst.layers = 1;
dst.mip_levels = 1; dst.mip_levels = 1;
dst.layout = VK_IMAGE_LAYOUT_UNDEFINED; dst.layout = vk::ImageLayout::eUndefined;
dst.memory.property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; dst.memory.property = vk::MemoryPropertyFlagBits::eDeviceLocal;
VkImageCreateInfo create {}; vk::ImageCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; create.sType = vk::StructureType::eImageCreateInfo;
create.imageType = VK_IMAGE_TYPE_2D; create.imageType = vk::ImageType::e2D;
create.extent = {dst.extent.width, dst.extent.height, 1}; create.extent = {dst.extent.width, dst.extent.height, 1};
create.mipLevels = 1; create.mipLevels = 1;
create.arrayLayers = 1; create.arrayLayers = 1;
create.format = dst.format; create.format = dst.format;
create.tiling = VK_IMAGE_TILING_OPTIMAL; create.tiling = vk::ImageTiling::eOptimal;
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; create.initialLayout = vk::ImageLayout::eUndefined;
create.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; create.usage = vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst;
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE; create.sharingMode = vk::SharingMode::eExclusive;
create.samples = VK_SAMPLE_COUNT_1_BIT; create.samples = vk::SampleCountFlagBits::e1;
if (!VulkanCreateImage(ctx, &create, &dst, &dst.memory)) { if (!VulkanCreateImage(ctx, &create, &dst, &dst.memory)) {
EXIT("failed to allocate prepared presentation image, extent=%ux%u format=%d\n", EXIT("failed to allocate prepared presentation image, extent=%ux%u format=%d\n",
dst.extent.width, dst.extent.height, static_cast<int>(dst.format)); dst.extent.width, dst.extent.height, static_cast<int>(dst.format));
@@ -186,11 +186,11 @@ static void ConfigurePreparedFrame(PreparedFrame* frame, VkExtent2D extent, VkFo
VulkanSwapchain::~VulkanSwapchain() = default; VulkanSwapchain::~VulkanSwapchain() = default;
[[maybe_unused]] static VkSwapchainKHR VulkanCreateSwapchainInternal( [[maybe_unused]] static vk::SwapchainKHR VulkanCreateSwapchainInternal(
VkDevice device, VkSurfaceKHR surface, uint32_t width, uint32_t height, uint32_t image_count, vk::Device device, vk::SurfaceKHR surface, uint32_t width, uint32_t height,
SurfaceCapabilities* r, VkFormat* swapchain_format, VkExtent2D* swapchain_extent, uint32_t image_count, SurfaceCapabilities* r, vk::Format* swapchain_format,
std::unique_ptr<VkImage[]>* swapchain_images, vk::Extent2D* swapchain_extent, std::unique_ptr<vk::Image[]>* swapchain_images,
std::unique_ptr<VkImageView[]>* swapchain_image_views, uint32_t* swapchain_images_count) { std::unique_ptr<vk::ImageView[]>* swapchain_image_views, uint32_t* swapchain_images_count) {
EXIT_IF(device == nullptr); EXIT_IF(device == nullptr);
EXIT_IF(surface == nullptr); EXIT_IF(surface == nullptr);
EXIT_IF(r == nullptr); EXIT_IF(r == nullptr);
@@ -202,7 +202,7 @@ VulkanSwapchain::~VulkanSwapchain() = default;
EXIT_NOT_IMPLEMENTED(r->formats.empty()); EXIT_NOT_IMPLEMENTED(r->formats.empty());
VkExtent2D extent {}; vk::Extent2D extent {};
extent.width = std::clamp(width, r->capabilities.minImageExtent.width, extent.width = std::clamp(width, r->capabilities.minImageExtent.width,
r->capabilities.maxImageExtent.width); r->capabilities.maxImageExtent.width);
extent.height = std::clamp(height, r->capabilities.minImageExtent.height, extent.height = std::clamp(height, r->capabilities.minImageExtent.height,
@@ -211,19 +211,19 @@ VulkanSwapchain::~VulkanSwapchain() = default;
image_count = image_count =
std::clamp(image_count, r->capabilities.minImageCount, r->capabilities.maxImageCount); std::clamp(image_count, r->capabilities.minImageCount, r->capabilities.maxImageCount);
VkSwapchainCreateInfoKHR create_info {}; vk::SwapchainCreateInfoKHR create_info {};
create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; create_info.sType = vk::StructureType::eSwapchainCreateInfoKHR;
create_info.pNext = nullptr; create_info.pNext = nullptr;
create_info.flags = 0; create_info.flags = {};
create_info.surface = surface; create_info.surface = surface;
create_info.minImageCount = image_count; create_info.minImageCount = image_count;
if (r->format_unorm_bgra32) { if (r->format_unorm_bgra32) {
create_info.imageFormat = VK_FORMAT_B8G8R8A8_UNORM; create_info.imageFormat = vk::Format::eB8G8R8A8Unorm;
create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; create_info.imageColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
} else if (r->format_srgb_bgra32) { } else if (r->format_srgb_bgra32) {
create_info.imageFormat = VK_FORMAT_B8G8R8A8_SRGB; create_info.imageFormat = vk::Format::eB8G8R8A8Srgb;
create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; create_info.imageColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
} else { } else {
const auto& format = r->formats[0]; const auto& format = r->formats[0];
create_info.imageFormat = format.format; create_info.imageFormat = format.format;
@@ -232,49 +232,50 @@ VulkanSwapchain::~VulkanSwapchain() = default;
create_info.imageExtent = extent; create_info.imageExtent = extent;
create_info.imageArrayLayers = 1; create_info.imageArrayLayers = 1;
create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; create_info.imageUsage =
create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferDst;
create_info.imageSharingMode = vk::SharingMode::eExclusive;
create_info.queueFamilyIndexCount = 0; create_info.queueFamilyIndexCount = 0;
create_info.pQueueFamilyIndices = nullptr; create_info.pQueueFamilyIndices = nullptr;
create_info.preTransform = r->capabilities.currentTransform; create_info.preTransform = r->capabilities.currentTransform;
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; create_info.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR; create_info.presentMode = vk::PresentModeKHR::eFifo;
create_info.clipped = VK_TRUE; create_info.clipped = VK_TRUE;
create_info.oldSwapchain = nullptr; create_info.oldSwapchain = nullptr;
*swapchain_format = create_info.imageFormat; *swapchain_format = create_info.imageFormat;
*swapchain_extent = extent; *swapchain_extent = extent;
VkSwapchainKHR swapchain = nullptr; vk::SwapchainKHR swapchain = nullptr;
vkCreateSwapchainKHR(device, &create_info, nullptr, &swapchain); device.createSwapchainKHR(&create_info, nullptr, &swapchain);
vkGetSwapchainImagesKHR(device, swapchain, swapchain_images_count, nullptr); device.getSwapchainImagesKHR(swapchain, swapchain_images_count, nullptr);
EXIT_NOT_IMPLEMENTED(*swapchain_images_count == 0); EXIT_NOT_IMPLEMENTED(*swapchain_images_count == 0);
*swapchain_images = std::make_unique<VkImage[]>(*swapchain_images_count); *swapchain_images = std::make_unique<vk::Image[]>(*swapchain_images_count);
vkGetSwapchainImagesKHR(device, swapchain, swapchain_images_count, swapchain_images->get()); device.getSwapchainImagesKHR(swapchain, swapchain_images_count, swapchain_images->get());
*swapchain_image_views = std::make_unique<VkImageView[]>(*swapchain_images_count); *swapchain_image_views = std::make_unique<vk::ImageView[]>(*swapchain_images_count);
for (uint32_t i = 0; i < *swapchain_images_count; i++) { for (uint32_t i = 0; i < *swapchain_images_count; i++) {
VkImageViewCreateInfo create_info {}; vk::ImageViewCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; create_info.sType = vk::StructureType::eImageViewCreateInfo;
create_info.pNext = nullptr; create_info.pNext = nullptr;
create_info.flags = 0; create_info.flags = {};
create_info.image = (*swapchain_images)[i]; create_info.image = (*swapchain_images)[i];
create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; create_info.viewType = vk::ImageViewType::e2D;
create_info.format = *swapchain_format; create_info.format = *swapchain_format;
create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; create_info.components.r = vk::ComponentSwizzle::eIdentity;
create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; create_info.components.g = vk::ComponentSwizzle::eIdentity;
create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; create_info.components.b = vk::ComponentSwizzle::eIdentity;
create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; create_info.components.a = vk::ComponentSwizzle::eIdentity;
create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; create_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
create_info.subresourceRange.baseArrayLayer = 0; create_info.subresourceRange.baseArrayLayer = 0;
create_info.subresourceRange.baseMipLevel = 0; create_info.subresourceRange.baseMipLevel = 0;
create_info.subresourceRange.layerCount = 1; create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = 1; create_info.subresourceRange.levelCount = 1;
vkCreateImageView(device, &create_info, nullptr, &((*swapchain_image_views)[i])); device.createImageView(&create_info, nullptr, &((*swapchain_image_views)[i]));
} }
return swapchain; return swapchain;
@@ -302,21 +303,21 @@ VulkanSwapchain* VulkanCreateSwapchain(GraphicContext* ctx, uint32_t image_count
s->current_index = static_cast<uint32_t>(-1); s->current_index = static_cast<uint32_t>(-1);
s->present_frame = 0; s->present_frame = 0;
VkSemaphoreCreateInfo semaphore_info {}; vk::SemaphoreCreateInfo semaphore_info {};
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphore_info.sType = vk::StructureType::eSemaphoreCreateInfo;
semaphore_info.pNext = nullptr; semaphore_info.pNext = nullptr;
semaphore_info.flags = 0; semaphore_info.flags = {};
s->image_acquired_semaphores = std::make_unique<VkSemaphore[]>(s->swapchain_images_count); s->image_acquired_semaphores = std::make_unique<vk::Semaphore[]>(s->swapchain_images_count);
s->render_complete_semaphores = std::make_unique<VkSemaphore[]>(s->swapchain_images_count); s->render_complete_semaphores = std::make_unique<vk::Semaphore[]>(s->swapchain_images_count);
for (uint32_t i = 0; i < s->swapchain_images_count; i++) { for (uint32_t i = 0; i < s->swapchain_images_count; i++) {
auto result = vkCreateSemaphore(ctx->device, &semaphore_info, nullptr, auto result =
&s->image_acquired_semaphores[i]); ctx->device.createSemaphore(&semaphore_info, nullptr, &s->image_acquired_semaphores[i]);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
result = vkCreateSemaphore(ctx->device, &semaphore_info, nullptr, result = ctx->device.createSemaphore(&semaphore_info, nullptr,
&s->render_complete_semaphores[i]); &s->render_complete_semaphores[i]);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
} }
GetPreparedFramePool()->EnsureCapacity(s->swapchain_images_count, s->swapchain_format); GetPreparedFramePool()->EnsureCapacity(s->swapchain_images_count, s->swapchain_format);
@@ -334,27 +335,27 @@ static void VulkanDeleteSwapchain(GraphicContext* ctx, VulkanSwapchain* s) {
if (s->image_acquired_semaphores != nullptr) { if (s->image_acquired_semaphores != nullptr) {
for (uint32_t i = 0; i < s->swapchain_images_count; i++) { for (uint32_t i = 0; i < s->swapchain_images_count; i++) {
if (s->image_acquired_semaphores[i] != nullptr) { if (s->image_acquired_semaphores[i] != nullptr) {
vkDestroySemaphore(ctx->device, s->image_acquired_semaphores[i], nullptr); ctx->device.destroySemaphore(s->image_acquired_semaphores[i], nullptr);
} }
} }
} }
if (s->render_complete_semaphores != nullptr) { if (s->render_complete_semaphores != nullptr) {
for (uint32_t i = 0; i < s->swapchain_images_count; i++) { for (uint32_t i = 0; i < s->swapchain_images_count; i++) {
if (s->render_complete_semaphores[i] != nullptr) { if (s->render_complete_semaphores[i] != nullptr) {
vkDestroySemaphore(ctx->device, s->render_complete_semaphores[i], nullptr); ctx->device.destroySemaphore(s->render_complete_semaphores[i], nullptr);
} }
} }
} }
if (s->swapchain_image_views != nullptr) { if (s->swapchain_image_views != nullptr) {
for (uint32_t i = 0; i < s->swapchain_images_count; i++) { for (uint32_t i = 0; i < s->swapchain_images_count; i++) {
if (s->swapchain_image_views[i] != nullptr) { if (s->swapchain_image_views[i] != nullptr) {
vkDestroyImageView(ctx->device, s->swapchain_image_views[i], nullptr); ctx->device.destroyImageView(s->swapchain_image_views[i], nullptr);
} }
} }
} }
if (s->swapchain != nullptr) { if (s->swapchain != nullptr) {
vkDestroySwapchainKHR(ctx->device, s->swapchain, nullptr); ctx->device.destroySwapchainKHR(s->swapchain, nullptr);
} }
} }
@@ -395,7 +396,7 @@ static void ValidatePreparedCommand(CommandBuffer* buffer) {
PreparedFrame* WindowPrepareFrame(CommandBuffer* buffer, VideoOutVulkanImage* image) { PreparedFrame* WindowPrepareFrame(CommandBuffer* buffer, VideoOutVulkanImage* image) {
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
ValidatePreparedCommand(buffer); ValidatePreparedCommand(buffer);
if (image->format == VK_FORMAT_UNDEFINED) { if (image->format == vk::Format::eUndefined) {
EXIT("unsupported presentation source, image=%p\n", static_cast<const void*>(image)); EXIT("unsupported presentation source, image=%p\n", static_cast<const void*>(image));
} }
@@ -405,8 +406,7 @@ PreparedFrame* WindowPrepareFrame(CommandBuffer* buffer, VideoOutVulkanImage* im
ConfigurePreparedFrame(frame, image->extent, image->format); ConfigurePreparedFrame(frame, image->extent, image->format);
const std::array copies {ImageImageCopy { const std::array copies {ImageImageCopy {
.src_image = image, .width = image->extent.width, .height = image->extent.height}}; .src_image = image, .width = image->extent.width, .height = image->extent.height}};
UtilImageToImage(buffer, copies, &frame->image, UtilImageToImage(buffer, copies, &frame->image, vk::ImageLayout::eTransferSrcOptimal);
static_cast<uint64_t>(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL));
return frame; return frame;
} }
@@ -419,7 +419,8 @@ PreparedFrame* WindowPrepareBlankFrame(CommandBuffer* buffer, uint32_t width, ui
auto* frame = pool->Acquire(); auto* frame = pool->Acquire();
Common::LockGuard render_lock(g_render_ctx->GetMutex()); Common::LockGuard render_lock(g_render_ctx->GetMutex());
ConfigurePreparedFrame(frame, {width, height}, format); ConfigurePreparedFrame(frame, {width, height}, format);
const VkClearColorValue clear {{0.0f, 0.0f, 0.0f, opaque ? 1.0f : 0.0f}}; vk::ClearColorValue clear {};
clear.float32[3] = opaque ? 1.0f : 0.0f;
UtilClearColorImage(buffer, &frame->image, clear); UtilClearColorImage(buffer, &frame->image, clear);
return frame; return frame;
} }
@@ -452,18 +453,20 @@ void WindowPresentFrame(PreparedFrame* frame) {
swapchain->current_index = static_cast<uint32_t>(-1); swapchain->current_index = static_cast<uint32_t>(-1);
auto result = vkAcquireNextImageKHR( auto result = g_window_ctx->graphic_ctx.device.acquireNextImageKHR(
g_window_ctx->graphic_ctx.device, swapchain->swapchain, UINT64_MAX, swapchain->swapchain, UINT64_MAX, swapchain->image_acquired_semaphores[present_frame],
swapchain->image_acquired_semaphores[present_frame], nullptr, &swapchain->current_index); nullptr, &swapchain->current_index);
switch (result) { switch (result) {
case VK_SUCCESS: break; case vk::Result::eSuccess: break;
case VK_SUBOPTIMAL_KHR: LOGF("vkAcquireNextImageKHR returned VK_SUBOPTIMAL_KHR\n"); break; case vk::Result::eSuboptimalKHR:
case VK_ERROR_OUT_OF_DATE_KHR: LOGF("vkAcquireNextImageKHR returned vk::Result::eSuboptimalKHR\n");
LOGF("vkAcquireNextImageKHR returned VK_ERROR_OUT_OF_DATE_KHR\n"); break;
case vk::Result::eErrorOutOfDateKHR:
LOGF("vkAcquireNextImageKHR returned vk::Result::eErrorOutOfDateKHR\n");
VulkanRecreateSwapchain(); VulkanRecreateSwapchain();
return; return;
default: EXIT("vkAcquireNextImageKHR failed: %s\n", string_VkResult(result)); default: EXIT("vkAcquireNextImageKHR failed: %s\n", VulkanToString(result).c_str());
} }
EXIT_NOT_IMPLEMENTED(swapchain->current_index == static_cast<uint32_t>(-1)); EXIT_NOT_IMPLEMENTED(swapchain->current_index == static_cast<uint32_t>(-1));
if (frame->present_commands == nullptr) { if (frame->present_commands == nullptr) {
@@ -472,41 +475,41 @@ void WindowPresentFrame(PreparedFrame* frame) {
frame->present_commands->WaitForFenceAndReset(); frame->present_commands->WaitForFenceAndReset();
auto& buffer = *frame->present_commands; auto& buffer = *frame->present_commands;
auto* vk_buffer = buffer.GetPool()->buffers[buffer.GetIndex()]; auto vk_buffer = buffer.GetPool()->buffers[buffer.GetIndex()];
buffer.Begin(); buffer.Begin();
UtilBlitPreparedImage(&buffer, &frame->image, swapchain); UtilBlitPreparedImage(&buffer, &frame->image, swapchain);
VkImageMemoryBarrier pre_present_barrier {}; vk::ImageMemoryBarrier pre_present_barrier {};
pre_present_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; pre_present_barrier.sType = vk::StructureType::eImageMemoryBarrier;
pre_present_barrier.pNext = nullptr; pre_present_barrier.pNext = nullptr;
pre_present_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; pre_present_barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
pre_present_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; pre_present_barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead;
pre_present_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; pre_present_barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal;
pre_present_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; pre_present_barrier.newLayout = vk::ImageLayout::ePresentSrcKHR;
pre_present_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; pre_present_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
pre_present_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; pre_present_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
pre_present_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; pre_present_barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
pre_present_barrier.subresourceRange.baseMipLevel = 0; pre_present_barrier.subresourceRange.baseMipLevel = 0;
pre_present_barrier.subresourceRange.levelCount = 1; pre_present_barrier.subresourceRange.levelCount = 1;
pre_present_barrier.subresourceRange.baseArrayLayer = 0; pre_present_barrier.subresourceRange.baseArrayLayer = 0;
pre_present_barrier.subresourceRange.layerCount = 1; pre_present_barrier.subresourceRange.layerCount = 1;
pre_present_barrier.image = swapchain->swapchain_images[swapchain->current_index]; pre_present_barrier.image = swapchain->swapchain_images[swapchain->current_index];
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, vk::PipelineStageFlagBits::eBottomOfPipe, vk::DependencyFlags {}, 0,
&pre_present_barrier); nullptr, 0, nullptr, 1, &pre_present_barrier);
buffer.End(); buffer.End();
auto render_complete_semaphore = auto render_complete_semaphore =
swapchain->render_complete_semaphores[swapchain->current_index]; swapchain->render_complete_semaphores[swapchain->current_index];
const VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; const vk::PipelineStageFlags wait_stage = vk::PipelineStageFlagBits::eTransfer;
buffer.ExecuteWithSemaphore(swapchain->image_acquired_semaphores[present_frame], wait_stage, buffer.ExecuteWithSemaphore(swapchain->image_acquired_semaphores[present_frame], wait_stage,
render_complete_semaphore); render_complete_semaphore);
VkPresentInfoKHR present; vk::PresentInfoKHR present;
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present.sType = vk::StructureType::ePresentInfoKHR;
present.pNext = nullptr; present.pNext = nullptr;
present.swapchainCount = 1; present.swapchainCount = 1;
present.pSwapchains = &swapchain->swapchain; present.pSwapchains = &swapchain->swapchain;
@@ -520,18 +523,20 @@ void WindowPresentFrame(PreparedFrame* frame) {
if (queue.mutex != nullptr) { if (queue.mutex != nullptr) {
queue.mutex->Lock(); queue.mutex->Lock();
} }
result = vkQueuePresentKHR(queue.vk_queue, &present); result = queue.vk_queue.presentKHR(&present);
if (queue.mutex != nullptr) { if (queue.mutex != nullptr) {
queue.mutex->Unlock(); queue.mutex->Unlock();
} }
switch (result) { switch (result) {
case VK_SUCCESS: break; case vk::Result::eSuccess: break;
case VK_SUBOPTIMAL_KHR: LOGF("vkQueuePresentKHR returned VK_SUBOPTIMAL_KHR\n"); break; case vk::Result::eSuboptimalKHR:
case VK_ERROR_OUT_OF_DATE_KHR: LOGF("vkQueuePresentKHR returned vk::Result::eSuboptimalKHR\n");
LOGF("vkQueuePresentKHR returned VK_ERROR_OUT_OF_DATE_KHR\n"); break;
case vk::Result::eErrorOutOfDateKHR:
LOGF("vkQueuePresentKHR returned vk::Result::eErrorOutOfDateKHR\n");
VulkanRecreateSwapchain(); VulkanRecreateSwapchain();
return; return;
default: EXIT("vkQueuePresentKHR failed: %s\n", string_VkResult(result)); default: EXIT("vkQueuePresentKHR failed: %s\n", VulkanToString(result).c_str());
} }
swapchain->present_frame = (present_frame + 1u) % swapchain->swapchain_images_count; swapchain->present_frame = (present_frame + 1u) % swapchain->swapchain_images_count;
+251 -245
View File
@@ -30,6 +30,7 @@
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h" #include "graphics/host_gpu/vma.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/renderDoc.h" #include "graphics/presentation/renderDoc.h"
#include "graphics/presentation/videoOut.h" #include "graphics/presentation/videoOut.h"
#include "graphics/presentation/window.h" #include "graphics/presentation/window.h"
@@ -45,7 +46,6 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include <vulkan/vk_enum_string_helper.h>
#include <vulkan/vk_platform.h> #include <vulkan/vk_platform.h>
// IWYU pragma: no_include <intrin.h> // IWYU pragma: no_include <intrin.h>
@@ -58,13 +58,13 @@ namespace Libs::Graphics {
struct VulkanExtensions { struct VulkanExtensions {
bool enable_validation_layers = false; bool enable_validation_layers = false;
std::vector<const char*> required_extensions; std::vector<const char*> required_extensions;
std::vector<VkExtensionProperties> available_extensions; std::vector<vk::ExtensionProperties> available_extensions;
std::vector<const char*> required_layers; std::vector<const char*> required_layers;
std::vector<VkLayerProperties> available_layers; std::vector<vk::LayerProperties> available_layers;
}; };
static bool HasExtension(const std::vector<VkExtensionProperties>& extensions, const char* name) { static bool HasExtension(const std::vector<vk::ExtensionProperties>& extensions, const char* name) {
return std::any_of(extensions.begin(), extensions.end(), return std::any_of(extensions.begin(), extensions.end(),
[name](const auto& ext) { return strcmp(ext.extensionName, name) == 0; }); [name](const auto& ext) { return strcmp(ext.extensionName, name) == 0; });
} }
@@ -74,54 +74,52 @@ static bool HasExtension(const std::vector<const char*>& extensions, const char*
[name](const char* ext) { return strcmp(ext, name) == 0; }); [name](const char* ext) { return strcmp(ext, name) == 0; });
} }
static bool HasLayer(const std::vector<VkLayerProperties>& layers, const char* name) { static bool HasLayer(const std::vector<vk::LayerProperties>& layers, const char* name) {
return std::any_of(layers.begin(), layers.end(), return std::any_of(layers.begin(), layers.end(),
[name](const auto& layer) { return strcmp(layer.layerName, name) == 0; }); [name](const auto& layer) { return strcmp(layer.layerName, name) == 0; });
} }
void VulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, void VulkanGetSurfaceCapabilities(vk::PhysicalDevice physical_device, vk::SurfaceKHR surface,
SurfaceCapabilities* r) { SurfaceCapabilities* r) {
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &r->capabilities); physical_device.getSurfaceCapabilitiesKHR(surface, &r->capabilities);
uint32_t formats_count = 0; uint32_t formats_count = 0;
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &formats_count, nullptr); physical_device.getSurfaceFormatsKHR(surface, &formats_count, nullptr);
EXIT_NOT_IMPLEMENTED(formats_count == 0); EXIT_NOT_IMPLEMENTED(formats_count == 0);
r->formats = std::vector<VkSurfaceFormatKHR>(formats_count); // @suppress("Ambiguous problem") r->formats = std::vector<vk::SurfaceFormatKHR>(formats_count); // @suppress("Ambiguous problem")
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &formats_count, physical_device.getSurfaceFormatsKHR(surface, &formats_count, r->formats.data());
r->formats.data());
uint32_t present_modes_count = 0; uint32_t present_modes_count = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count, physical_device.getSurfacePresentModesKHR(surface, &present_modes_count, nullptr);
nullptr);
EXIT_NOT_IMPLEMENTED(present_modes_count == 0); EXIT_NOT_IMPLEMENTED(present_modes_count == 0);
r->present_modes = r->present_modes =
std::vector<VkPresentModeKHR>(present_modes_count); // @suppress("Ambiguous problem") std::vector<vk::PresentModeKHR>(present_modes_count); // @suppress("Ambiguous problem")
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count, physical_device.getSurfacePresentModesKHR(surface, &present_modes_count,
r->present_modes.data()); r->present_modes.data());
r->format_srgb_bgra32 = false; r->format_srgb_bgra32 = false;
for (const auto& f: r->formats) { for (const auto& f: r->formats) {
if (f.format == VK_FORMAT_B8G8R8A8_SRGB && if (f.format == vk::Format::eB8G8R8A8Srgb &&
f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { f.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
r->format_srgb_bgra32 = true; r->format_srgb_bgra32 = true;
break; break;
} }
if (f.format == VK_FORMAT_B8G8R8A8_UNORM && if (f.format == vk::Format::eB8G8R8A8Unorm &&
f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { f.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
r->format_unorm_bgra32 = true; r->format_unorm_bgra32 = true;
break; break;
} }
} }
} }
static bool CheckFormat(VkPhysicalDevice device, VkFormat format, bool tile, static bool CheckFormat(vk::PhysicalDevice device, vk::Format format, bool tile,
VkFormatFeatureFlags features) { vk::FormatFeatureFlags features) {
VkFormatProperties format_props {}; vk::FormatProperties format_props {};
vkGetPhysicalDeviceFormatProperties(device, format, &format_props); device.getFormatProperties(format, &format_props);
const auto supported_features = const auto supported_features =
(tile ? format_props.optimalTilingFeatures : format_props.linearTilingFeatures); (tile ? format_props.optimalTilingFeatures : format_props.linearTilingFeatures);
@@ -175,7 +173,7 @@ static void VulkanDumpQueues(const VulkanQueues& qs) {
} }
} }
static VulkanQueues VulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface, static VulkanQueues VulkanFindQueues(vk::PhysicalDevice device, vk::SurfaceKHR surface,
uint32_t graphics_num, uint32_t compute_num, uint32_t graphics_num, uint32_t compute_num,
uint32_t transfer_num, uint32_t present_num) { uint32_t transfer_num, uint32_t present_num) {
EXIT_IF(device == nullptr); EXIT_IF(device == nullptr);
@@ -184,28 +182,28 @@ static VulkanQueues VulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surfa
VulkanQueues qs; VulkanQueues qs;
uint32_t queue_family_count = 0; uint32_t queue_family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, nullptr); device.getQueueFamilyProperties(&queue_family_count, nullptr);
std::vector<VkQueueFamilyProperties> queue_families(queue_family_count); std::vector<vk::QueueFamilyProperties> queue_families(queue_family_count);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families.data()); device.getQueueFamilyProperties(&queue_family_count, queue_families.data());
qs.family_count = queue_family_count; qs.family_count = queue_family_count;
uint32_t family = 0; uint32_t family = 0;
for (auto& f: queue_families) { for (auto& f: queue_families) {
VkBool32 presentation_supported = VK_FALSE; vk::Bool32 presentation_supported = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(device, family, surface, &presentation_supported); device.getSurfaceSupportKHR(family, surface, &presentation_supported);
LOGF("\tqueue family: %s [count = %u], [present = %s]\n", LOGF("\tqueue family: %s [count = %u], [present = %s]\n",
string_VkQueueFlags(f.queueFlags).c_str(), f.queueCount, VulkanToString(f.queueFlags).c_str(), f.queueCount,
(presentation_supported == VK_TRUE ? "true" : "false")); (presentation_supported == VK_TRUE ? "true" : "false"));
for (uint32_t i = 0; i < f.queueCount; i++) { for (uint32_t i = 0; i < f.queueCount; i++) {
QueueInfo info; QueueInfo info;
info.family = family; info.family = family;
info.index = i; info.index = i;
info.graphics = (f.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0; info.graphics = static_cast<bool>(f.queueFlags & vk::QueueFlagBits::eGraphics);
info.compute = (f.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0; info.compute = static_cast<bool>(f.queueFlags & vk::QueueFlagBits::eCompute);
info.transfer = (f.queueFlags & VK_QUEUE_TRANSFER_BIT) != 0; info.transfer = static_cast<bool>(f.queueFlags & vk::QueueFlagBits::eTransfer);
info.present = (presentation_supported == VK_TRUE); info.present = (presentation_supported == VK_TRUE);
qs.available.push_back(info); qs.available.push_back(info);
@@ -253,10 +251,10 @@ static VulkanQueues VulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surfa
} }
// NOLINTNEXTLINE(readability-function-cognitive-complexity) // NOLINTNEXTLINE(readability-function-cognitive-complexity)
static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface, static void VulkanFindPhysicalDevice(vk::Instance instance, vk::SurfaceKHR surface,
const std::vector<const char*>& device_extensions, const std::vector<const char*>& device_extensions,
SurfaceCapabilities* out_capabilities, SurfaceCapabilities* out_capabilities,
VkPhysicalDevice* out_device, VulkanQueues* out_queues) { vk::PhysicalDevice* out_device, VulkanQueues* out_queues) {
EXIT_IF(instance == nullptr); EXIT_IF(instance == nullptr);
EXIT_IF(surface == nullptr); EXIT_IF(surface == nullptr);
EXIT_IF(out_capabilities == nullptr); EXIT_IF(out_capabilities == nullptr);
@@ -264,23 +262,23 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
EXIT_IF(out_queues == nullptr); EXIT_IF(out_queues == nullptr);
uint32_t devices_count = 0; uint32_t devices_count = 0;
vkEnumeratePhysicalDevices(instance, &devices_count, nullptr); instance.enumeratePhysicalDevices(&devices_count, nullptr);
EXIT_NOT_IMPLEMENTED(devices_count == 0); EXIT_NOT_IMPLEMENTED(devices_count == 0);
std::vector<VkPhysicalDevice> devices(devices_count); std::vector<vk::PhysicalDevice> devices(devices_count);
vkEnumeratePhysicalDevices(instance, &devices_count, devices.data()); instance.enumeratePhysicalDevices(&devices_count, devices.data());
VkPhysicalDevice best_device = nullptr; vk::PhysicalDevice best_device = nullptr;
VulkanQueues best_queues; VulkanQueues best_queues;
for (const auto& device: devices) { for (const auto& device: devices) {
bool skip_device = false; bool skip_device = false;
VkPhysicalDeviceProperties device_properties {}; vk::PhysicalDeviceProperties device_properties {};
vkGetPhysicalDeviceProperties(device, &device_properties); device.getProperties(&device_properties);
LOGF("Vulkan device: %s\n", device_properties.deviceName); LOGF("Vulkan device: %s\n", device_properties.deviceName.data());
if (device_properties.apiVersion < VULKAN_TARGET_API_VERSION) { if (device_properties.apiVersion < VULKAN_TARGET_API_VERSION) {
LOGF("Vulkan %u.%u is required, but device supports only %u.%u.%u\n", LOGF("Vulkan %u.%u is required, but device supports only %u.%u.%u\n",
VK_VERSION_MAJOR(VULKAN_TARGET_API_VERSION), VK_VERSION_MAJOR(VULKAN_TARGET_API_VERSION),
@@ -291,30 +289,29 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
continue; continue;
} }
VkPhysicalDeviceFeatures2 device_features2 {}; vk::PhysicalDeviceFeatures2 device_features2 {};
VkPhysicalDeviceVulkan13Features features13 {}; vk::PhysicalDeviceVulkan13Features features13 {};
features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; features13.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
features13.pNext = nullptr; features13.pNext = nullptr;
VkPhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {}; vk::PhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {};
color_write_ext.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT; color_write_ext.sType = vk::StructureType::ePhysicalDeviceColorWriteEnableFeaturesEXT;
color_write_ext.pNext = nullptr; color_write_ext.pNext = nullptr;
VkPhysicalDeviceDepthClipControlFeaturesEXT depth_clip_control {}; vk::PhysicalDeviceDepthClipControlFeaturesEXT depth_clip_control {};
depth_clip_control.sType = depth_clip_control.sType = vk::StructureType::ePhysicalDeviceDepthClipControlFeaturesEXT;
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT;
depth_clip_control.pNext = &color_write_ext; depth_clip_control.pNext = &color_write_ext;
VkPhysicalDeviceVulkan12Features features12 {}; vk::PhysicalDeviceVulkan12Features features12 {};
features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; features12.sType = vk::StructureType::ePhysicalDeviceVulkan12Features;
features12.pNext = &depth_clip_control; features12.pNext = &depth_clip_control;
features13.pNext = &features12; features13.pNext = &features12;
device_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; device_features2.sType = vk::StructureType::ePhysicalDeviceFeatures2;
device_features2.pNext = &features13; device_features2.pNext = &features13;
vkGetPhysicalDeviceFeatures2(device, &device_features2); device.getFeatures2(&device_features2);
auto qs = VulkanFindQueues( auto qs = VulkanFindQueues(
device, surface, GraphicContext::QUEUE_GFX_NUM, GraphicContext::QUEUE_COMPUTE_NUM, device, surface, GraphicContext::QUEUE_GFX_NUM, GraphicContext::QUEUE_COMPUTE_NUM,
@@ -391,13 +388,13 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
if (!skip_device) { if (!skip_device) {
uint32_t extensions_count = 0; uint32_t extensions_count = 0;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensions_count, nullptr); device.enumerateDeviceExtensionProperties(nullptr, &extensions_count, nullptr);
EXIT_NOT_IMPLEMENTED(extensions_count == 0); EXIT_NOT_IMPLEMENTED(extensions_count == 0);
std::vector<VkExtensionProperties> available_extensions(extensions_count); std::vector<vk::ExtensionProperties> available_extensions(extensions_count);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensions_count, device.enumerateDeviceExtensionProperties(nullptr, &extensions_count,
available_extensions.data()); available_extensions.data());
for (const char* ext: device_extensions) { for (const char* ext: device_extensions) {
if (!HasExtension(available_extensions, ext)) { if (!HasExtension(available_extensions, ext)) {
@@ -408,7 +405,7 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
if (skip_device) { if (skip_device) {
for (const auto& ext: available_extensions) { for (const auto& ext: available_extensions) {
LOGF("Vulkan available extension: %s, version = %u\n", ext.extensionName, LOGF("Vulkan available extension: %s, version = %u\n", ext.extensionName.data(),
ext.specVersion); ext.specVersion);
} }
} }
@@ -417,87 +414,87 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
if (!skip_device) { if (!skip_device) {
VulkanGetSurfaceCapabilities(device, surface, out_capabilities); VulkanGetSurfaceCapabilities(device, surface, out_capabilities);
if ((out_capabilities->capabilities.supportedUsageFlags & if (!(out_capabilities->capabilities.supportedUsageFlags &
VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) { vk::ImageUsageFlagBits::eTransferDst)) {
LOGF("Surface cannot be destination of blit\n"); LOGF("Surface cannot be destination of blit\n");
skip_device = true; skip_device = true;
} }
} }
if (!skip_device && if (!skip_device && !CheckFormat(device, vk::Format::eR8G8B8A8Srgb, false,
!CheckFormat(device, VK_FORMAT_R8G8B8A8_SRGB, false, VK_FORMAT_FEATURE_BLIT_SRC_BIT)) { vk::FormatFeatureFlagBits::eBlitSrc)) {
LOGF("Format VK_FORMAT_R8G8B8A8_SRGB cannot be used as transfer source\n"); LOGF("Format vk::Format::eR8G8B8A8Srgb cannot be used as transfer source\n");
skip_device = true; skip_device = true;
} }
if (!skip_device && !CheckFormat(device, VK_FORMAT_D32_SFLOAT, true, if (!skip_device && !CheckFormat(device, vk::Format::eD32Sfloat, true,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) { vk::FormatFeatureFlagBits::eDepthStencilAttachment)) {
LOGF("Format VK_FORMAT_D32_SFLOAT cannot be used as depth buffer\n"); LOGF("Format vk::Format::eD32Sfloat cannot be used as depth buffer\n");
skip_device = true; skip_device = true;
} }
if (!skip_device && !CheckFormat(device, VK_FORMAT_D32_SFLOAT_S8_UINT, true, if (!skip_device && !CheckFormat(device, vk::Format::eD32SfloatS8Uint, true,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) { vk::FormatFeatureFlagBits::eDepthStencilAttachment)) {
LOGF("Format VK_FORMAT_D32_SFLOAT_S8_UINT cannot be used as depth buffer\n"); LOGF("Format vk::Format::eD32SfloatS8Uint cannot be used as depth buffer\n");
skip_device = true; skip_device = true;
} }
if (!skip_device && !CheckFormat(device, VK_FORMAT_D16_UNORM, true, if (!skip_device && !CheckFormat(device, vk::Format::eD16Unorm, true,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) { vk::FormatFeatureFlagBits::eDepthStencilAttachment)) {
LOGF("Format VK_FORMAT_D16_UNORM cannot be used as depth buffer\n"); LOGF("Format vk::Format::eD16Unorm cannot be used as depth buffer\n");
skip_device = true; skip_device = true;
} }
if (!skip_device && !CheckFormat(device, VK_FORMAT_BC3_SRGB_BLOCK, true, if (!skip_device && !CheckFormat(device, vk::Format::eBc3SrgbBlock, true,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | vk::FormatFeatureFlagBits::eSampledImage |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format VK_FORMAT_BC3_SRGB_BLOCK cannot be used as texture\n"); LOGF("Format vk::Format::eBc3SrgbBlock cannot be used as texture\n");
skip_device = true; skip_device = true;
} }
if (!skip_device && !CheckFormat(device, VK_FORMAT_R8G8B8A8_SRGB, true, if (!skip_device && !CheckFormat(device, vk::Format::eR8G8B8A8Srgb, true,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | vk::FormatFeatureFlagBits::eSampledImage |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format VK_FORMAT_R8G8B8A8_SRGB cannot be used as texture\n"); LOGF("Format vk::Format::eR8G8B8A8Srgb cannot be used as texture\n");
skip_device = true; skip_device = true;
} }
if (!skip_device && !CheckFormat(device, VK_FORMAT_R8_UNORM, true, if (!skip_device && !CheckFormat(device, vk::Format::eR8Unorm, true,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | vk::FormatFeatureFlagBits::eSampledImage |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format VK_FORMAT_R8_UNORM cannot be used as texture\n"); LOGF("Format vk::Format::eR8Unorm cannot be used as texture\n");
skip_device = true; skip_device = true;
} }
if (!skip_device && !CheckFormat(device, VK_FORMAT_R8G8_UNORM, true, if (!skip_device && !CheckFormat(device, vk::Format::eR8G8Unorm, true,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | vk::FormatFeatureFlagBits::eSampledImage |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format VK_FORMAT_R8G8_UNORM cannot be used as texture\n"); LOGF("Format vk::Format::eR8G8Unorm cannot be used as texture\n");
skip_device = true; skip_device = true;
} }
if (!skip_device && !CheckFormat(device, VK_FORMAT_R8G8B8A8_SRGB, true, if (!skip_device && !CheckFormat(device, vk::Format::eR8G8B8A8Srgb, true,
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | vk::FormatFeatureFlagBits::eStorageImage |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format VK_FORMAT_R8G8B8A8_SRGB cannot be used as texture\n"); LOGF("Format vk::Format::eR8G8B8A8Srgb cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, VK_FORMAT_R8G8B8A8_UNORM, true, if (!skip_device && !CheckFormat(device, vk::Format::eR8G8B8A8Unorm, true,
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | vk::FormatFeatureFlagBits::eStorageImage |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format VK_FORMAT_R8G8B8A8_UNORM cannot be used as texture\n"); LOGF("Format vk::Format::eR8G8B8A8Unorm cannot be used as texture\n");
skip_device = true; skip_device = true;
} }
} }
if (!skip_device && !CheckFormat(device, VK_FORMAT_B8G8R8A8_SRGB, true, if (!skip_device && !CheckFormat(device, vk::Format::eB8G8R8A8Srgb, true,
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | vk::FormatFeatureFlagBits::eStorageImage |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format VK_FORMAT_B8G8R8A8_SRGB cannot be used as texture\n"); LOGF("Format vk::Format::eB8G8R8A8Srgb cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, VK_FORMAT_B8G8R8A8_UNORM, true, if (!skip_device && !CheckFormat(device, vk::Format::eB8G8R8A8Unorm, true,
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | vk::FormatFeatureFlagBits::eStorageImage |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format VK_FORMAT_B8G8R8A8_UNORM cannot be used as texture\n"); LOGF("Format vk::Format::eB8G8R8A8Unorm cannot be used as texture\n");
skip_device = true; skip_device = true;
} }
} }
@@ -512,7 +509,7 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
} }
if (best_device == nullptr || if (best_device == nullptr ||
device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { device_properties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
best_device = device; best_device = device;
best_queues = qs; best_queues = qs;
} }
@@ -522,34 +519,33 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
*out_queues = best_queues; *out_queues = best_queues;
} }
static void VulkanInitSubgroupSizeControl(VkPhysicalDevice physical_device, GraphicContext* ctx) { static void VulkanInitSubgroupSizeControl(vk::PhysicalDevice physical_device, GraphicContext* ctx) {
EXIT_IF(physical_device == nullptr); EXIT_IF(physical_device == nullptr);
EXIT_IF(ctx == nullptr); EXIT_IF(ctx == nullptr);
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control {}; vk::PhysicalDeviceSubgroupSizeControlProperties subgroup_size_control {};
subgroup_size_control.sType = subgroup_size_control.sType = vk::StructureType::ePhysicalDeviceSubgroupSizeControlProperties;
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES;
subgroup_size_control.pNext = nullptr; subgroup_size_control.pNext = nullptr;
VkPhysicalDeviceVulkan11Properties properties11 {}; vk::PhysicalDeviceVulkan11Properties properties11 {};
properties11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES; properties11.sType = vk::StructureType::ePhysicalDeviceVulkan11Properties;
properties11.pNext = &subgroup_size_control; properties11.pNext = &subgroup_size_control;
VkPhysicalDeviceProperties2 properties2 {}; vk::PhysicalDeviceProperties2 properties2 {};
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; properties2.sType = vk::StructureType::ePhysicalDeviceProperties2;
properties2.pNext = &properties11; properties2.pNext = &properties11;
vkGetPhysicalDeviceProperties2(physical_device, &properties2); physical_device.getProperties2(&properties2);
VkPhysicalDeviceVulkan13Features features13 {}; vk::PhysicalDeviceVulkan13Features features13 {};
features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; features13.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
features13.pNext = nullptr; features13.pNext = nullptr;
VkPhysicalDeviceFeatures2 features2 {}; vk::PhysicalDeviceFeatures2 features2 {};
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; features2.sType = vk::StructureType::ePhysicalDeviceFeatures2;
features2.pNext = &features13; features2.pNext = &features13;
vkGetPhysicalDeviceFeatures2(physical_device, &features2); physical_device.getFeatures2(&features2);
ctx->subgroup_size = properties11.subgroupSize; ctx->subgroup_size = properties11.subgroupSize;
ctx->min_subgroup_size = subgroup_size_control.minSubgroupSize; ctx->min_subgroup_size = subgroup_size_control.minSubgroupSize;
@@ -561,21 +557,22 @@ static void VulkanInitSubgroupSizeControl(VkPhysicalDevice physical_device, Grap
LOGF("Vulkan subgroup: default=%u min=%u max=%u stages=0x%08x size_control=%s\n", LOGF("Vulkan subgroup: default=%u min=%u max=%u stages=0x%08x size_control=%s\n",
ctx->subgroup_size, ctx->min_subgroup_size, ctx->max_subgroup_size, ctx->subgroup_size, ctx->min_subgroup_size, ctx->max_subgroup_size,
ctx->required_subgroup_size_stages, ctx->subgroup_size_control_enabled ? "true" : "false"); static_cast<vk::ShaderStageFlags::MaskType>(ctx->required_subgroup_size_stages),
ctx->subgroup_size_control_enabled ? "true" : "false");
} }
static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface, static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, vk::SurfaceKHR surface,
const VulkanExtensions* r, const VulkanQueues& queues, const VulkanExtensions* r, const VulkanQueues& queues,
const std::vector<const char*>& device_extensions, const std::vector<const char*>& device_extensions,
const GraphicContext* ctx) { const GraphicContext* ctx) {
EXIT_IF(physical_device == nullptr); EXIT_IF(physical_device == nullptr);
EXIT_IF(r == nullptr); EXIT_IF(r == nullptr);
EXIT_IF(surface == nullptr); EXIT_IF(surface == nullptr);
EXIT_IF(ctx == nullptr); EXIT_IF(ctx == nullptr);
std::vector<VkDeviceQueueCreateInfo> queue_create_info(queues.family_count); std::vector<vk::DeviceQueueCreateInfo> queue_create_info(queues.family_count);
std::vector<std::vector<float>> queue_priority(queues.family_count); std::vector<std::vector<float>> queue_priority(queues.family_count);
uint32_t queue_create_info_num = 0; uint32_t queue_create_info_num = 0;
for (uint32_t i = 0; i < queues.family_count; i++) { for (uint32_t i = 0; i < queues.family_count; i++) {
if (queues.family_used[i] != 0) { if (queues.family_used[i] != 0) {
@@ -584,9 +581,9 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
} }
queue_create_info[queue_create_info_num].sType = queue_create_info[queue_create_info_num].sType =
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; vk::StructureType::eDeviceQueueCreateInfo;
queue_create_info[queue_create_info_num].pNext = nullptr; queue_create_info[queue_create_info_num].pNext = nullptr;
queue_create_info[queue_create_info_num].flags = 0; queue_create_info[queue_create_info_num].flags = {};
queue_create_info[queue_create_info_num].queueFamilyIndex = i; queue_create_info[queue_create_info_num].queueFamilyIndex = i;
queue_create_info[queue_create_info_num].queueCount = queues.family_used[i]; queue_create_info[queue_create_info_num].queueCount = queues.family_used[i];
queue_create_info[queue_create_info_num].pQueuePriorities = queue_create_info[queue_create_info_num].pQueuePriorities =
@@ -596,45 +593,45 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
} }
} }
VkPhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {}; vk::PhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {};
color_write_ext.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT; color_write_ext.sType = vk::StructureType::ePhysicalDeviceColorWriteEnableFeaturesEXT;
color_write_ext.pNext = nullptr; color_write_ext.pNext = nullptr;
color_write_ext.colorWriteEnable = VK_TRUE; color_write_ext.colorWriteEnable = VK_TRUE;
VkPhysicalDeviceDepthClipControlFeaturesEXT depth_clip_control {}; vk::PhysicalDeviceDepthClipControlFeaturesEXT depth_clip_control {};
depth_clip_control.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT; depth_clip_control.sType = vk::StructureType::ePhysicalDeviceDepthClipControlFeaturesEXT;
depth_clip_control.pNext = &color_write_ext; depth_clip_control.pNext = &color_write_ext;
depth_clip_control.depthClipControl = VK_TRUE; depth_clip_control.depthClipControl = VK_TRUE;
VkPhysicalDeviceVulkan12Features features12 {}; vk::PhysicalDeviceVulkan12Features features12 {};
features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; features12.sType = vk::StructureType::ePhysicalDeviceVulkan12Features;
features12.pNext = &depth_clip_control; features12.pNext = &depth_clip_control;
features12.samplerMirrorClampToEdge = VK_TRUE; features12.samplerMirrorClampToEdge = VK_TRUE;
VkPhysicalDeviceSubgroupSizeControlFeatures subgroup_size_control {}; vk::PhysicalDeviceSubgroupSizeControlFeatures subgroup_size_control {};
subgroup_size_control.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES; subgroup_size_control.sType = vk::StructureType::ePhysicalDeviceSubgroupSizeControlFeatures;
subgroup_size_control.pNext = &features12; subgroup_size_control.pNext = &features12;
VkPhysicalDeviceVulkan13Features supported_features13 {}; vk::PhysicalDeviceVulkan13Features supported_features13 {};
supported_features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; supported_features13.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
supported_features13.pNext = nullptr; supported_features13.pNext = nullptr;
const auto robustness2_ext_enabled = const auto robustness2_ext_enabled =
HasExtension(device_extensions, VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); HasExtension(device_extensions, VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
VkPhysicalDeviceRobustness2FeaturesEXT supported_robustness2 {}; vk::PhysicalDeviceRobustness2FeaturesEXT supported_robustness2 {};
supported_robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; supported_robustness2.sType = vk::StructureType::ePhysicalDeviceRobustness2FeaturesEXT;
supported_robustness2.pNext = nullptr; supported_robustness2.pNext = nullptr;
if (robustness2_ext_enabled) { if (robustness2_ext_enabled) {
supported_features13.pNext = &supported_robustness2; supported_features13.pNext = &supported_robustness2;
} }
VkPhysicalDeviceFeatures2 supported_features2 {}; vk::PhysicalDeviceFeatures2 supported_features2 {};
supported_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; supported_features2.sType = vk::StructureType::ePhysicalDeviceFeatures2;
supported_features2.pNext = &supported_features13; supported_features2.pNext = &supported_features13;
vkGetPhysicalDeviceFeatures2(physical_device, &supported_features2); physical_device.getFeatures2(&supported_features2);
VkPhysicalDeviceFeatures device_features {}; vk::PhysicalDeviceFeatures device_features {};
device_features.fragmentStoresAndAtomics = VK_TRUE; device_features.fragmentStoresAndAtomics = VK_TRUE;
device_features.samplerAnisotropy = VK_TRUE; device_features.samplerAnisotropy = VK_TRUE;
device_features.robustBufferAccess = VK_TRUE; device_features.robustBufferAccess = VK_TRUE;
@@ -655,8 +652,8 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
? static_cast<const void*>(&subgroup_size_control) ? static_cast<const void*>(&subgroup_size_control)
: static_cast<const void*>(&features12)); : static_cast<const void*>(&features12));
VkPhysicalDeviceRobustness2FeaturesEXT robustness2 {}; vk::PhysicalDeviceRobustness2FeaturesEXT robustness2 {};
robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; robustness2.sType = vk::StructureType::ePhysicalDeviceRobustness2FeaturesEXT;
robustness2.pNext = const_cast<void*>(base_feature_chain); robustness2.pNext = const_cast<void*>(base_feature_chain);
if (robustness2_ext_enabled) { if (robustness2_ext_enabled) {
robustness2.robustBufferAccess2 = supported_robustness2.robustBufferAccess2; robustness2.robustBufferAccess2 = supported_robustness2.robustBufferAccess2;
@@ -664,8 +661,8 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
robustness2.nullDescriptor = supported_robustness2.nullDescriptor; robustness2.nullDescriptor = supported_robustness2.nullDescriptor;
} }
VkPhysicalDeviceVulkan13Features features13 {}; vk::PhysicalDeviceVulkan13Features features13 {};
features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; features13.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
features13.pNext = features13.pNext =
robustness2_ext_enabled ? &robustness2 : const_cast<void*>(base_feature_chain); robustness2_ext_enabled ? &robustness2 : const_cast<void*>(base_feature_chain);
features13.robustImageAccess = supported_features13.robustImageAccess; features13.robustImageAccess = supported_features13.robustImageAccess;
@@ -674,10 +671,10 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
features13.robustImageAccess == VK_TRUE ? "true" : "false", features13.robustImageAccess == VK_TRUE ? "true" : "false",
robustness2_ext_enabled && robustness2.robustImageAccess2 == VK_TRUE ? "true" : "false"); robustness2_ext_enabled && robustness2.robustImageAccess2 == VK_TRUE ? "true" : "false");
VkDeviceCreateInfo create_info {}; vk::DeviceCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; create_info.sType = vk::StructureType::eDeviceCreateInfo;
create_info.pNext = &features13; create_info.pNext = &features13;
create_info.flags = 0; create_info.flags = {};
create_info.pQueueCreateInfos = queue_create_info.data(); create_info.pQueueCreateInfos = queue_create_info.data();
create_info.queueCreateInfoCount = queue_create_info_num; create_info.queueCreateInfoCount = queue_create_info_num;
create_info.enabledLayerCount = create_info.enabledLayerCount =
@@ -688,11 +685,11 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
create_info.ppEnabledExtensionNames = device_extensions.data(); create_info.ppEnabledExtensionNames = device_extensions.data();
create_info.pEnabledFeatures = &device_features; create_info.pEnabledFeatures = &device_features;
VkDevice device = nullptr; vk::Device device = nullptr;
auto result = vkCreateDevice(physical_device, &create_info, nullptr, &device); auto result = physical_device.createDevice(&create_info, nullptr, &device);
if (result != VK_SUCCESS) { if (result != vk::Result::eSuccess) {
LOGF("vkCreateDevice failed: %s\n", string_VkResult(result)); LOGF("vkCreateDevice failed: %s\n", VulkanToString(result).c_str());
return nullptr; return nullptr;
} }
@@ -724,15 +721,15 @@ static void VulkanGetExtensions(SDL_Window* window, VulkanExtensions* r) {
EXIT_NOT_IMPLEMENTED(required_extensions_count == 0); EXIT_NOT_IMPLEMENTED(required_extensions_count == 0);
EXIT_NOT_IMPLEMENTED(required_extensions_count != r->required_extensions.size()); EXIT_NOT_IMPLEMENTED(required_extensions_count != r->required_extensions.size());
vkEnumerateInstanceExtensionProperties(nullptr, &available_extensions_count, nullptr); vk::enumerateInstanceExtensionProperties(nullptr, &available_extensions_count, nullptr);
r->available_extensions = std::vector<VkExtensionProperties>( r->available_extensions = std::vector<vk::ExtensionProperties>(
available_extensions_count); // @suppress("Ambiguous problem") available_extensions_count); // @suppress("Ambiguous problem")
std::memset(r->available_extensions.data(), 0, std::memset(r->available_extensions.data(), 0,
sizeof(VkExtensionProperties) * r->available_extensions.size()); sizeof(vk::ExtensionProperties) * r->available_extensions.size());
vkEnumerateInstanceExtensionProperties(nullptr, &available_extensions_count, vk::enumerateInstanceExtensionProperties(nullptr, &available_extensions_count,
r->available_extensions.data()); r->available_extensions.data());
EXIT_NOT_IMPLEMENTED(available_extensions_count != r->available_extensions.size()); EXIT_NOT_IMPLEMENTED(available_extensions_count != r->available_extensions.size());
@@ -749,22 +746,23 @@ static void VulkanGetExtensions(SDL_Window* window, VulkanExtensions* r) {
} }
for (const auto& ext: r->available_extensions) { for (const auto& ext: r->available_extensions) {
LOGF("Vulkan available extension: %s, version = %u\n", ext.extensionName, ext.specVersion); LOGF("Vulkan available extension: %s, version = %u\n", ext.extensionName.data(),
ext.specVersion);
} }
vkEnumerateInstanceLayerProperties(&available_layers_count, nullptr); vk::enumerateInstanceLayerProperties(&available_layers_count, nullptr);
r->available_layers = r->available_layers =
std::vector<VkLayerProperties>(available_layers_count); // @suppress("Ambiguous problem") std::vector<vk::LayerProperties>(available_layers_count); // @suppress("Ambiguous problem")
std::memset(r->available_layers.data(), 0, std::memset(r->available_layers.data(), 0,
sizeof(VkLayerProperties) * r->available_layers.size()); sizeof(vk::LayerProperties) * r->available_layers.size());
vkEnumerateInstanceLayerProperties(&available_layers_count, r->available_layers.data()); vk::enumerateInstanceLayerProperties(&available_layers_count, r->available_layers.data());
EXIT_NOT_IMPLEMENTED(available_layers_count != r->available_layers.size()); EXIT_NOT_IMPLEMENTED(available_layers_count != r->available_layers.size());
for (const auto& l: r->available_layers) { for (const auto& l: r->available_layers) {
LOGF("Vulkan available layer: %s, specVersion = %u, implVersion = %u, %s\n", l.layerName, LOGF("Vulkan available layer: %s, specVersion = %u, implVersion = %u, %s\n",
l.specVersion, l.implementationVersion, l.description); l.layerName.data(), l.specVersion, l.implementationVersion, l.description.data());
} }
r->required_layers = {"VK_LAYER_KHRONOS_validation"}; r->required_layers = {"VK_LAYER_KHRONOS_validation"};
@@ -780,18 +778,18 @@ static void VulkanGetExtensions(SDL_Window* window, VulkanExtensions* r) {
} }
if (r->enable_validation_layers) { if (r->enable_validation_layers) {
vkEnumerateInstanceExtensionProperties("VK_LAYER_KHRONOS_validation", vk::enumerateInstanceExtensionProperties("VK_LAYER_KHRONOS_validation",
&available_extensions_count, nullptr); &available_extensions_count, nullptr);
std::vector<VkExtensionProperties> available_extensions(available_extensions_count); std::vector<vk::ExtensionProperties> available_extensions(available_extensions_count);
vkEnumerateInstanceExtensionProperties("VK_LAYER_KHRONOS_validation", vk::enumerateInstanceExtensionProperties("VK_LAYER_KHRONOS_validation",
&available_extensions_count, &available_extensions_count,
available_extensions.data()); available_extensions.data());
for (const auto& ext: available_extensions) { for (const auto& ext: available_extensions) {
LOGF("VK_LAYER_KHRONOS_validation available extension: %s, version = %u\n", LOGF("VK_LAYER_KHRONOS_validation available extension: %s, version = %u\n",
ext.extensionName, ext.specVersion); ext.extensionName.data(), ext.specVersion);
} }
if (HasExtension(available_extensions, VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME)) { if (HasExtension(available_extensions, VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME)) {
@@ -802,10 +800,10 @@ static void VulkanGetExtensions(SDL_Window* window, VulkanExtensions* r) {
} }
} }
static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugMessengerCallback( static VKAPI_ATTR vk::Bool32 VKAPI_CALL VulkanDebugMessengerCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, vk::DebugUtilsMessageSeverityFlagBitsEXT message_severity,
VkDebugUtilsMessageTypeFlagsEXT message_types, vk::DebugUtilsMessageTypeFlagsEXT message_types,
const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* /*user_data*/) { const vk::DebugUtilsMessengerCallbackDataEXT* callback_data, void* /*user_data*/) {
EXIT_IF(callback_data == nullptr); EXIT_IF(callback_data == nullptr);
EXIT_IF(callback_data->pMessage == nullptr); EXIT_IF(callback_data->pMessage == nullptr);
@@ -815,13 +813,13 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugMessengerCallback(
bool error = false; bool error = false;
bool debug_printf = false; bool debug_printf = false;
switch (message_severity) { switch (message_severity) {
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: case vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose:
severity_str = "V"; severity_str = "V";
severity_style = Log::Color::BrightWhite; severity_style = Log::Color::BrightWhite;
skip = true; skip = true;
break; break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: case vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo:
if ((message_types & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) != 0 && if ((message_types & vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation) &&
Config::SpirvDebugPrintfEnabled() && callback_data->pMessageIdName != nullptr && Config::SpirvDebugPrintfEnabled() && callback_data->pMessageIdName != nullptr &&
strcmp(callback_data->pMessageIdName, "UNASSIGNED-DEBUG-PRINTF") == 0) { strcmp(callback_data->pMessageIdName, "UNASSIGNED-DEBUG-PRINTF") == 0) {
debug_printf = true; debug_printf = true;
@@ -833,16 +831,17 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugMessengerCallback(
skip = true; skip = true;
} }
break; break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: case vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning:
severity_str = "W"; severity_str = "W";
severity_style = Log::Color::Red; severity_style = Log::Color::Red;
break; break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: case vk::DebugUtilsMessageSeverityFlagBitsEXT::eError:
severity_str = "E"; severity_str = "E";
severity_style = Log::Color::BrightRed; severity_style = Log::Color::BrightRed;
// Only validation errors are fatal; GENERAL-type errors can come // Only validation errors are fatal; GENERAL-type errors can come
// from unrelated loader/layer issues (e.g. a broken overlay). // from unrelated loader/layer issues (e.g. a broken overlay).
error = (message_types & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) != 0; error = static_cast<bool>(message_types &
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation);
break; break;
default: severity_str = "?"; default: severity_str = "?";
} }
@@ -867,17 +866,15 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugMessengerCallback(
return VK_FALSE; return VK_FALSE;
} }
static VKAPI_ATTR VkResult VKAPI_CALL VulkanCreateDebugUtilsMessengerEXT( static VKAPI_ATTR vk::Result VKAPI_CALL VulkanCreateDebugUtilsMessengerEXT(
VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* create_info, vk::Instance instance, const vk::DebugUtilsMessengerCreateInfoEXT* create_info,
const VkAllocationCallbacks* allocator, VkDebugUtilsMessengerEXT* messenger) { const vk::AllocationCallbacks* allocator, vk::DebugUtilsMessengerEXT* messenger) {
EXIT_IF(instance == nullptr); EXIT_IF(instance == nullptr);
if (auto func = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>( if (auto func = VULKAN_HPP_DEFAULT_DISPATCHER.vkCreateDebugUtilsMessengerEXT; func != nullptr) {
vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT")); return instance.createDebugUtilsMessengerEXT(create_info, allocator, messenger);
func != nullptr) {
return func(instance, create_info, allocator, messenger);
} }
return VK_ERROR_EXTENSION_NOT_PRESENT; return vk::Result::eErrorExtensionNotPresent;
} }
static void VulkanCreateQueues(GraphicContext* ctx, const VulkanQueues& queues) { static void VulkanCreateQueues(GraphicContext* ctx, const VulkanQueues& queues) {
@@ -893,8 +890,8 @@ static void VulkanCreateQueues(GraphicContext* ctx, const VulkanQueues& queues)
ctx->queues[id].family = info.family; ctx->queues[id].family = info.family;
ctx->queues[id].index = info.index; ctx->queues[id].index = info.index;
EXIT_IF(ctx->queues[id].vk_queue != nullptr); EXIT_IF(ctx->queues[id].vk_queue != nullptr);
vkGetDeviceQueue(ctx->device, ctx->queues[id].family, ctx->queues[id].index, ctx->device.getQueue(ctx->queues[id].family, ctx->queues[id].index,
&ctx->queues[id].vk_queue); &ctx->queues[id].vk_queue);
EXIT_NOT_IMPLEMENTED(ctx->queues[id].vk_queue == nullptr); EXIT_NOT_IMPLEMENTED(ctx->queues[id].vk_queue == nullptr);
if (with_mutex) { if (with_mutex) {
ctx->queues[id].mutex = new Common::Mutex; ctx->queues[id].mutex = new Common::Mutex;
@@ -947,12 +944,10 @@ static void VulkanCreateQueues(GraphicContext* ctx, const VulkanQueues& queues)
static void VulkanCheckInstanceVersion() { static void VulkanCheckInstanceVersion() {
uint32_t version = VK_API_VERSION_1_0; uint32_t version = VK_API_VERSION_1_0;
auto enumerate_instance_version = reinterpret_cast<PFN_vkEnumerateInstanceVersion>( if (VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceVersion != nullptr) {
vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion")); auto result = vk::enumerateInstanceVersion(&version);
if (enumerate_instance_version != nullptr) { if (result != vk::Result::eSuccess) {
auto result = enumerate_instance_version(&version); EXIT("Could not query Vulkan loader version: %s\n", VulkanToString(result).c_str());
if (result != VK_SUCCESS) {
EXIT("Could not query Vulkan loader version: %s\n", string_VkResult(result));
} }
} }
@@ -973,12 +968,19 @@ void VulkanCreate(WindowContext* ctx) {
EXIT_IF(ctx->graphic_ctx.device != nullptr); EXIT_IF(ctx->graphic_ctx.device != nullptr);
EXIT_IF(ctx->surface_capabilities != nullptr); EXIT_IF(ctx->surface_capabilities != nullptr);
auto get_instance_proc_addr =
reinterpret_cast<PFN_vkGetInstanceProcAddr>(SDL_Vulkan_GetVkGetInstanceProcAddr());
if (get_instance_proc_addr == nullptr) {
EXIT("Could not load Vulkan: %s\n", SDL_GetError());
}
VULKAN_HPP_DEFAULT_DISPATCHER.init(get_instance_proc_addr);
VulkanExtensions r; VulkanExtensions r;
VulkanGetExtensions(ctx->window, &r); VulkanGetExtensions(ctx->window, &r);
VulkanCheckInstanceVersion(); VulkanCheckInstanceVersion();
VkApplicationInfo app_info {}; vk::ApplicationInfo app_info {};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.sType = vk::StructureType::eApplicationInfo;
app_info.pNext = nullptr; app_info.pNext = nullptr;
app_info.pApplicationName = "Kyty"; app_info.pApplicationName = "Kyty";
app_info.applicationVersion = 1; app_info.applicationVersion = 1;
@@ -986,17 +988,17 @@ void VulkanCreate(WindowContext* ctx) {
app_info.engineVersion = 1; app_info.engineVersion = 1;
app_info.apiVersion = VULKAN_TARGET_API_VERSION; // NOLINT app_info.apiVersion = VULKAN_TARGET_API_VERSION; // NOLINT
VkValidationFeatureEnableEXT enabled_features[] = { vk::ValidationFeatureEnableEXT enabled_features[] = {
#ifdef KYTY_ENABLE_BEST_PRACTICES #ifdef KYTY_ENABLE_BEST_PRACTICES
VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT, vk::ValidationFeatureEnableEXT::eBestPractices,
#endif #endif
#ifdef KYTY_ENABLE_DEBUG_PRINTF #ifdef KYTY_ENABLE_DEBUG_PRINTF
VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT, vk::ValidationFeatureEnableEXT::eDebugPrintf,
#endif #endif
}; };
uint32_t enabled_features_count = uint32_t enabled_features_count =
sizeof(enabled_features) / sizeof(VkValidationFeatureEnableEXT); sizeof(enabled_features) / sizeof(vk::ValidationFeatureEnableEXT);
#ifdef KYTY_ENABLE_DEBUG_PRINTF #ifdef KYTY_ENABLE_DEBUG_PRINTF
if (!Config::SpirvDebugPrintfEnabled()) { if (!Config::SpirvDebugPrintfEnabled()) {
@@ -1004,34 +1006,32 @@ void VulkanCreate(WindowContext* ctx) {
} }
#endif #endif
VkValidationFeaturesEXT validation_features {}; vk::ValidationFeaturesEXT validation_features {};
validation_features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT; validation_features.sType = vk::StructureType::eValidationFeaturesEXT;
validation_features.pNext = nullptr; validation_features.pNext = nullptr;
validation_features.enabledValidationFeatureCount = enabled_features_count; validation_features.enabledValidationFeatureCount = enabled_features_count;
validation_features.pEnabledValidationFeatures = enabled_features; validation_features.pEnabledValidationFeatures = enabled_features;
validation_features.disabledValidationFeatureCount = 0; validation_features.disabledValidationFeatureCount = 0;
validation_features.pDisabledValidationFeatures = nullptr; validation_features.pDisabledValidationFeatures = nullptr;
VkDebugUtilsMessengerCreateInfoEXT dbg_create_info {}; vk::DebugUtilsMessengerCreateInfoEXT dbg_create_info {};
dbg_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; dbg_create_info.sType = vk::StructureType::eDebugUtilsMessengerCreateInfoEXT;
dbg_create_info.pNext = &validation_features; dbg_create_info.pNext = &validation_features;
dbg_create_info.flags = 0; dbg_create_info.flags = {};
dbg_create_info.messageSeverity = dbg_create_info.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose |
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) | vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo |
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError;
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT); dbg_create_info.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
dbg_create_info.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance;
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) |
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT);
dbg_create_info.pfnUserCallback = VulkanDebugMessengerCallback; dbg_create_info.pfnUserCallback = VulkanDebugMessengerCallback;
dbg_create_info.pUserData = nullptr; dbg_create_info.pUserData = nullptr;
VkInstanceCreateInfo inst_info {}; vk::InstanceCreateInfo inst_info {};
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; inst_info.sType = vk::StructureType::eInstanceCreateInfo;
inst_info.pNext = (r.enable_validation_layers ? &dbg_create_info : nullptr); inst_info.pNext = (r.enable_validation_layers ? &dbg_create_info : nullptr);
inst_info.flags = 0; inst_info.flags = {};
inst_info.pApplicationInfo = &app_info; inst_info.pApplicationInfo = &app_info;
inst_info.enabledExtensionCount = static_cast<uint32_t>(r.required_extensions.size()); inst_info.enabledExtensionCount = static_cast<uint32_t>(r.required_extensions.size());
inst_info.ppEnabledExtensionNames = r.required_extensions.data(); inst_info.ppEnabledExtensionNames = r.required_extensions.data();
@@ -1040,25 +1040,31 @@ void VulkanCreate(WindowContext* ctx) {
inst_info.ppEnabledLayerNames = inst_info.ppEnabledLayerNames =
(r.enable_validation_layers ? r.required_layers.data() : nullptr); (r.enable_validation_layers ? r.required_layers.data() : nullptr);
const VkResult result = vkCreateInstance(&inst_info, nullptr, &ctx->graphic_ctx.instance); const vk::Result result = vk::createInstance(&inst_info, nullptr, &ctx->graphic_ctx.instance);
switch (result) { switch (result) {
case VK_SUCCESS: break; case vk::Result::eSuccess: break;
case VK_ERROR_INCOMPATIBLE_DRIVER: EXIT("Unable to find a compatible Vulkan Driver"); case vk::Result::eErrorIncompatibleDriver:
EXIT("Unable to find a compatible Vulkan Driver");
default: EXIT("Could not create a Vulkan instance (for unknown reasons)"); default: EXIT("Could not create a Vulkan instance (for unknown reasons)");
} }
VULKAN_HPP_DEFAULT_DISPATCHER.init(ctx->graphic_ctx.instance);
if (r.enable_validation_layers) { if (r.enable_validation_layers) {
dbg_create_info.pNext = nullptr; dbg_create_info.pNext = nullptr;
if (VulkanCreateDebugUtilsMessengerEXT(ctx->graphic_ctx.instance, &dbg_create_info, nullptr, if (VulkanCreateDebugUtilsMessengerEXT(ctx->graphic_ctx.instance, &dbg_create_info, nullptr,
&ctx->graphic_ctx.debug_messenger) != VK_SUCCESS) { &ctx->graphic_ctx.debug_messenger) !=
vk::Result::eSuccess) {
EXIT("Could not create debug messenger"); EXIT("Could not create debug messenger");
} }
} }
if (SDL_Vulkan_CreateSurface(ctx->window, ctx->graphic_ctx.instance, &ctx->surface) == vk::SurfaceKHR::CType native_surface = VK_NULL_HANDLE;
SDL_FALSE) { if (SDL_Vulkan_CreateSurface(ctx->window,
static_cast<vk::Instance::CType>(ctx->graphic_ctx.instance),
&native_surface) == SDL_FALSE) {
EXIT("Could not create a Vulkan surface"); EXIT("Could not create a Vulkan surface");
} }
ctx->surface = native_surface;
std::vector<const char*> device_extensions = { std::vector<const char*> device_extensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME,
@@ -1082,22 +1088,21 @@ void VulkanCreate(WindowContext* ctx) {
EXIT("Could not find suitable device"); EXIT("Could not find suitable device");
} }
vkGetPhysicalDeviceProperties(ctx->graphic_ctx.physical_device, ctx->graphic_ctx.physical_device.getProperties(&ctx->graphic_ctx.physical_device_properties);
&ctx->graphic_ctx.physical_device_properties); ctx->graphic_ctx.physical_device.getMemoryProperties(
vkGetPhysicalDeviceMemoryProperties(ctx->graphic_ctx.physical_device, &ctx->graphic_ctx.physical_device_memory_properties);
&ctx->graphic_ctx.physical_device_memory_properties);
const auto& device_properties = ctx->graphic_ctx.GetPhysicalDeviceProperties(); const auto& device_properties = ctx->graphic_ctx.GetPhysicalDeviceProperties();
LOGF("Select device: %s\n", device_properties.deviceName); LOGF("Select device: %s\n", device_properties.deviceName.data());
{ {
uint32_t extensions_count = 0; uint32_t extensions_count = 0;
vkEnumerateDeviceExtensionProperties(ctx->graphic_ctx.physical_device, nullptr, ctx->graphic_ctx.physical_device.enumerateDeviceExtensionProperties(
&extensions_count, nullptr); nullptr, &extensions_count, nullptr);
std::vector<VkExtensionProperties> available_extensions(extensions_count); std::vector<vk::ExtensionProperties> available_extensions(extensions_count);
vkEnumerateDeviceExtensionProperties(ctx->graphic_ctx.physical_device, nullptr, ctx->graphic_ctx.physical_device.enumerateDeviceExtensionProperties(
&extensions_count, available_extensions.data()); nullptr, &extensions_count, available_extensions.data());
if (HasExtension(available_extensions, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME)) { if (HasExtension(available_extensions, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME)) {
device_extensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); device_extensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
@@ -1119,6 +1124,7 @@ void VulkanCreate(WindowContext* ctx) {
if (ctx->graphic_ctx.device == nullptr) { if (ctx->graphic_ctx.device == nullptr) {
EXIT("Could not create device"); EXIT("Could not create device");
} }
VULKAN_HPP_DEFAULT_DISPATCHER.init(ctx->graphic_ctx.device);
if (!VulkanCreateAllocator(&ctx->graphic_ctx)) { if (!VulkanCreateAllocator(&ctx->graphic_ctx)) {
EXIT("Could not create Vulkan memory allocator"); EXIT("Could not create Vulkan memory allocator");
+2 -2
View File
@@ -32,6 +32,7 @@
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h" #include "graphics/host_gpu/vma.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/renderDoc.h" #include "graphics/presentation/renderDoc.h"
#include "graphics/presentation/videoOut.h" #include "graphics/presentation/videoOut.h"
#include "graphics/presentation/window/windowInternal.h" #include "graphics/presentation/window/windowInternal.h"
@@ -45,7 +46,6 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include <vulkan/vk_enum_string_helper.h>
#include <vulkan/vk_platform.h> #include <vulkan/vk_platform.h>
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
@@ -1035,7 +1035,7 @@ void WindowRun() {
std::_Exit(0); std::_Exit(0);
} }
VkSurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities() { vk::SurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities() {
EXIT_IF(g_window_ctx == nullptr); EXIT_IF(g_window_ctx == nullptr);
Common::LockGuard lock(g_window_ctx->mutex); Common::LockGuard lock(g_window_ctx->mutex);
@@ -4,21 +4,21 @@
#include "SDL_video.h" #include "SDL_video.h"
#include "common/threads.h" #include "common/threads.h"
#include "graphics/host_gpu/graphicContext.h" #include "graphics/host_gpu/graphicContext.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics { namespace Libs::Graphics {
struct WindowGame; struct WindowGame;
struct SurfaceCapabilities { struct SurfaceCapabilities {
VkSurfaceCapabilitiesKHR capabilities {}; vk::SurfaceCapabilitiesKHR capabilities {};
std::vector<VkSurfaceFormatKHR> formats; std::vector<vk::SurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> present_modes; std::vector<vk::PresentModeKHR> present_modes;
bool format_srgb_bgra32 = false; bool format_srgb_bgra32 = false;
bool format_unorm_bgra32 = false; bool format_unorm_bgra32 = false;
}; };
struct WindowContext { struct WindowContext {
@@ -26,7 +26,7 @@ struct WindowContext {
VulkanSwapchain* swapchain = nullptr; VulkanSwapchain* swapchain = nullptr;
SDL_Window* window = nullptr; SDL_Window* window = nullptr;
bool window_hidden = true; bool window_hidden = true;
VkSurfaceKHR surface = nullptr; vk::SurfaceKHR surface = nullptr;
SurfaceCapabilities* surface_capabilities = nullptr; SurfaceCapabilities* surface_capabilities = nullptr;
WindowGame* game = nullptr; WindowGame* game = nullptr;
@@ -40,7 +40,7 @@ struct WindowContext {
extern WindowContext* g_window_ctx; extern WindowContext* g_window_ctx;
void VulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, void VulkanGetSurfaceCapabilities(vk::PhysicalDevice physical_device, vk::SurfaceKHR surface,
SurfaceCapabilities* capabilities); SurfaceCapabilities* capabilities);
VulkanSwapchain* VulkanCreateSwapchain(GraphicContext* ctx, uint32_t image_count); VulkanSwapchain* VulkanCreateSwapchain(GraphicContext* ctx, uint32_t image_count);
void VulkanCreate(WindowContext* ctx); void VulkanCreate(WindowContext* ctx);
+9 -29
View File
@@ -9,7 +9,7 @@
namespace Libs::Graphics::Rt { namespace Libs::Graphics::Rt {
namespace { namespace {
bool ExtensionAvailable(const std::vector<VkExtensionProperties>& available, const char* name) { bool ExtensionAvailable(const std::vector<vk::ExtensionProperties>& available, const char* name) {
return std::ranges::any_of(available, [name](const auto& extension) { return std::ranges::any_of(available, [name](const auto& extension) {
return std::strcmp(extension.extensionName, name) == 0; return std::strcmp(extension.extensionName, name) == 0;
}); });
@@ -26,7 +26,7 @@ void AppendExtensionIfMissing(std::vector<const char*>& extensions, const char*
} // namespace } // namespace
void AppendHardwareRayTracingDeviceExtensions( void AppendHardwareRayTracingDeviceExtensions(
const std::vector<VkExtensionProperties>& available_extensions, const std::vector<vk::ExtensionProperties>& available_extensions,
std::vector<const char*>* device_extensions, GraphicContext* ctx) { std::vector<const char*>* device_extensions, GraphicContext* ctx) {
EXIT_IF(device_extensions == nullptr || ctx == nullptr); EXIT_IF(device_extensions == nullptr || ctx == nullptr);
@@ -64,33 +64,13 @@ void LoadHardwareRayTracingFunctions(GraphicContext* ctx) {
return; return;
} }
ctx->vkGetBufferDeviceAddressKHR = reinterpret_cast<PFN_vkGetBufferDeviceAddressKHR>( const auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER;
vkGetDeviceProcAddr(ctx->device, "vkGetBufferDeviceAddressKHR")); if (dispatcher.vkGetBufferDeviceAddressKHR == nullptr ||
if (ctx->vkGetBufferDeviceAddressKHR == nullptr) { dispatcher.vkCreateAccelerationStructureKHR == nullptr ||
ctx->vkGetBufferDeviceAddressKHR = reinterpret_cast<PFN_vkGetBufferDeviceAddressKHR>( dispatcher.vkDestroyAccelerationStructureKHR == nullptr ||
vkGetDeviceProcAddr(ctx->device, "vkGetBufferDeviceAddress")); dispatcher.vkGetAccelerationStructureBuildSizesKHR == nullptr ||
} dispatcher.vkCmdBuildAccelerationStructuresKHR == nullptr ||
ctx->vkCreateAccelerationStructureKHR = reinterpret_cast<PFN_vkCreateAccelerationStructureKHR>( dispatcher.vkGetAccelerationStructureDeviceAddressKHR == nullptr) {
vkGetDeviceProcAddr(ctx->device, "vkCreateAccelerationStructureKHR"));
ctx->vkDestroyAccelerationStructureKHR =
reinterpret_cast<PFN_vkDestroyAccelerationStructureKHR>(
vkGetDeviceProcAddr(ctx->device, "vkDestroyAccelerationStructureKHR"));
ctx->vkGetAccelerationStructureBuildSizesKHR =
reinterpret_cast<PFN_vkGetAccelerationStructureBuildSizesKHR>(
vkGetDeviceProcAddr(ctx->device, "vkGetAccelerationStructureBuildSizesKHR"));
ctx->vkCmdBuildAccelerationStructuresKHR =
reinterpret_cast<PFN_vkCmdBuildAccelerationStructuresKHR>(
vkGetDeviceProcAddr(ctx->device, "vkCmdBuildAccelerationStructuresKHR"));
ctx->vkGetAccelerationStructureDeviceAddressKHR =
reinterpret_cast<PFN_vkGetAccelerationStructureDeviceAddressKHR>(
vkGetDeviceProcAddr(ctx->device, "vkGetAccelerationStructureDeviceAddressKHR"));
if (ctx->vkGetBufferDeviceAddressKHR == nullptr ||
ctx->vkCreateAccelerationStructureKHR == nullptr ||
ctx->vkDestroyAccelerationStructureKHR == nullptr ||
ctx->vkGetAccelerationStructureBuildSizesKHR == nullptr ||
ctx->vkCmdBuildAccelerationStructuresKHR == nullptr ||
ctx->vkGetAccelerationStructureDeviceAddressKHR == nullptr) {
EXIT("Vulkan RT: failed to load required device functions\n"); EXIT("Vulkan RT: failed to load required device functions\n");
} }
} }
+1 -1
View File
@@ -10,7 +10,7 @@ namespace Libs::Graphics {
namespace Rt { namespace Rt {
void AppendHardwareRayTracingDeviceExtensions( void AppendHardwareRayTracingDeviceExtensions(
const std::vector<VkExtensionProperties>& available_extensions, const std::vector<vk::ExtensionProperties>& available_extensions,
std::vector<const char*>* device_extensions, GraphicContext* ctx); std::vector<const char*>* device_extensions, GraphicContext* ctx);
void LoadHardwareRayTracingFunctions(GraphicContext* ctx); void LoadHardwareRayTracingFunctions(GraphicContext* ctx);
File diff suppressed because it is too large. Load diff
+33 -31
View File
@@ -411,14 +411,16 @@ constexpr uint32_t EncodeSopp(uint32_t opcode, uint32_t simm = 0) {
void TestNativeShaderResourceDependencies() { void TestNativeShaderResourceDependencies() {
const auto stages = ShaderPipelineStages( const auto stages = ShaderPipelineStages(
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT); vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment |
Check(stages == (VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | vk::ShaderStageFlagBits::eCompute);
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT), Check(stages == (vk::PipelineStageFlagBits::eVertexShader |
vk::PipelineStageFlagBits::eFragmentShader |
vk::PipelineStageFlagBits::eComputeShader),
"shader-stage dependency mapping was not exact"); "shader-stage dependency mapping was not exact");
const auto shader_barrier = MakeShaderWriteDependency(); const auto shader_barrier = MakeShaderWriteDependency();
Check(shader_barrier.srcAccessMask == VK_ACCESS_SHADER_WRITE_BIT && Check(shader_barrier.srcAccessMask == vk::AccessFlagBits::eShaderWrite &&
(shader_barrier.dstAccessMask & VK_ACCESS_SHADER_READ_BIT) != 0 && (shader_barrier.dstAccessMask & vk::AccessFlagBits::eShaderRead) &&
(shader_barrier.dstAccessMask & VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT) != 0, (shader_barrier.dstAccessMask & vk::AccessFlagBits::eVertexAttributeRead),
"shader-write dependency does not expose draw/dispatch buffer writes"); "shader-write dependency does not expose draw/dispatch buffer writes");
ShaderRecompiler::IR::Program program; ShaderRecompiler::IR::Program program;
@@ -445,27 +447,27 @@ void TestNativeShaderResourceDependencies() {
"graphics/compute write collector lost or invented a storage-buffer range"); "graphics/compute write collector lost or invented a storage-buffer range");
VulkanImage image {VulkanImageType::StorageTexture}; VulkanImage image {VulkanImageType::StorageTexture};
image.image = reinterpret_cast<VkImage>(uintptr_t {1}); image.image = reinterpret_cast<vk::Image::CType>(uintptr_t {1});
image.layout = VK_IMAGE_LAYOUT_GENERAL; image.layout = vk::ImageLayout::eGeneral;
image.layers = 3; image.layers = 3;
const auto image_barrier = MakeStorageImageDependency(image, true, true); const auto image_barrier = MakeStorageImageDependency(image, true, true);
Check(image_barrier.oldLayout == VK_IMAGE_LAYOUT_GENERAL && Check(image_barrier.oldLayout == vk::ImageLayout::eGeneral &&
image_barrier.newLayout == VK_IMAGE_LAYOUT_GENERAL && image_barrier.newLayout == vk::ImageLayout::eGeneral &&
(image_barrier.srcAccessMask & VK_ACCESS_MEMORY_WRITE_BIT) != 0 && (image_barrier.srcAccessMask & vk::AccessFlagBits::eMemoryWrite) &&
(image_barrier.dstAccessMask & VK_ACCESS_SHADER_READ_BIT) != 0 && (image_barrier.dstAccessMask & vk::AccessFlagBits::eShaderRead) &&
(image_barrier.dstAccessMask & VK_ACCESS_SHADER_WRITE_BIT) != 0 && (image_barrier.dstAccessMask & vk::AccessFlagBits::eShaderWrite) &&
image_barrier.subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS && image_barrier.subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS &&
image_barrier.subresourceRange.layerCount == image.layers, image_barrier.subresourceRange.layerCount == image.layers,
"GENERAL storage-image dependency lacks a complete memory barrier"); "GENERAL storage-image dependency lacks a complete memory barrier");
VulkanBuffer buffer; VulkanBuffer buffer;
buffer.buffer = reinterpret_cast<VkBuffer>(uintptr_t {1}); buffer.buffer = reinterpret_cast<vk::Buffer::CType>(uintptr_t {1});
const auto gds_barrier = MakeGdsDependency(buffer); const auto gds_barrier = MakeGdsDependency(buffer);
Check((gds_barrier.srcAccessMask & VK_ACCESS_HOST_WRITE_BIT) != 0 && Check((gds_barrier.srcAccessMask & vk::AccessFlagBits::eHostWrite) &&
(gds_barrier.srcAccessMask & VK_ACCESS_TRANSFER_WRITE_BIT) != 0 && (gds_barrier.srcAccessMask & vk::AccessFlagBits::eTransferWrite) &&
(gds_barrier.srcAccessMask & VK_ACCESS_SHADER_WRITE_BIT) != 0 && (gds_barrier.srcAccessMask & vk::AccessFlagBits::eShaderWrite) &&
gds_barrier.dstAccessMask == gds_barrier.dstAccessMask ==
(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT) && (vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite) &&
gds_barrier.size == VK_WHOLE_SIZE, gds_barrier.size == VK_WHOLE_SIZE,
"GDS dependency does not order host/transfer/shader writes"); "GDS dependency does not order host/transfer/shader writes");
} }
@@ -476,21 +478,21 @@ void TestNativeSubgroupPolicy() {
context.min_subgroup_size = 32; context.min_subgroup_size = 32;
context.max_subgroup_size = 32; context.max_subgroup_size = 32;
context.subgroup_size_control_enabled = true; context.subgroup_size_control_enabled = true;
context.required_subgroup_size_stages = VK_SHADER_STAGE_ALL; context.required_subgroup_size_stages = vk::ShaderStageFlagBits::eAll;
ShaderRecompiler::IR::Program safe; ShaderRecompiler::IR::Program safe;
safe.wave_size = 32; safe.wave_size = 32;
safe.lane_mask_mode = ShaderLaneMaskMode::NativeWave; safe.lane_mask_mode = ShaderLaneMaskMode::NativeWave;
Check(ConfigureShaderSubgroup(context, VK_SHADER_STAGE_VERTEX_BIT, safe).mode == Check(ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eVertex, safe).mode ==
ShaderSubgroupMode::Natural, ShaderSubgroupMode::Natural,
"native wave32 policy changed"); "native wave32 policy changed");
safe.wave_size = 64; safe.wave_size = 64;
Check(SelectGraphicsLaneMaskMode(context, safe.wave_size) == Check(SelectGraphicsLaneMaskMode(context, safe.wave_size) ==
ShaderLaneMaskMode::PerInvocation && ShaderLaneMaskMode::PerInvocation &&
ConfigureShaderSubgroup(context, VK_SHADER_STAGE_VERTEX_BIT, safe).mode == ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eVertex, safe).mode ==
ShaderSubgroupMode::Unsupported, ShaderSubgroupMode::Unsupported,
"wave64 graphics mismatch accepted native-wave mask lowering"); "wave64 graphics mismatch accepted native-wave mask lowering");
safe.lane_mask_mode = ShaderLaneMaskMode::PerInvocation; safe.lane_mask_mode = ShaderLaneMaskMode::PerInvocation;
Check(ConfigureShaderSubgroup(context, VK_SHADER_STAGE_VERTEX_BIT, safe).mode == Check(ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eVertex, safe).mode ==
ShaderSubgroupMode::PerInvocationGraphics, ShaderSubgroupMode::PerInvocationGraphics,
"wave64 graphics mismatch did not select per-invocation masks"); "wave64 graphics mismatch did not select per-invocation masks");
@@ -498,12 +500,12 @@ void TestNativeSubgroupPolicy() {
cross_lane.blocks.emplace_back().instructions.emplace_back().op = cross_lane.blocks.emplace_back().instructions.emplace_back().op =
ShaderRecompiler::IR::Opcode::ReadLaneU32; ShaderRecompiler::IR::Opcode::ReadLaneU32;
Check(ShaderRecompiler::Spirv::ProgramRequiresExactSubgroupSize(cross_lane) && Check(ShaderRecompiler::Spirv::ProgramRequiresExactSubgroupSize(cross_lane) &&
ConfigureShaderSubgroup(context, VK_SHADER_STAGE_VERTEX_BIT, cross_lane).mode == ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eVertex, cross_lane).mode ==
ShaderSubgroupMode::PerInvocationGraphics, ShaderSubgroupMode::PerInvocationGraphics,
"graphics mismatch did not select per-invocation masks"); "graphics mismatch did not select per-invocation masks");
auto cross_lane_compute = cross_lane; auto cross_lane_compute = cross_lane;
cross_lane_compute.lane_mask_mode = ShaderLaneMaskMode::NativeWave; cross_lane_compute.lane_mask_mode = ShaderLaneMaskMode::NativeWave;
Check(ConfigureShaderSubgroup(context, VK_SHADER_STAGE_COMPUTE_BIT, cross_lane_compute).mode == Check(ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eCompute, cross_lane_compute).mode ==
ShaderSubgroupMode::Unsupported, ShaderSubgroupMode::Unsupported,
"cross-lane compute mismatch bypassed the exact subgroup requirement"); "cross-lane compute mismatch bypassed the exact subgroup requirement");
@@ -519,7 +521,7 @@ void TestNativeSubgroupPolicy() {
zero_bfm.src_count = 2; zero_bfm.src_count = 2;
zero_bfm.scalar_sources[0] = 2; zero_bfm.scalar_sources[0] = 2;
Check(!ShaderRecompiler::Spirv::ProgramRequiresExactSubgroupSize(zero_exec) && Check(!ShaderRecompiler::Spirv::ProgramRequiresExactSubgroupSize(zero_exec) &&
ConfigureShaderSubgroup(context, VK_SHADER_STAGE_COMPUTE_BIT, zero_exec).mode == ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eCompute, zero_exec).mode ==
ShaderSubgroupMode::FlattenedMasks, ShaderSubgroupMode::FlattenedMasks,
"compile-time uniform-zero EXEC write did not stay on the mask-free path"); "compile-time uniform-zero EXEC write did not stay on the mask-free path");
@@ -550,23 +552,23 @@ void TestNativeSubgroupPolicy() {
ds_partial.lane_mask_mode = ShaderLaneMaskMode::NativeWave; ds_partial.lane_mask_mode = ShaderLaneMaskMode::NativeWave;
ds_partial.blocks.emplace_back().instructions.emplace_back().op = ds_partial.blocks.emplace_back().instructions.emplace_back().op =
ShaderRecompiler::IR::Opcode::DsAppend; ShaderRecompiler::IR::Opcode::DsAppend;
Check(ConfigureShaderSubgroup(context, VK_SHADER_STAGE_COMPUTE_BIT, ds_partial).mode == Check(ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eCompute, ds_partial).mode ==
ShaderSubgroupMode::Unsupported, ShaderSubgroupMode::Unsupported,
"partial wave64 DS append bypassed the exact subgroup requirement"); "partial wave64 DS append bypassed the exact subgroup requirement");
context.max_subgroup_size = 64; context.max_subgroup_size = 64;
const auto controlled = const auto controlled =
ConfigureShaderSubgroup(context, VK_SHADER_STAGE_COMPUTE_BIT, cross_lane_compute); ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eCompute, cross_lane_compute);
Check(controlled.mode == ShaderSubgroupMode::Controlled && controlled.required_size == 64, Check(controlled.mode == ShaderSubgroupMode::Controlled && controlled.required_size == 64,
"supported controlled wave64 was not preferred over splitting"); "supported controlled wave64 was not preferred over splitting");
context.subgroup_size = 64; context.subgroup_size = 64;
context.subgroup_size_control_enabled = false; context.subgroup_size_control_enabled = false;
cross_lane.wave_size = 32; cross_lane.wave_size = 32;
cross_lane.lane_mask_mode = ShaderLaneMaskMode::PerInvocation; cross_lane.lane_mask_mode = ShaderLaneMaskMode::PerInvocation;
Check(ConfigureShaderSubgroup(context, VK_SHADER_STAGE_FRAGMENT_BIT, cross_lane).mode == Check(ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eFragment, cross_lane).mode ==
ShaderSubgroupMode::Unsupported, ShaderSubgroupMode::Unsupported,
"inverse graphics mismatch was accepted as one guest wave"); "inverse graphics mismatch was accepted as one guest wave");
cross_lane_compute.wave_size = 32; cross_lane_compute.wave_size = 32;
Check(ConfigureShaderSubgroup(context, VK_SHADER_STAGE_COMPUTE_BIT, cross_lane_compute).mode == Check(ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eCompute, cross_lane_compute).mode ==
ShaderSubgroupMode::Unsupported, ShaderSubgroupMode::Unsupported,
"inverse cross-lane compute mismatch was accepted"); "inverse cross-lane compute mismatch was accepted");
} }
@@ -5720,7 +5722,7 @@ void TestRenderTargetReverseFloat16ExportMapping() {
TextureGetRenderTargetFormat(Prospero::GpuEnumValue(Prospero::ChannelLayout::k16_16_16_16), TextureGetRenderTargetFormat(Prospero::GpuEnumValue(Prospero::ChannelLayout::k16_16_16_16),
Prospero::GpuEnumValue(Prospero::ChannelType::kFloat), Prospero::GpuEnumValue(Prospero::ChannelType::kFloat),
Prospero::GpuEnumValue(Prospero::ChannelOrder::kReversed)); Prospero::GpuEnumValue(Prospero::ChannelOrder::kReversed));
Check(format.format == VK_FORMAT_R16G16B16A16_SFLOAT && format.bytes_per_element == 8u, Check(format.format == vk::Format::eR16G16B16A16Sfloat && format.bytes_per_element == 8u,
"reverse RGBA16F render target did not retain its native host format " "reverse RGBA16F render target did not retain its native host format "
"and size"); "and size");
Check(format.export_mapping == Prospero::ColorMappingAbgr && Check(format.export_mapping == Prospero::ColorMappingAbgr &&
@@ -5735,7 +5737,7 @@ void TestRenderTargetReverseFloat16ExportMapping() {
Prospero::GpuEnumValue(Prospero::ChannelLayout::k8_8_8_8), Prospero::GpuEnumValue(Prospero::ChannelLayout::k8_8_8_8),
Prospero::GpuEnumValue(Prospero::ChannelType::kUNorm), Prospero::GpuEnumValue(Prospero::ChannelType::kUNorm),
Prospero::GpuEnumValue(Prospero::ChannelOrder::kAlt)); Prospero::GpuEnumValue(Prospero::ChannelOrder::kAlt));
Check(legacy_alt.format == VK_FORMAT_B8G8R8A8_UNORM && legacy_alt.export_mapping.IsIdentity(), Check(legacy_alt.format == vk::Format::eB8G8R8A8Unorm && legacy_alt.export_mapping.IsIdentity(),
"legacy BGRA render target acquired a duplicate shader export mapping"); "legacy BGRA render target acquired a duplicate shader export mapping");
const uint32_t shader[] = { const uint32_t shader[] = {