graphics: migrate Vulkan backend to Vulkan-Hpp

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

View File

@ -5,30 +5,6 @@ add_subdirectory(cpuinfo)
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
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_EXECUTABLES ON CACHE BOOL "" FORCE)
set(SKIP_SPIRV_TOOLS_INSTALL ON CACHE BOOL "" FORCE)

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")
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
${CMAKE_CURRENT_SOURCE_DIR}
@ -194,10 +194,6 @@ set(inc_headers
${KYTY_THIRD_PARTY_DIR}/stb
)
if(DEFINED ENV{VULKAN_SDK})
list(APPEND inc_headers $ENV{VULKAN_SDK}/Include)
endif()
if (KYTY_CLANG_CL)
list(APPEND kyty_emulator_link_libraries winpthread)
list(APPEND inc_headers

View File

@ -8,80 +8,81 @@ namespace Libs::Graphics::Prospero {
namespace {
constexpr FormatInfo kFormatInfo[] = {
{GpuEnumValue(BufferFormat::k8UNorm), VK_FORMAT_R8_UNORM, 1, 0, 1, true, false},
{GpuEnumValue(BufferFormat::k8SNorm), VK_FORMAT_UNDEFINED, 0, 0, 1, false, false},
{GpuEnumValue(BufferFormat::k8UInt), VK_FORMAT_R8_UINT, 1, 0, 1, true, true},
{GpuEnumValue(BufferFormat::k16UNorm), VK_FORMAT_R16_UNORM, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k16SNorm), VK_FORMAT_R16_SNORM, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k16UInt), VK_FORMAT_R16_UINT, 2, 0, 2, true, true},
{GpuEnumValue(BufferFormat::k16SInt), VK_FORMAT_R16_SINT, 2, 0, 2, false, false},
{GpuEnumValue(BufferFormat::k16Float), VK_FORMAT_R16_SFLOAT, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k8_8UNorm), VK_FORMAT_R8G8_UNORM, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k8_8SNorm), VK_FORMAT_R8G8_SNORM, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k8_8UInt), VK_FORMAT_R8G8_UINT, 2, 0, 2, true, true},
{GpuEnumValue(BufferFormat::k8_8SInt), VK_FORMAT_R8G8_SINT, 2, 0, 2, false, false},
{GpuEnumValue(BufferFormat::k32UInt), VK_FORMAT_R32_UINT, 4, 0, 4, true, true},
{GpuEnumValue(BufferFormat::k32SInt), VK_FORMAT_R32_SINT, 4, 0, 4, false, false},
{GpuEnumValue(BufferFormat::k32Float), VK_FORMAT_R32_SFLOAT, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k16_16UNorm), VK_FORMAT_R16G16_UNORM, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k16_16SNorm), VK_FORMAT_R16G16_SNORM, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k16_16UInt), VK_FORMAT_R16G16_UINT, 4, 0, 4, true, true},
{GpuEnumValue(BufferFormat::k16_16SInt), VK_FORMAT_R16G16_SINT, 4, 0, 4, false, false},
{GpuEnumValue(BufferFormat::k16_16Float), VK_FORMAT_R16G16_SFLOAT, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k11_11_10Float), VK_FORMAT_B10G11R11_UFLOAT_PACK32, 4, 0, 4, true,
{GpuEnumValue(BufferFormat::k8UNorm), vk::Format::eR8Unorm, 1, 0, 1, true, false},
{GpuEnumValue(BufferFormat::k8SNorm), vk::Format::eUndefined, 0, 0, 1, false, false},
{GpuEnumValue(BufferFormat::k8UInt), vk::Format::eR8Uint, 1, 0, 1, true, true},
{GpuEnumValue(BufferFormat::k16UNorm), vk::Format::eR16Unorm, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k16SNorm), vk::Format::eR16Snorm, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k16UInt), vk::Format::eR16Uint, 2, 0, 2, true, true},
{GpuEnumValue(BufferFormat::k16SInt), vk::Format::eR16Sint, 2, 0, 2, false, false},
{GpuEnumValue(BufferFormat::k16Float), vk::Format::eR16Sfloat, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k8_8UNorm), vk::Format::eR8G8Unorm, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k8_8SNorm), vk::Format::eR8G8Snorm, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k8_8UInt), vk::Format::eR8G8Uint, 2, 0, 2, true, true},
{GpuEnumValue(BufferFormat::k8_8SInt), vk::Format::eR8G8Sint, 2, 0, 2, false, false},
{GpuEnumValue(BufferFormat::k32UInt), vk::Format::eR32Uint, 4, 0, 4, true, true},
{GpuEnumValue(BufferFormat::k32SInt), vk::Format::eR32Sint, 4, 0, 4, false, false},
{GpuEnumValue(BufferFormat::k32Float), vk::Format::eR32Sfloat, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k16_16UNorm), vk::Format::eR16G16Unorm, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k16_16SNorm), vk::Format::eR16G16Snorm, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k16_16UInt), vk::Format::eR16G16Uint, 4, 0, 4, true, true},
{GpuEnumValue(BufferFormat::k16_16SInt), vk::Format::eR16G16Sint, 4, 0, 4, false, false},
{GpuEnumValue(BufferFormat::k16_16Float), vk::Format::eR16G16Sfloat, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k11_11_10Float), vk::Format::eB10G11R11UfloatPack32, 4, 0, 4, true,
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},
{GpuEnumValue(BufferFormat::k8_8_8_8UNorm), VK_FORMAT_R8G8B8A8_UNORM, 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_8UInt), VK_FORMAT_R8G8B8A8_UINT, 4, 0, 4, true, true},
{GpuEnumValue(BufferFormat::k8_8_8_8SInt), VK_FORMAT_R8G8B8A8_SINT, 4, 0, 4, false, false},
{GpuEnumValue(BufferFormat::k32_32UInt), VK_FORMAT_R32G32_UINT, 8, 0, 8, true, true},
{GpuEnumValue(BufferFormat::k32_32SInt), VK_FORMAT_R32G32_SINT, 8, 0, 8, false, false},
{GpuEnumValue(BufferFormat::k32_32Float), VK_FORMAT_R32G32_SFLOAT, 8, 0, 8, true, false},
{GpuEnumValue(BufferFormat::k16_16_16_16UNorm), VK_FORMAT_R16G16B16A16_UNORM, 8, 0, 8, true,
{GpuEnumValue(BufferFormat::k8_8_8_8UNorm), vk::Format::eR8G8B8A8Unorm, 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::eR8G8B8A8Uint, 4, 0, 4, true, true},
{GpuEnumValue(BufferFormat::k8_8_8_8SInt), vk::Format::eR8G8B8A8Sint, 4, 0, 4, false, false},
{GpuEnumValue(BufferFormat::k32_32UInt), vk::Format::eR32G32Uint, 8, 0, 8, true, true},
{GpuEnumValue(BufferFormat::k32_32SInt), vk::Format::eR32G32Sint, 8, 0, 8, false, false},
{GpuEnumValue(BufferFormat::k32_32Float), vk::Format::eR32G32Sfloat, 8, 0, 8, true, false},
{GpuEnumValue(BufferFormat::k16_16_16_16UNorm), vk::Format::eR16G16B16A16Unorm, 8, 0, 8, true,
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},
{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},
{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},
{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},
{GpuEnumValue(BufferFormat::k32_32_32UInt), VK_FORMAT_R32G32B32_UINT, 12, 0, 12, true, true},
{GpuEnumValue(BufferFormat::k32_32_32SInt), VK_FORMAT_R32G32B32_SINT, 12, 0, 12, false, false},
{GpuEnumValue(BufferFormat::k32_32_32Float), VK_FORMAT_R32G32B32_SFLOAT, 12, 0, 12, true,
{GpuEnumValue(BufferFormat::k32_32_32UInt), vk::Format::eR32G32B32Uint, 12, 0, 12, true, true},
{GpuEnumValue(BufferFormat::k32_32_32SInt), vk::Format::eR32G32B32Sint, 12, 0, 12, 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},
{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},
{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},
{GpuEnumValue(BufferFormat::k8_8_8_8Srgb), VK_FORMAT_R8G8B8A8_SRGB, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k9_9_9_5Float), VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 4, 0, 0, true,
{GpuEnumValue(BufferFormat::k5_6_5UNorm), vk::Format::eB5G6R5UnormPack16, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k5_5_5_1UNorm), vk::Format::eR5G5B5A1UnormPack16, 2, 0, 2, true,
false},
{GpuEnumValue(BufferFormat::k5_6_5UNorm), VK_FORMAT_B5G6R5_UNORM_PACK16, 2, 0, 2, true, false},
{GpuEnumValue(BufferFormat::k5_5_5_1UNorm), VK_FORMAT_R5G5B5A1_UNORM_PACK16, 2, 0, 2, true,
{GpuEnumValue(BufferFormat::k4_4_4_4UNorm), vk::Format::eR4G4B4A4UnormPack16, 2, 0, 2, true,
false},
{GpuEnumValue(BufferFormat::k4_4_4_4UNorm), VK_FORMAT_R4G4B4A4_UNORM_PACK16, 2, 0, 2, true,
false},
{GpuEnumValue(BufferFormat::kFmask8_S4_F4), VK_FORMAT_R32_SFLOAT, 1, 0, 1, true, false},
{GpuEnumValue(BufferFormat::kBc1UNorm), VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc1Srgb), VK_FORMAT_BC1_RGBA_SRGB_BLOCK, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc2UNorm), VK_FORMAT_BC2_UNORM_BLOCK, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc2Srgb), VK_FORMAT_BC2_SRGB_BLOCK, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc3UNorm), VK_FORMAT_BC3_UNORM_BLOCK, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc3Srgb), VK_FORMAT_BC3_SRGB_BLOCK, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc4UNorm), VK_FORMAT_BC4_UNORM_BLOCK, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc4SNorm), VK_FORMAT_BC4_SNORM_BLOCK, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc5UNorm), VK_FORMAT_BC5_UNORM_BLOCK, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc5SNorm), VK_FORMAT_BC5_SNORM_BLOCK, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc6UFloat), VK_FORMAT_BC6H_UFLOAT_BLOCK, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc6SFloat), VK_FORMAT_BC6H_SFLOAT_BLOCK, 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},
{GpuEnumValue(BufferFormat::kFmask8_S4_F4), vk::Format::eR32Sfloat, 1, 0, 1, true, false},
{GpuEnumValue(BufferFormat::kBc1UNorm), vk::Format::eBc1RgbaUnormBlock, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc1Srgb), vk::Format::eBc1RgbaSrgbBlock, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc2UNorm), vk::Format::eBc2UnormBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc2Srgb), vk::Format::eBc2SrgbBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc3UNorm), vk::Format::eBc3UnormBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc3Srgb), vk::Format::eBc3SrgbBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc4UNorm), vk::Format::eBc4UnormBlock, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc4SNorm), vk::Format::eBc4SnormBlock, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc5UNorm), vk::Format::eBc5UnormBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc5SNorm), vk::Format::eBc5SnormBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc6UFloat), vk::Format::eBc6HUfloatBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc6SFloat), vk::Format::eBc6HSfloatBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc7UNorm), vk::Format::eBc7UnormBlock, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc7Srgb), vk::Format::eBc7SrgbBlock, 0, 16, 0, true, false},
};
constexpr auto MakeFormatInfoLookup() {
@ -105,9 +106,9 @@ const FormatInfo* FindFormatInfo(uint32_t format) {
return format < kFormatInfoLookup.size() ? kFormatInfoLookup[format] : nullptr;
}
VkFormat SurfaceFormat(uint32_t format) {
vk::Format SurfaceFormat(uint32_t 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) {

View File

@ -2,25 +2,25 @@
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GUEST_GPU_GPU_FORMAT_H_
#include "common/common.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <span>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics::Prospero {
struct FormatInfo {
uint32_t format = 0;
VkFormat vk_format = VK_FORMAT_UNDEFINED;
uint32_t bytes_per_element = 0;
uint32_t block_compressed_bytes_per_block = 0;
uint32_t render_target_bytes_per_element = 0;
bool supported_sampled_texture_format = false;
bool unsigned_integer_texture_format = false;
uint32_t format = 0;
vk::Format vk_format = vk::Format::eUndefined;
uint32_t bytes_per_element = 0;
uint32_t block_compressed_bytes_per_block = 0;
uint32_t render_target_bytes_per_element = 0;
bool supported_sampled_texture_format = false;
bool unsigned_integer_texture_format = false;
};
std::span<const FormatInfo> Formats();
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 BlockCompressedBytesPerBlock(uint32_t format);
uint32_t RenderTargetBytesPerElement(uint32_t format);

View File

@ -4,13 +4,13 @@
#include "common/abi.h"
#include "common/common.h"
#include "common/threads.h"
#include "graphics/host_gpu/vulkanCommon.h" // IWYU pragma: export
#include "graphics/host_gpu/vulkanInstance.h"
#include <memory>
#include <mutex>
#include <vector>
#include <vk_mem_alloc.h>
#include <vulkan/vulkan_core.h> // IWYU pragma: export
namespace Libs::Graphics {
@ -19,26 +19,26 @@ class CommandBuffer;
struct VulkanSwapchain {
~VulkanSwapchain();
VkSwapchainKHR swapchain = nullptr;
VkFormat swapchain_format = VK_FORMAT_UNDEFINED;
VkExtent2D swapchain_extent = {};
std::unique_ptr<VkImage[]> swapchain_images;
std::unique_ptr<VkImageView[]> swapchain_image_views;
uint32_t swapchain_images_count = 0;
std::unique_ptr<VkSemaphore[]> image_acquired_semaphores;
std::unique_ptr<VkSemaphore[]> render_complete_semaphores;
uint32_t current_index = 0;
uint32_t present_frame = 0;
vk::SwapchainKHR swapchain = nullptr;
vk::Format swapchain_format = vk::Format::eUndefined;
vk::Extent2D swapchain_extent = {};
std::unique_ptr<vk::Image[]> swapchain_images;
std::unique_ptr<vk::ImageView[]> swapchain_image_views;
uint32_t swapchain_images_count = 0;
std::unique_ptr<vk::Semaphore[]> image_acquired_semaphores;
std::unique_ptr<vk::Semaphore[]> render_complete_semaphores;
uint32_t current_index = 0;
uint32_t present_frame = 0;
};
struct VulkanCommandPool {
Common::Mutex mutex;
VkCommandPool pool = nullptr;
std::unique_ptr<VkCommandBuffer[]> buffers;
std::unique_ptr<VkFence[]> fences;
std::unique_ptr<VkSemaphore[]> semaphores;
std::unique_ptr<bool[]> busy;
uint32_t buffers_count = 0;
Common::Mutex mutex;
vk::CommandPool pool = nullptr;
std::unique_ptr<vk::CommandBuffer[]> buffers;
std::unique_ptr<vk::Fence[]> fences;
std::unique_ptr<vk::Semaphore[]> semaphores;
std::unique_ptr<bool[]> busy;
uint32_t buffers_count = 0;
};
struct GraphicContext: public VulkanInstance {
@ -47,14 +47,14 @@ struct GraphicContext: public VulkanInstance {
};
struct VulkanMemory {
VkMemoryRequirements requirements = {};
VkMemoryPropertyFlags property = 0;
VkDeviceMemory memory = nullptr;
VmaAllocation allocation = nullptr;
VmaAllocationInfo allocation_info = {};
VkDeviceSize offset = 0;
uint32_t type = 0;
uint64_t unique_id = 0;
vk::MemoryRequirements requirements = {};
vk::MemoryPropertyFlags property = {};
vk::DeviceMemory memory = nullptr;
VmaAllocation allocation = nullptr;
VmaAllocationInfo allocation_info = {};
vk::DeviceSize offset = 0;
uint32_t type = 0;
uint64_t unique_id = 0;
};
enum class VulkanImageType {
@ -67,22 +67,22 @@ enum class VulkanImageType {
};
struct ImageViewInfo {
VkFormat format = VK_FORMAT_UNDEFINED;
VkImageViewType type = VK_IMAGE_VIEW_TYPE_2D;
VkImageAspectFlags aspect = 0;
uint32_t base_level = 0;
uint32_t level_count = 0;
uint32_t base_layer = 0;
uint32_t layer_count = 1;
uint32_t swizzle = 0;
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT;
vk::Format format = vk::Format::eUndefined;
vk::ImageViewType type = vk::ImageViewType::e2D;
vk::ImageAspectFlags aspect = {};
uint32_t base_level = 0;
uint32_t level_count = 0;
uint32_t base_layer = 0;
uint32_t layer_count = 1;
uint32_t swizzle = 0;
vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eSampled;
bool operator==(const ImageViewInfo&) const = default;
};
struct CachedImageView {
ImageViewInfo info;
VkImageView view = nullptr;
vk::ImageView view = nullptr;
};
struct ImageViewCache {
@ -104,14 +104,14 @@ struct VulkanImage {
KYTY_CLASS_NO_COPY(VulkanImage);
VulkanImageType type = VulkanImageType::Unknown;
VkFormat format = VK_FORMAT_UNDEFINED;
VkExtent2D extent = {};
vk::Format format = vk::Format::eUndefined;
vk::Extent2D extent = {};
uint32_t guest_pitch = 0;
uint32_t layers = 1;
uint32_t mip_levels = 1;
VkImage image = nullptr;
VkImageView image_view[VIEW_MAX] = {};
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
vk::Image image = nullptr;
vk::ImageView image_view[VIEW_MAX] = {};
vk::ImageLayout layout = vk::ImageLayout::eUndefined;
Graphics::VulkanMemory memory;
ImageViewCache view_cache;
};
@ -142,10 +142,10 @@ struct RenderTextureVulkanImage: public VulkanImage {
};
struct VulkanBuffer {
VkBuffer buffer = nullptr;
VulkanMemory memory;
VkBufferUsageFlags usage = 0;
uint64_t buffer_size = 0;
vk::Buffer buffer = nullptr;
VulkanMemory memory;
vk::BufferUsageFlags usage = {};
uint64_t buffer_size = 0;
};
struct StorageVulkanBuffer: public VulkanBuffer {};

View File

@ -25,12 +25,12 @@ struct LabelCallbacks {
};
struct LabelEvent final {
VkDevice device = nullptr;
VkEvent event = nullptr;
vk::Device device = nullptr;
vk::Event event = nullptr;
~LabelEvent() {
if (event != nullptr) {
vkDestroyEvent(device, event, nullptr);
device.destroyEvent(event, nullptr);
}
}
};
@ -41,7 +41,7 @@ struct LabelSubmission {
};
struct Label {
VkDevice device = nullptr;
vk::Device device = nullptr;
LabelStatus status = LabelStatus::New;
LabelCallbacks callbacks;
std::vector<LabelSubmission> submissions;
@ -115,14 +115,14 @@ void LabelManager::ThreadRun(void* data) {
it->completion->event == nullptr) {
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) {
case VK_EVENT_SET:
case vk::Result::eEventSet:
fired_labels.push_back(it->callbacks);
finished_submissions.push_back(*it);
it = label->submissions.erase(it);
break;
case VK_EVENT_RESET: ++it; break;
case vk::Result::eEventReset: ++it; break;
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->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);
VkEventCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
vk::EventCreateInfo create_info {};
create_info.sType = vk::StructureType::eEventCreateInfo;
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);
buffer->RetainResourceUntilFence(submission.completion);
// Labels can be reused before an earlier end-of-pipe event has been
// observed by the polling thread. Capture a separate Vulkan event and
// callback snapshot for each set so older writes are not lost.
vkResetEvent(label->device, submission.completion->event);
vkCmdSetEvent(vk_buffer, submission.completion->event, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
label->device.resetEvent(submission.completion->event);
vk_buffer.setEvent(submission.completion->event, vk::PipelineStageFlagBits::eBottomOfPipe);
label->submissions.push_back(submission);

View File

@ -28,115 +28,115 @@ RenderTargetFormatInfo TextureGetRenderTargetFormat(uint32_t raw_layout, uint32_
if (layout == Prospero::ChannelLayout::k8 && type == Prospero::ChannelType::kUNorm &&
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_B10G11R11_UFLOAT_PACK32, 4};
return {vk::Format::eB10G11R11UfloatPack32, 4};
}
if (is(Prospero::ChannelLayout::k16, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16_UNORM, 2};
return {vk::Format::eR16Unorm, 2};
}
if (is(Prospero::ChannelLayout::k16, Prospero::ChannelType::kUInt,
Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16_UINT, 2};
return {vk::Format::eR16Uint, 2};
}
if (is(Prospero::ChannelLayout::k16, Prospero::ChannelType::kFloat,
Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16_SFLOAT, 2};
return {vk::Format::eR16Sfloat, 2};
}
if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kUNorm,
Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16G16_UNORM, 4};
return {vk::Format::eR16G16Unorm, 4};
}
if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kSNorm,
Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16G16_SNORM, 4};
return {vk::Format::eR16G16Snorm, 4};
}
if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kUInt,
Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R16G16_UINT, 4};
return {vk::Format::eR16G16Uint, 4};
}
if (is(Prospero::ChannelLayout::k16_16, Prospero::ChannelType::kFloat,
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,
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,
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,
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,
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,
Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R32_SFLOAT, 4};
return {vk::Format::eR32Sfloat, 4};
}
if (is(Prospero::ChannelLayout::k32_32, Prospero::ChannelType::kUInt,
Prospero::ChannelOrder::kStandard)) {
return {VK_FORMAT_R32G32_UINT, 8};
return {vk::Format::eR32G32Uint, 8};
}
if (is(Prospero::ChannelLayout::k32_32, Prospero::ChannelType::kFloat,
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,
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,
raw_type, raw_order);
@ -209,7 +209,7 @@ void TextureCopyBufferBytes(GraphicContext* ctx, VulkanBuffer* src_buffer,
return;
}
if ((src_buffer->memory.property & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) {
if (src_buffer->memory.property & vk::MemoryPropertyFlagBits::eHostVisible) {
void* data = nullptr;
VulkanMapMemory(ctx, &src_buffer->memory, &data);
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 {};
readback.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
readback.memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
readback.usage = vk::BufferUsageFlagBits::eTransferDst;
readback.memory.property = vk::MemoryPropertyFlagBits::eHostVisible |
vk::MemoryPropertyFlagBits::eHostCoherent |
vk::MemoryPropertyFlagBits::eHostCached;
VulkanCreateBuffer(ctx, (src_buffer_offset + available + 3u) & ~uint64_t {3}, &readback);
UtilCopyBuffer(src_buffer, &readback, src_buffer_offset + available);
@ -233,25 +233,25 @@ void TextureCopyBufferBytes(GraphicContext* ctx, VulkanBuffer* src_buffer,
VulkanDeleteBuffer(ctx, &readback);
}
VkComponentSwizzle TextureGetComponentSwizzle(uint8_t s) {
vk::ComponentSwizzle TextureGetComponentSwizzle(uint8_t s) {
switch (static_cast<Prospero::CompSwizzle>(s)) {
case Prospero::CompSwizzle::kZero: return VK_COMPONENT_SWIZZLE_ZERO;
case Prospero::CompSwizzle::kOne: return VK_COMPONENT_SWIZZLE_ONE;
case Prospero::CompSwizzle::kRed: return VK_COMPONENT_SWIZZLE_R;
case Prospero::CompSwizzle::kGreen: return VK_COMPONENT_SWIZZLE_G;
case Prospero::CompSwizzle::kBlue: return VK_COMPONENT_SWIZZLE_B;
case Prospero::CompSwizzle::kAlpha: return VK_COMPONENT_SWIZZLE_A;
case Prospero::CompSwizzle::kZero: return vk::ComponentSwizzle::eZero;
case Prospero::CompSwizzle::kOne: return vk::ComponentSwizzle::eOne;
case Prospero::CompSwizzle::kRed: return vk::ComponentSwizzle::eR;
case Prospero::CompSwizzle::kGreen: return vk::ComponentSwizzle::eG;
case Prospero::CompSwizzle::kBlue: return vk::ComponentSwizzle::eB;
case Prospero::CompSwizzle::kAlpha: return vk::ComponentSwizzle::eA;
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) {
return (swizzle >> (channel * 3u)) & 0x7u;
}
VkComponentMapping TextureGetComponentMapping(uint32_t swizzle) {
VkComponentMapping components {};
vk::ComponentMapping TextureGetComponentMapping(uint32_t swizzle) {
vk::ComponentMapping components {};
components.r = TextureGetComponentSwizzle(static_cast<uint8_t>(TextureGetDstSel(swizzle, 0)));
components.g = TextureGetComponentSwizzle(static_cast<uint8_t>(TextureGetDstSel(swizzle, 1)));
components.b = TextureGetComponentSwizzle(static_cast<uint8_t>(TextureGetDstSel(swizzle, 2)));
@ -259,57 +259,63 @@ VkComponentMapping TextureGetComponentMapping(uint32_t swizzle) {
return components;
}
bool TextureCheckFormat(GraphicContext* ctx, VkImageCreateInfo* image_info) {
VkImageFormatProperties props {};
bool TextureCheckFormat(GraphicContext* ctx, vk::ImageCreateInfo* image_info) {
vk::ImageFormatProperties props {};
if (ctx->GetImageFormatProperties(image_info->format, image_info->imageType, image_info->tiling,
image_info->usage, image_info->flags,
&props) == VK_ERROR_FORMAT_NOT_SUPPORTED) {
auto apply_fallback = [&](VkFormat replacement, const char* message) {
&props) == vk::Result::eErrorFormatNotSupported) {
auto apply_fallback = [&](vk::Format replacement, const char* message) {
image_info->format = replacement;
const bool result = TextureCheckFormat(ctx, image_info);
LOGF("%s [%s]\n", message, (!result ? "FAIL" : "SUCCESS"));
return result;
};
if (image_info->format == VK_FORMAT_R8G8B8A8_SRGB) {
if (image_info->format == vk::Format::eR8G8B8A8Srgb) {
// TODO() convert SRGB -> LINEAR in shader
return apply_fallback(VK_FORMAT_R8G8B8A8_UNORM,
"replace VK_FORMAT_R8G8B8A8_SRGB => VK_FORMAT_R8G8B8A8_UNORM");
return apply_fallback(
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
return apply_fallback(VK_FORMAT_B8G8R8A8_UNORM,
"replace VK_FORMAT_B8G8R8A8_SRGB => VK_FORMAT_B8G8R8A8_UNORM");
return apply_fallback(
vk::Format::eB8G8R8A8Unorm,
"replace vk::Format::eB8G8R8A8Srgb => vk::Format::eB8G8R8A8Unorm");
}
return false;
}
return true;
}
static bool TextureCheckFormatExact(GraphicContext* ctx, const VkImageCreateInfo& image_info) {
VkImageFormatProperties props {};
static bool TextureCheckFormatExact(GraphicContext* ctx, const vk::ImageCreateInfo& image_info) {
vk::ImageFormatProperties props {};
return ctx->GetImageFormatProperties(image_info.format, image_info.imageType, image_info.tiling,
image_info.usage, image_info.flags,
&props) != VK_ERROR_FORMAT_NOT_SUPPORTED;
&props) != vk::Result::eErrorFormatNotSupported;
}
bool TextureCheckStorageSwizzle(VkImageCreateInfo* image_info, VkComponentMapping* components) {
if ((image_info->usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) {
if (components->r == VK_COMPONENT_SWIZZLE_R && components->g == VK_COMPONENT_SWIZZLE_G &&
components->b == VK_COMPONENT_SWIZZLE_B && components->a == VK_COMPONENT_SWIZZLE_A) {
bool TextureCheckStorageSwizzle(vk::ImageCreateInfo* image_info, vk::ComponentMapping* components) {
if (image_info->usage & vk::ImageUsageFlagBits::eStorage) {
if (components->r == vk::ComponentSwizzle::eR &&
components->g == vk::ComponentSwizzle::eG &&
components->b == vk::ComponentSwizzle::eB &&
components->a == vk::ComponentSwizzle::eA) {
return true;
}
if (components->r == VK_COMPONENT_SWIZZLE_B && components->g == VK_COMPONENT_SWIZZLE_G &&
components->b == VK_COMPONENT_SWIZZLE_R && components->a == VK_COMPONENT_SWIZZLE_A &&
image_info->format == VK_FORMAT_R8G8B8A8_SRGB) {
LOGF("replace VK_FORMAT_R8G8B8A8_SRGB => VK_FORMAT_B8G8R8A8_SRGB\n");
if (components->r == vk::ComponentSwizzle::eB &&
components->g == vk::ComponentSwizzle::eG &&
components->b == vk::ComponentSwizzle::eR &&
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->g = VK_COMPONENT_SWIZZLE_G;
components->b = VK_COMPONENT_SWIZZLE_B;
components->a = VK_COMPONENT_SWIZZLE_A;
image_info->format = VK_FORMAT_B8G8R8A8_SRGB;
components->r = vk::ComponentSwizzle::eR;
components->g = vk::ComponentSwizzle::eG;
components->b = vk::ComponentSwizzle::eB;
components->a = vk::ComponentSwizzle::eA;
image_info->format = vk::Format::eB8G8R8A8Srgb;
return true;
}
@ -320,35 +326,36 @@ bool TextureCheckStorageSwizzle(VkImageCreateInfo* image_info, VkComponentMappin
return true;
}
VkImageUsageFlags TextureGetUsage(TextureFormatUsage usage) {
VkImageUsageFlags vk_usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
vk::ImageUsageFlags TextureGetUsage(TextureFormatUsage usage) {
vk::ImageUsageFlags vk_usage =
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eTransferSrc;
if (TextureHasFormatUsage(usage, TextureFormatUsage::Sampled)) {
vk_usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
vk_usage |= vk::ImageUsageFlagBits::eSampled;
}
if (TextureHasFormatUsage(usage, TextureFormatUsage::Storage)) {
vk_usage |= VK_IMAGE_USAGE_STORAGE_BIT;
vk_usage |= vk::ImageUsageFlagBits::eStorage;
}
return vk_usage;
}
VkImageUsageFlags TextureGetViewUsage(TextureFormatUsage usage) {
VkImageUsageFlags vk_usage = 0;
vk::ImageUsageFlags TextureGetViewUsage(TextureFormatUsage usage) {
vk::ImageUsageFlags vk_usage = {};
if (TextureHasFormatUsage(usage, TextureFormatUsage::Sampled)) {
vk_usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
vk_usage |= vk::ImageUsageFlagBits::eSampled;
}
if (TextureHasFormatUsage(usage, TextureFormatUsage::Storage)) {
vk_usage |= VK_IMAGE_USAGE_STORAGE_BIT;
vk_usage |= vk::ImageUsageFlagBits::eStorage;
}
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);
if (vk_format != VK_FORMAT_UNDEFINED) {
if (vk_format != vk::Format::eUndefined) {
return vk_format;
}
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) {
@ -426,13 +433,13 @@ static bool CalcStandard4kbVolumeMipLayout(uint32_t format, uint32_t pitch, uint
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) {
return (depth > 1 && levels > 1 && UtilIsBcFormat(format) ? AlignUpU32(mip_height, 4u)
: 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) {
auto image_height = height * depth;
if (depth <= 1 || levels <= 1 || !UtilIsBcFormat(format)) {
@ -452,7 +459,7 @@ uint32_t TextureCalcStackedImageHeight(VkFormat format, uint32_t height, uint32_
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) {
auto image_height = height * depth;
if (levels <= 1) {
@ -495,8 +502,8 @@ bool TextureCanCreateCubeView(uint64_t type, uint32_t base_array, uint32_t layer
layer_count % 6u == 0;
}
VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj, VulkanMemory* mem,
const TextureImageCreateParams& params) {
vk::ComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj, VulkanMemory* mem,
const TextureImageCreateParams& params) {
EXIT_IF(ctx == nullptr);
EXIT_IF(vk_obj == nullptr);
EXIT_IF(mem == nullptr);
@ -506,7 +513,7 @@ VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj,
const bool volume_texture = TextureIs3DTexture(params.type);
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.height == 0);
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);
}
VkComponentMapping components =
vk::ComponentMapping components =
TextureGetComponentMapping(static_cast<uint32_t>(params.swizzle));
VkImageCreateInfo image_info {};
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
vk::ImageCreateInfo image_info {};
image_info.sType = vk::StructureType::eImageCreateInfo;
image_info.pNext = nullptr;
image_info.flags =
(params.allow_cube_view && TextureCanCreateCubeView(params.type, 0, params.depth)
? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
: 0) |
(volume_texture ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT : 0) |
(params.compatible_format_views ? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT : 0);
image_info.imageType = (volume_texture ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D);
? vk::ImageCreateFlagBits::eCubeCompatible
: vk::ImageCreateFlags {}) |
(volume_texture ? vk::ImageCreateFlagBits::e2DArrayCompatible : vk::ImageCreateFlags {}) |
(params.compatible_format_views ? vk::ImageCreateFlagBits::eMutableFormat
: 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.height = image_height;
image_info.extent.depth = (volume_texture ? params.depth : 1);
image_info.mipLevels = image_mips;
image_info.arrayLayers = (array_texture ? params.depth : 1);
image_info.format = pixel_format;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_info.tiling = vk::ImageTiling::eOptimal;
image_info.initialLayout = vk::ImageLayout::eUndefined;
image_info.usage = TextureGetUsage(params.format_usage);
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_info.sharingMode = vk::SharingMode::eExclusive;
image_info.samples = vk::SampleCountFlagBits::e1;
const bool storage_view = TextureHasFormatUsage(params.view_usage, TextureFormatUsage::Storage);
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",
params.owner, params.swizzle);
}
components.r = VK_COMPONENT_SWIZZLE_R;
components.g = VK_COMPONENT_SWIZZLE_G;
components.b = VK_COMPONENT_SWIZZLE_B;
components.a = VK_COMPONENT_SWIZZLE_A;
components.r = vk::ComponentSwizzle::eR;
components.g = vk::ComponentSwizzle::eG;
components.b = vk::ComponentSwizzle::eB;
components.a = vk::ComponentSwizzle::eA;
}
const auto view_checked_format = image_info.format;
@ -612,7 +620,7 @@ VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* 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);
EXIT_NOT_IMPLEMENTED(!created);
@ -623,7 +631,7 @@ VkComponentMapping TextureCreateImage(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,
bool allow_cube_view, TextureFormatUsage view_usage) {
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 volume_slices = std::max(depth >> base_level, 1u);
VkImageViewUsageCreateInfo usage_info {};
usage_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;
vk::ImageViewUsageCreateInfo usage_info {};
usage_info.sType = vk::StructureType::eImageViewUsageCreateInfo;
usage_info.pNext = nullptr;
usage_info.usage = TextureGetViewUsage(view_usage);
VkImageViewCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
create_info.pNext = (usage_info.usage != 0 ? &usage_info : nullptr);
create_info.flags = 0;
vk::ImageViewCreateInfo create_info {};
create_info.sType = vk::StructureType::eImageViewCreateInfo;
create_info.pNext = (usage_info.usage ? &usage_info : nullptr);
create_info.flags = {};
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.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.baseMipLevel = base_level;
create_info.subresourceRange.layerCount = layer_count;
create_info.subresourceRange.levelCount = level_count;
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.layerCount = 1;
} else if (allow_cube_view && TextureCanCreateCubeView(type, base_array, layer_count)) {
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) {
create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
create_info.viewType = vk::ImageViewType::e2DArray;
}
vkCreateImageView(ctx->device, &create_info, nullptr,
&vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
ctx->device.createImageView(&create_info, nullptr,
&vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);
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);
vkCreateImageView(ctx->device, &create_info, nullptr,
&vk_obj->image_view[VulkanImage::VIEW_DEFAULT_ARRAY]);
ctx->device.createImageView(&create_info, nullptr,
&vk_obj->image_view[VulkanImage::VIEW_DEFAULT_ARRAY]);
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;
}
std::vector<BufferImageCopy>
TextureBuildUploadRegions(const TextureUploadLayout& layout, VkFormat image_format, uint32_t width,
uint32_t height, uint32_t depth, uint64_t levels, bool array_texture,
bool volume_texture, TextureUploadDestination destination,
TextureUploadSliceLayout slice_layout) {
std::vector<BufferImageCopy> TextureBuildUploadRegions(
const TextureUploadLayout& layout, vk::Format image_format, uint32_t width, uint32_t height,
uint32_t depth, uint64_t levels, bool array_texture, bool volume_texture,
TextureUploadDestination destination, TextureUploadSliceLayout slice_layout) {
uint32_t mip_width = width;
uint32_t mip_height = height;
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,
const std::vector<BufferImageCopy>& regions, uint64_t dst_layout,
const char* owner) {
const std::vector<BufferImageCopy>& regions,
vk::ImageLayout dst_layout, const char* owner) {
constexpr uint32_t kIdentityFmaskPattern = 0x76543210u;
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,
uint64_t height, uint32_t depth, uint64_t levels,
TextureUploadSliceLayout source_slice_layout, const char* owner,
uint64_t dst_layout) {
vk::ImageLayout dst_layout) {
if (fmt == 0) {
EXIT("%s: legacy texture upload format unsupported: fmt=0 tile=%u size=%" PRIu64
" extent=%" PRIu64 "x%" PRIu64 " depth=%u pitch=%u levels=%" PRIu64 "\n",

View File

@ -6,9 +6,9 @@
#include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/guest_gpu/tile.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -48,7 +48,7 @@ enum class TextureUploadDestination { MipLevels, MipAtlas };
enum class TextureUploadSliceLayout { MipChainPerSlice, MipLevelPerSlice };
struct RenderTargetFormatInfo {
VkFormat format = VK_FORMAT_UNDEFINED;
vk::Format format = vk::Format::eUndefined;
uint32_t bytes_per_element = 0;
Prospero::ColorComponentMapping export_mapping;
};
@ -87,28 +87,28 @@ struct TextureImageCreateParams {
const char* owner = nullptr;
};
VkComponentSwizzle TextureGetComponentSwizzle(uint8_t s);
VkComponentMapping TextureGetComponentMapping(uint32_t swizzle);
bool TextureCheckFormat(GraphicContext* ctx, VkImageCreateInfo* image_info);
bool TextureCheckStorageSwizzle(VkImageCreateInfo* image_info, VkComponentMapping* components);
VkImageUsageFlags TextureGetUsage(TextureFormatUsage usage);
VkImageUsageFlags TextureGetViewUsage(TextureFormatUsage usage);
VkFormat TextureGetFormat(uint32_t fmt, TextureFormatUsage usage);
vk::ComponentSwizzle TextureGetComponentSwizzle(uint8_t s);
vk::ComponentMapping TextureGetComponentMapping(uint32_t swizzle);
bool TextureCheckFormat(GraphicContext* ctx, vk::ImageCreateInfo* image_info);
bool TextureCheckStorageSwizzle(vk::ImageCreateInfo* image_info, vk::ComponentMapping* components);
vk::ImageUsageFlags TextureGetUsage(TextureFormatUsage usage);
vk::ImageUsageFlags TextureGetViewUsage(TextureFormatUsage usage);
vk::Format TextureGetFormat(uint32_t fmt, TextureFormatUsage usage);
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);
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);
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);
bool TextureIs3DTexture(uint64_t type);
bool TextureIsCubeTexture(uint64_t type);
bool TextureIsLayeredTexture(uint64_t type);
bool TextureCanCreateCubeView(uint64_t type, uint32_t base_array, uint32_t layer_count);
VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj, VulkanMemory* mem,
const TextureImageCreateParams& params);
vk::ComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj, VulkanMemory* mem,
const TextureImageCreateParams& params);
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,
bool allow_cube_view, TextureFormatUsage view_usage);
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,
const std::vector<BufferImageCopy>& regions, uint64_t levels,
uint32_t depth, TextureUploadSliceLayout source_slice_layout);
std::vector<BufferImageCopy>
TextureBuildUploadRegions(const TextureUploadLayout& layout, VkFormat image_format, uint32_t width,
uint32_t height, uint32_t depth, uint64_t levels, bool array_texture,
bool volume_texture, TextureUploadDestination destination,
TextureUploadSliceLayout slice_layout);
std::vector<BufferImageCopy> TextureBuildUploadRegions(
const TextureUploadLayout& layout, vk::Format image_format, uint32_t width, uint32_t height,
uint32_t depth, uint64_t levels, bool array_texture, bool volume_texture,
TextureUploadDestination destination, TextureUploadSliceLayout slice_layout);
void TextureCopyBufferBytes(GraphicContext* ctx, VulkanBuffer* src_buffer,
uint64_t src_buffer_offset, uint64_t copy_size, UtilScratchBuffer* dst);
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,
uint64_t height, uint32_t depth, uint64_t levels,
TextureUploadSliceLayout source_slice_layout, const char* owner,
uint64_t dst_layout);
vk::ImageLayout dst_layout);
} // namespace Libs::Graphics

View File

@ -421,10 +421,10 @@ struct BufferCache::ReadbackWorker {
i, family, ctx->queues[i].family);
}
}
readback.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
readback.memory.property = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
readback.usage = vk::BufferUsageFlagBits::eTransferDst;
readback.memory.property = vk::MemoryPropertyFlagBits::eHostVisible |
vk::MemoryPropertyFlagBits::eHostCoherent |
vk::MemoryPropertyFlagBits::eHostCached;
VulkanCreateBuffer(ctx, READBACK_CAPACITY, &readback);
VulkanMapMemory(ctx, &readback.memory, &mapped);
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",
vaddr, page, cached.vaddr, cached.size);
}
uint32_t data_offset = 0;
std::array<VkBufferCopy, MAX_RANGES> copies {};
std::array<VkBufferMemoryBarrier, MAX_RANGES> barriers {};
uint32_t data_offset = 0;
std::array<vk::BufferCopy, MAX_RANGES> copies {};
std::array<vk::BufferMemoryBarrier, MAX_RANGES> barriers {};
cache.m_gpu_modified_ranges.ForEachIntersection(
page, TRACKER_PAGE_SIZE, [&](RangeSet::Range range) {
if (range_count == MAX_RANGES || (range.address - cached.vaddr) % 4 != 0 ||
@ -475,9 +475,9 @@ struct BufferCache::ReadbackWorker {
.dstOffset = data_offset,
.size = range.size};
auto& barrier = barriers[range_count];
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
barrier.sType = vk::StructureType::eBufferMemoryBarrier;
barrier.srcAccessMask = vk::AccessFlagBits::eMemoryWrite;
barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.buffer = cached.buffer->buffer;
@ -498,13 +498,13 @@ struct BufferCache::ReadbackWorker {
" count=%u bytes=%u\n",
page, range_count, data_offset);
}
auto* vk_buffer = command->GetPool()->buffers[command->GetIndex()];
auto vk_buffer = command->GetPool()->buffers[command->GetIndex()];
command->Begin();
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, range_count,
barriers.data(), 0, nullptr);
vkCmdCopyBuffer(vk_buffer, cached.buffer->buffer, readback.buffer, range_count,
copies.data());
vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlags {},
0, nullptr, range_count, barriers.data(), 0, nullptr);
vk_buffer.copyBuffer(cached.buffer->buffer, readback.buffer, range_count,
copies.data());
command->End();
command->Execute();
command->WaitForFenceAndReset();
@ -687,10 +687,10 @@ std::pair<VulkanBuffer*, uint64_t> BufferCache::ObtainBuffer(CommandBuffer* com
!texture_region.gpu_metadata_bytes) {
std::array<uint8_t, CACHING_PAGE_SIZE> guest_data;
if (Libs::LibKernel::Memory::TryReadBacking(vaddr, guest_data.data(), size)) {
VulkanBuffer* stream_buffer = nullptr;
VkDeviceSize stream_offset = 0;
VkDeviceSize stream_range = 0;
const auto stream_alignment = std::max<uint64_t>(ctx->StorageMinAlignment(), 16);
VulkanBuffer* stream_buffer = nullptr;
vk::DeviceSize stream_offset = 0;
vk::DeviceSize stream_range = 0;
const auto stream_alignment = std::max<uint64_t>(ctx->StorageMinAlignment(), 16);
if (UploadHostData(command, ctx, guest_data.data(), size, stream_alignment,
&stream_buffer, &stream_offset, &stream_range)) {
return {stream_buffer, stream_offset};
@ -795,20 +795,20 @@ std::pair<VulkanBuffer*, uint64_t> BufferCache::ObtainBuffer(CommandBuffer* com
cached->ctx = ctx;
cached->buffer = MakeSharedVulkanBuffer(ctx);
cached->buffer->usage =
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
cached->buffer->memory.property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst |
vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eIndexBuffer |
vk::BufferUsageFlagBits::eStorageBuffer;
cached->buffer->memory.property = vk::MemoryPropertyFlagBits::eDeviceLocal;
VulkanCreateBuffer(ctx, cached->size, cached->buffer.get());
if (!overlaps.empty()) {
auto* vk_buffer = command->GetPool()->buffers[command->GetIndex()];
std::vector<VkBufferMemoryBarrier> before;
auto vk_buffer = command->GetPool()->buffers[command->GetIndex()];
std::vector<vk::BufferMemoryBarrier> before;
before.reserve(overlaps.size() + 1);
for (const auto& overlap: overlaps) {
VkBufferMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
vk::BufferMemoryBarrier barrier {};
barrier.sType = vk::StructureType::eBufferMemoryBarrier;
barrier.srcAccessMask = vk::AccessFlagBits::eMemoryWrite;
barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.buffer = overlap->second->buffer->buffer;
@ -816,37 +816,38 @@ std::pair<VulkanBuffer*, uint64_t> BufferCache::ObtainBuffer(CommandBuffer* com
barrier.size = overlap->second->size;
before.push_back(barrier);
}
VkBufferMemoryBarrier destination {};
destination.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
destination.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
vk::BufferMemoryBarrier destination {};
destination.sType = vk::StructureType::eBufferMemoryBarrier;
destination.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
destination.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
destination.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
destination.buffer = cached->buffer->buffer;
destination.offset = 0;
destination.size = cached->size;
before.push_back(destination);
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0,
nullptr, static_cast<uint32_t>(before.size()), before.data(), 0,
nullptr);
vk_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eTransfer,
vk::DependencyFlagBits::eByRegion, 0, nullptr, static_cast<uint32_t>(before.size()),
before.data(), 0, nullptr);
for (const auto& overlap: overlaps) {
const auto& old = *overlap->second;
const VkBufferCopy copy {
const auto& old = *overlap->second;
const vk::BufferCopy copy {
.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 {};
after.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
after.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
after.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
vk::BufferMemoryBarrier after {};
after.sType = vk::StructureType::eBufferMemoryBarrier;
after.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
after.dstAccessMask =
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
after.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
after.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
after.buffer = cached->buffer->buffer;
after.offset = 0;
after.size = cached->size;
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0,
nullptr, 1, &after, 0, nullptr);
vk_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eAllCommands,
vk::DependencyFlagBits::eByRegion, 0, nullptr, 1, &after, 0, nullptr);
for (const auto& overlap: overlaps) {
command->RetainResourceUntilFence(overlap->second->buffer);
m_buffers.erase(overlap);
@ -896,12 +897,13 @@ VulkanBuffer* BufferCache::ObtainNullBuffer(CommandBuffer* command, GraphicConte
if (m_null_buffer == nullptr) {
// robustBufferAccess makes every fetch safe; TODO: Use a
// persistent 16-byte fallback when Vulkan null vertex descriptors are unavailable.
auto buffer = MakeSharedVulkanBuffer(ctx);
buffer->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
buffer->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
auto buffer = MakeSharedVulkanBuffer(ctx);
buffer->usage = vk::BufferUsageFlagBits::eStorageBuffer |
vk::BufferUsageFlagBits::eVertexBuffer |
vk::BufferUsageFlagBits::eIndexBuffer;
buffer->memory.property = vk::MemoryPropertyFlagBits::eHostVisible |
vk::MemoryPropertyFlagBits::eHostCoherent |
vk::MemoryPropertyFlagBits::eHostCached;
VulkanCreateBuffer(ctx, 16, buffer.get());
void* data = nullptr;
VulkanMapMemory(ctx, &buffer->memory, &data);
@ -1040,8 +1042,8 @@ BufferImageCopySource BufferCache::ObtainBufferForImage(uint64_t vaddr, uint64_t
}
namespace {
VkBufferMemoryBarrier MakeDmaBarrier(VulkanBuffer* buffer, uint64_t offset, uint64_t size,
VkAccessFlags source, VkAccessFlags destination) {
vk::BufferMemoryBarrier MakeDmaBarrier(VulkanBuffer* buffer, uint64_t offset, uint64_t size,
vk::AccessFlags source, vk::AccessFlags destination) {
if (buffer == nullptr || buffer->buffer == nullptr || size == 0 ||
offset > buffer->buffer_size || size > buffer->buffer_size - offset) {
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 ? 0 : buffer->buffer_size);
}
VkBufferMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
vk::BufferMemoryBarrier barrier {};
barrier.sType = vk::StructureType::eBufferMemoryBarrier;
barrier.srcAccessMask = source;
barrier.dstAccessMask = destination;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@ -1062,7 +1064,7 @@ VkBufferMemoryBarrier MakeDmaBarrier(VulkanBuffer* buffer, uint64_t offset, uint
return barrier;
}
VkCommandBuffer GetDmaCommandBuffer(CommandBuffer* command) {
vk::CommandBuffer GetDmaCommandBuffer(CommandBuffer* command) {
if (command == nullptr || command->IsInvalid() || command->GetPool() == nullptr ||
command->GetIndex() >= command->GetPool()->buffers_count) {
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 before = MakeDmaBarrier(dst, dst_offset, size,
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
const auto before = MakeDmaBarrier(
dst, dst_offset, size, vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite,
vk::AccessFlagBits::eTransferWrite);
const auto vk_buffer = GetDmaCommandBuffer(command);
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1,
&before, 0, nullptr);
vkCmdFillBuffer(vk_buffer, dst->buffer, dst_offset, size, value);
const auto after = MakeDmaBarrier(dst, dst_offset, size, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0,
nullptr, 1, &after, 0, nullptr);
vk_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eTransfer,
vk::DependencyFlagBits::eByRegion, 0, nullptr, 1, &before, 0, nullptr);
vk_buffer.fillBuffer(dst->buffer, dst_offset, size, value);
const auto after =
MakeDmaBarrier(dst, dst_offset, size, vk::AccessFlagBits::eTransferWrite,
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite);
vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eAllCommands,
vk::DependencyFlagBits::eByRegion, 0, nullptr, 1, &after, 0, nullptr);
}
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",
src_offset, dst_offset, size);
}
const VkBufferMemoryBarrier before[] = {
const vk::BufferMemoryBarrier before[] = {
MakeDmaBarrier(dst, dst_offset, size,
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT),
MakeDmaBarrier(src, src_offset, size, VK_ACCESS_MEMORY_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT),
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite,
vk::AccessFlagBits::eTransferWrite),
MakeDmaBarrier(src, src_offset, size, vk::AccessFlagBits::eMemoryWrite,
vk::AccessFlagBits::eTransferRead),
};
const auto vk_buffer = GetDmaCommandBuffer(command);
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 2,
before, 0, nullptr);
const VkBufferCopy copy {src_offset, dst_offset, size};
vkCmdCopyBuffer(vk_buffer, src->buffer, dst->buffer, 1, &copy);
const VkBufferMemoryBarrier after[] = {
MakeDmaBarrier(dst, dst_offset, size, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT),
MakeDmaBarrier(src, src_offset, size, VK_ACCESS_TRANSFER_READ_BIT,
VK_ACCESS_MEMORY_WRITE_BIT),
vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eTransfer,
vk::DependencyFlagBits::eByRegion, 0, nullptr, 2, before, 0, nullptr);
const vk::BufferCopy copy {src_offset, dst_offset, size};
vk_buffer.copyBuffer(src->buffer, dst->buffer, 1, &copy);
const vk::BufferMemoryBarrier after[] = {
MakeDmaBarrier(dst, dst_offset, size, vk::AccessFlagBits::eTransferWrite,
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite),
MakeDmaBarrier(src, src_offset, size, vk::AccessFlagBits::eTransferRead,
vk::AccessFlagBits::eMemoryWrite),
};
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0,
nullptr, 2, after, 0, nullptr);
vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eAllCommands,
vk::DependencyFlagBits::eByRegion, 0, nullptr, 2, after, 0, nullptr);
}
bool BufferCache::HasPageOverlap(uint64_t vaddr, uint64_t size) {

View File

@ -17,6 +17,7 @@
#include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/displayBuffer.h"
#include <algorithm>
@ -25,7 +26,6 @@
#include <cstdarg>
#include <cstdio>
#include <limits>
#include <vulkan/vk_enum_string_helper.h>
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);
}
[[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 c1 = rt.clear_word1.word1;
VkClearColorValue color {};
vk::ClearColorValue color {};
switch (static_cast<Prospero::ChannelType>(rt.info.channel_type)) {
case Prospero::ChannelType::kUNorm:
@ -312,7 +312,7 @@ void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const H
r->base_addr = 0;
r->vulkan_buffer = nullptr;
r->vulkan_view = nullptr;
r->format = VK_FORMAT_UNDEFINED;
r->format = vk::Format::eUndefined;
r->extent = {};
r->base_mip_level = 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)) {
EXIT("mipmapped display render targets are unsupported\n");
}
const VkExtent2D view_extent = {std::max(width >> rt.view.current_mip_level, 1u),
std::max(height >> 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)};
auto decision_log_id = g_render_color_log_count.fetch_add(1);
if (decision_log_id < 128 || !render_to_texture) {

View File

@ -3,9 +3,9 @@
#include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/host_gpu/renderer/renderTarget.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <cstdint>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -25,9 +25,9 @@ enum class RenderColorType {
struct RenderColorInfo {
RenderColorType type = RenderColorType::NoColorOutput;
VulkanImage* vulkan_buffer = nullptr;
VkImageView vulkan_view = nullptr;
VkFormat format = VK_FORMAT_UNDEFINED;
VkExtent2D extent = {};
vk::ImageView vulkan_view = nullptr;
vk::Format format = vk::Format::eUndefined;
vk::Extent2D extent = {};
uint32_t base_mip_level = 0;
uint32_t base_array_layer = 0;
uint64_t base_addr = 0;
@ -35,7 +35,7 @@ struct RenderColorInfo {
uint32_t target_slot = 0;
Prospero::ColorComponentMapping export_mapping;
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,

View File

@ -14,13 +14,13 @@
#include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/window.h"
#include <algorithm>
#include <atomic>
#include <cstring>
#include <memory>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics {
static std::atomic<uint64_t> g_command_buffer_submit_seq = 0;
class CommandPool {
@ -103,51 +103,53 @@ void CommandPool::Create(int id) {
pool = new VulkanCommandPool;
VkCommandPoolCreateInfo pool_info {};
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
vk::CommandPoolCreateInfo pool_info {};
pool_info.sType = vk::StructureType::eCommandPoolCreateInfo;
pool_info.pNext = nullptr;
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);
pool->buffers_count = 8;
pool->buffers = std::make_unique<VkCommandBuffer[]>(pool->buffers_count);
pool->fences = std::make_unique<VkFence[]>(pool->buffers_count);
pool->semaphores = std::make_unique<VkSemaphore[]>(pool->buffers_count);
pool->buffers = std::make_unique<vk::CommandBuffer[]>(pool->buffers_count);
pool->fences = std::make_unique<vk::Fence[]>(pool->buffers_count);
pool->semaphores = std::make_unique<vk::Semaphore[]>(pool->buffers_count);
pool->busy = std::make_unique<bool[]>(pool->buffers_count);
VkCommandBufferAllocateInfo alloc_info {};
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
vk::CommandBufferAllocateInfo alloc_info {};
alloc_info.sType = vk::StructureType::eCommandBufferAllocateInfo;
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;
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");
}
for (uint32_t i = 0; i < pool->buffers_count; i++) {
pool->busy[i] = false;
VkFenceCreateInfo fence_info {};
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
vk::FenceCreateInfo fence_info {};
fence_info.sType = vk::StructureType::eFenceCreateInfo;
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");
}
VkSemaphoreCreateInfo semaphore_info {};
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
vk::SemaphoreCreateInfo semaphore_info {};
semaphore_info.sType = vk::StructureType::eSemaphoreCreateInfo;
semaphore_info.pNext = nullptr;
semaphore_info.flags = 0;
semaphore_info.flags = {};
if (vkCreateSemaphore(ctx->device, &semaphore_info, nullptr, &pool->semaphores[i]) !=
VK_SUCCESS) {
if (ctx->device.createSemaphore(&semaphore_info, nullptr, &pool->semaphores[i]) !=
vk::Result::eSuccess) {
EXIT("Can't create semaphore");
}
@ -166,13 +168,13 @@ void CommandPool::DeleteAll() {
EXIT_IF(ctx->device == nullptr);
for (uint32_t i = 0; i < pool->buffers_count; i++) {
vkDestroySemaphore(ctx->device, pool->semaphores[i], nullptr);
vkDestroyFence(ctx->device, pool->fences[i], nullptr);
ctx->device.destroySemaphore(pool->semaphores[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;
pool = nullptr;
@ -202,7 +204,7 @@ void CommandBuffer::Allocate() {
for (uint32_t i = 0; i < m_pool->buffers_count; i++) {
if (!m_pool->busy[i]) {
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;
break;
}
@ -221,7 +223,7 @@ void CommandBuffer::Free() {
m_host_stream.Release();
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();
m_fence_resources.ReleaseAfterFence();
m_index = static_cast<uint32_t>(-1);
@ -258,27 +260,27 @@ void CommandBuffer::RecycleDescriptorsAfterFence() {
void CommandBuffer::Begin() const {
EXIT_IF(IsInvalid());
auto* buffer = m_pool->buffers[m_index];
auto buffer = m_pool->buffers[m_index];
VkCommandBufferBeginInfo begin_info {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vk::CommandBufferBeginInfo begin_info {};
begin_info.sType = vk::StructureType::eCommandBufferBeginInfo;
begin_info.pNext = nullptr;
begin_info.flags = 0;
begin_info.flags = {};
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 {
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,
@ -296,11 +298,11 @@ void CommandBuffer::Execute() {
EXIT_IF(IsInvalid());
EXIT_IF(m_execute);
auto* buffer = m_pool->buffers[m_index];
auto* fence = m_pool->fences[m_index];
auto buffer = m_pool->buffers[m_index];
auto fence = m_pool->fences[m_index];
VkSubmitInfo submit_info {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
vk::SubmitInfo submit_info {};
submit_info.sType = vk::StructureType::eSubmitInfo;
submit_info.pNext = nullptr;
submit_info.waitSemaphoreCount = 0;
submit_info.pWaitSemaphores = nullptr;
@ -314,12 +316,12 @@ void CommandBuffer::Execute() {
const auto& queue = g_render_ctx->GetGraphicCtx()->queues[m_queue];
auto result = vkResetFences(g_render_ctx->GetGraphicCtx()->device, 1, &fence);
if (result != VK_SUCCESS) {
LOGF("vkResetFences failed before submit: %s (%d)\n", string_VkResult(result),
auto result = g_render_ctx->GetGraphicCtx()->device.resetFences(1, &fence);
if (result != vk::Result::eSuccess) {
LOGF("vkResetFences failed before submit: %s (%d)\n", VulkanToString(result).c_str(),
static_cast<int>(result));
}
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
if (queue.mutex != nullptr) {
queue.mutex->Lock();
@ -332,7 +334,7 @@ void CommandBuffer::Execute() {
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) {
queue.mutex->Unlock();
@ -342,29 +344,29 @@ void CommandBuffer::Execute() {
m_fence_waited = false;
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
" 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,
m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2, m_debug_arg3,
m_debug_arg4);
VulkanToString(result).c_str(), static_cast<int>(result), m_queue, m_index,
m_submit_seq, m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2,
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(m_execute);
auto* buffer = m_pool->buffers[m_index];
auto* fence = m_pool->fences[m_index];
auto buffer = m_pool->buffers[m_index];
auto fence = m_pool->fences[m_index];
if (signal_semaphore == nullptr) {
signal_semaphore = m_pool->semaphores[m_index];
}
VkSubmitInfo submit_info {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
vk::SubmitInfo submit_info {};
submit_info.sType = vk::StructureType::eSubmitInfo;
submit_info.pNext = nullptr;
submit_info.waitSemaphoreCount = 0;
submit_info.pWaitSemaphores = nullptr;
@ -378,12 +380,12 @@ void CommandBuffer::ExecuteWithSemaphore(VkSemaphore signal_semaphore) {
const auto& queue = g_render_ctx->GetGraphicCtx()->queues[m_queue];
auto result = vkResetFences(g_render_ctx->GetGraphicCtx()->device, 1, &fence);
if (result != VK_SUCCESS) {
LOGF("vkResetFences failed before submit: %s (%d)\n", string_VkResult(result),
auto result = g_render_ctx->GetGraphicCtx()->device.resetFences(1, &fence);
if (result != vk::Result::eSuccess) {
LOGF("vkResetFences failed before submit: %s (%d)\n", VulkanToString(result).c_str(),
static_cast<int>(result));
}
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
if (queue.mutex != nullptr) {
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);
}
result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
result = queue.vk_queue.submit(1, &submit_info, fence);
if (queue.mutex != nullptr) {
queue.mutex->Unlock();
@ -406,32 +408,32 @@ void CommandBuffer::ExecuteWithSemaphore(VkSemaphore signal_semaphore) {
m_fence_waited = false;
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
" 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,
m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2, m_debug_arg3,
m_debug_arg4);
VulkanToString(result).c_str(), static_cast<int>(result), m_queue, m_index,
m_submit_seq, m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2,
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,
VkPipelineStageFlags wait_stage,
VkSemaphore signal_semaphore) {
void CommandBuffer::ExecuteWithSemaphore(vk::Semaphore wait_semaphore,
vk::PipelineStageFlags wait_stage,
vk::Semaphore signal_semaphore) {
EXIT_IF(IsInvalid());
EXIT_IF(m_execute);
EXIT_IF(wait_semaphore == nullptr);
auto* buffer = m_pool->buffers[m_index];
auto* fence = m_pool->fences[m_index];
auto buffer = m_pool->buffers[m_index];
auto fence = m_pool->fences[m_index];
if (signal_semaphore == nullptr) {
signal_semaphore = m_pool->semaphores[m_index];
}
VkSubmitInfo submit_info {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
vk::SubmitInfo submit_info {};
submit_info.sType = vk::StructureType::eSubmitInfo;
submit_info.pNext = nullptr;
submit_info.waitSemaphoreCount = 1;
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];
auto result = vkResetFences(g_render_ctx->GetGraphicCtx()->device, 1, &fence);
if (result != VK_SUCCESS) {
LOGF("vkResetFences failed before submit: %s (%d)\n", string_VkResult(result),
auto result = g_render_ctx->GetGraphicCtx()->device.resetFences(1, &fence);
if (result != vk::Result::eSuccess) {
LOGF("vkResetFences failed before submit: %s (%d)\n", VulkanToString(result).c_str(),
static_cast<int>(result));
}
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
if (queue.mutex != nullptr) {
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);
}
result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
result = queue.vk_queue.submit(1, &submit_info, fence);
if (queue.mutex != nullptr) {
queue.mutex->Unlock();
@ -474,14 +476,14 @@ void CommandBuffer::ExecuteWithSemaphore(VkSemaphore wait_semaphore,
m_fence_waited = false;
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
" 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,
m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2, m_debug_arg3,
m_debug_arg4);
VulkanToString(result).c_str(), static_cast<int>(result), m_queue, m_index,
m_submit_seq, m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2,
m_debug_arg3, m_debug_arg4);
}
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
}
void CommandBuffer::WaitForFence() {
@ -505,16 +507,16 @@ void CommandBuffer::WaitForFenceOnly() {
if (!m_execute || m_fence_waited) {
return;
}
auto* device = g_render_ctx->GetGraphicCtx()->device;
auto result = vkWaitForFences(device, 1, &m_pool->fences[m_index], VK_TRUE, UINT64_MAX);
if (result != VK_SUCCESS) {
auto device = g_render_ctx->GetGraphicCtx()->device;
auto result = device.waitForFences(1, &m_pool->fences[m_index], VK_TRUE, UINT64_MAX);
if (result != vk::Result::eSuccess) {
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",
string_VkResult(result), static_cast<int>(result), m_queue, m_index, m_submit_seq,
m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2, m_debug_arg3,
m_debug_arg4);
VulkanToString(result).c_str(), static_cast<int>(result), m_queue, m_index,
m_submit_seq, m_debug_op, m_debug_submit_id, m_debug_arg0, m_debug_arg1, m_debug_arg2,
m_debug_arg3, m_debug_arg4);
}
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
m_fence_waited = true;
}
@ -524,8 +526,7 @@ void CommandBuffer::WaitForFenceAndReset() {
if (was_executed) {
m_execute = false;
m_fence_waited = false;
vkResetCommandBuffer(m_pool->buffers[m_index],
VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
m_pool->buffers[m_index].reset(vk::CommandBufferResetFlagBits::eReleaseResources);
m_recording_generation++;
}
m_host_stream.Reset();
@ -544,13 +545,13 @@ void CommandBuffer::BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorI
uint32_t requested_color_count, RenderDepthInfo* depth) const {
EXIT_IF(IsInvalid());
auto* buffer = m_pool->buffers[m_index];
auto buffer = m_pool->buffers[m_index];
EXIT_IF(framebuffer == nullptr);
EXIT_IF(colors == nullptr);
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;
for (uint32_t i = 0; i < requested_color_count; i++) {
if (colors[i].vulkan_buffer == nullptr) {
@ -562,16 +563,16 @@ void CommandBuffer::BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorI
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++) {
clears[i].color = colors[i].color_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 {};
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
vk::RenderPassBeginInfo render_pass_info {};
render_pass_info.sType = vk::StructureType::eRenderPassBeginInfo;
render_pass_info.pNext = nullptr;
render_pass_info.renderPass = framebuffer->render_pass;
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 (graphics_debug_dump_enabled()) {
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,
string_VkImageLayout(colors[i].vulkan_buffer->layout),
string_VkImageLayout(color_initial_layout));
VulkanToString(colors[i].vulkan_buffer->layout).c_str(),
VulkanToString(color_initial_layout).c_str());
}
VkImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = 0;
image_memory_barrier.dstAccessMask =
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
image_memory_barrier.oldLayout = colors[i].vulkan_buffer->layout;
image_memory_barrier.newLayout = color_initial_layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = colors[i].vulkan_buffer->image;
image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vk::ImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = vk::StructureType::eImageMemoryBarrier;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = {};
image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead |
vk::AccessFlagBits::eColorAttachmentWrite;
image_memory_barrier.oldLayout = colors[i].vulkan_buffer->layout;
image_memory_barrier.newLayout = color_initial_layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = colors[i].vulkan_buffer->image;
image_memory_barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
image_memory_barrier.subresourceRange.baseMipLevel = 0;
image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
image_memory_barrier.subresourceRange.layerCount = colors[i].vulkan_buffer->layers;
vkCmdPipelineBarrier(buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0,
nullptr, 1, &image_memory_barrier);
buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1,
&image_memory_barrier);
colors[i].vulkan_buffer->layout = image_memory_barrier.newLayout;
} else if (graphics_debug_dump_enabled()) {
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,
string_VkImageLayout(colors[i].vulkan_buffer->layout));
VulkanToString(colors[i].vulkan_buffer->layout).c_str());
}
}
const auto 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) {
VkImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
vk::ImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = vk::StructureType::eImageMemoryBarrier;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask =
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
image_memory_barrier.dstAccessMask =
(depth_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
? VK_ACCESS_MEMORY_READ_BIT
: VK_ACCESS_MEMORY_WRITE_BIT);
(depth_layout == vk::ImageLayout::eDepthStencilReadOnlyOptimal
? vk::AccessFlagBits::eMemoryRead
: vk::AccessFlagBits::eMemoryWrite);
image_memory_barrier.oldLayout = depth->vulkan_buffer->layout;
image_memory_barrier.newLayout = depth_layout;
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.layerCount = depth->vulkan_buffer->layers;
vkCmdPipelineBarrier(
buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0,
nullptr, 0, nullptr, 1, &image_memory_barrier);
buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader,
vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader,
vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
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++) {
colors[i].vulkan_buffer->layout = RENDER_COLOR_IMAGE_LAYOUT;
@ -664,9 +667,9 @@ void CommandBuffer::BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorI
void CommandBuffer::EndRenderPass() const {
EXIT_IF(IsInvalid());
auto* buffer = m_pool->buffers[m_index];
auto buffer = m_pool->buffers[m_index];
vkCmdEndRenderPass(buffer);
buffer.endRenderPass();
}
} // namespace Libs::Graphics

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,
VkExtent2D extent) {
vk::Extent2D extent) {
ScissorRect screen {vp.screen_scissor_left, vp.screen_scissor_top, vp.screen_scissor_right,
vp.screen_scissor_bottom};
ScissorRect final = screen;

View File

@ -1,10 +1,11 @@
#ifndef 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 <string>
#include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -37,7 +38,7 @@ void hw_print(const HW::Context& hw);
void hw_check(const HW::Context& hw);
void LogDrawPhase(const char* draw_name, const char* phase);
ScissorRect calc_final_scissor(const HW::ScreenViewport& vp, const HW::ScanModeControl& smc,
VkExtent2D extent);
vk::Extent2D extent);
} // namespace Libs::Graphics

View File

@ -17,6 +17,7 @@
#include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/displayBuffer.h"
#include <algorithm>
@ -25,7 +26,6 @@
#include <cstdarg>
#include <cstdio>
#include <limits>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics {
@ -40,17 +40,17 @@ namespace Libs::Graphics {
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)) {
case Prospero::StencilOp::kKeep: return VK_STENCIL_OP_KEEP;
case Prospero::StencilOp::kZero: return VK_STENCIL_OP_ZERO;
case Prospero::StencilOp::kKeep: return vk::StencilOp::eKeep;
case Prospero::StencilOp::kZero: return vk::StencilOp::eZero;
case Prospero::StencilOp::kReplaceTest:
case Prospero::StencilOp::kReplaceOp: return VK_STENCIL_OP_REPLACE;
case Prospero::StencilOp::kAddClamp: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
case Prospero::StencilOp::kSubClamp: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
case Prospero::StencilOp::kInvert: return VK_STENCIL_OP_INVERT;
case Prospero::StencilOp::kAddWrap: return VK_STENCIL_OP_INCREMENT_AND_WRAP;
case Prospero::StencilOp::kSubWrap: return VK_STENCIL_OP_DECREMENT_AND_WRAP;
case Prospero::StencilOp::kReplaceOp: return vk::StencilOp::eReplace;
case Prospero::StencilOp::kAddClamp: return vk::StencilOp::eIncrementAndClamp;
case Prospero::StencilOp::kSubClamp: return vk::StencilOp::eDecrementAndClamp;
case Prospero::StencilOp::kInvert: return vk::StencilOp::eInvert;
case Prospero::StencilOp::kAddWrap: return vk::StencilOp::eIncrementAndWrap;
case Prospero::StencilOp::kSubWrap: return vk::StencilOp::eDecrementAndWrap;
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);
}
[[nodiscard]] static VkFormat ResolveHostDepthAttachmentFormat(GraphicContext* ctx,
const DepthFormatPolicy& policy,
bool has_stencil) {
[[nodiscard]] static vk::Format ResolveHostDepthAttachmentFormat(GraphicContext* ctx,
const DepthFormatPolicy& policy,
bool has_stencil) {
if (!has_stencil) {
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::kZ16: {
if (ctx == nullptr) {
return VK_FORMAT_UNDEFINED;
return vk::Format::eUndefined;
}
for (const auto format: policy.stencil_attachment_formats) {
VkImageFormatProperties properties {};
if (ctx->GetImageFormatProperties(format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
DepthTargetImageUsage(), 0,
&properties) == VK_SUCCESS) {
vk::ImageFormatProperties properties {};
if (ctx->GetImageFormatProperties(format, vk::ImageType::e2D,
vk::ImageTiling::eOptimal,
DepthTargetImageUsage(), vk::ImageCreateFlags {},
&properties) == vk::Result::eSuccess) {
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.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 ||
dc.zfunc > static_cast<uint8_t>(VK_COMPARE_OP_ALWAYS)) {
dc.zfunc > static_cast<uint8_t>(vk::CompareOp::eAlways)) {
DepthFatal("unsupported depth register state");
}
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);
r->format =
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",
string_VkFormat(ideal_format));
VulkanToString(ideal_format).c_str());
}
const uint32_t guest_format = Prospero::GpuEnumValue(policy->guest_format);
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_test_enable = dc.z_enable;
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_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_test_enable = 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.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) &&
sm.stencil_opval != sm.stencil_testval) ||
(dc.backface_enable &&
@ -346,14 +347,15 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
}
r->stencil_static_front = {
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,
rc.stencil_clear_enable ? 0u : sm.stencil_writemask,
sm.stencil_testval};
if (dc.backface_enable) {
r->stencil_static_back = {
ConvertStencilOp(sc.stencil_fail_bf), ConvertStencilOp(sc.stencil_zpass_bf),
ConvertStencilOp(sc.stencil_zfail_bf), static_cast<VkCompareOp>(dc.stencilfunc_bf)};
r->stencil_static_back = {ConvertStencilOp(sc.stencil_fail_bf),
ConvertStencilOp(sc.stencil_zpass_bf),
ConvertStencilOp(sc.stencil_zfail_bf),
static_cast<vk::CompareOp>(dc.stencilfunc_bf)};
r->stencil_dynamic_back = {sm.stencil_mask_bf,
rc.stencil_clear_enable ? 0u : sm.stencil_writemask_bf,
sm.stencil_testval_bf};
@ -402,7 +404,8 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
}
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)) {
g_render_ctx->GetTextureCache()->MarkGpuWritten(target.vulkan_buffer);

View File

@ -3,9 +3,9 @@
#include "common/assert.h"
#include "graphics/host_gpu/renderer/renderTarget.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <cstdint>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -22,7 +22,7 @@ inline constexpr bool depth_htile_stencil_acceleration_compatible(bool has_stenc
}
struct RenderDepthInfo {
VkFormat format = VK_FORMAT_UNDEFINED;
vk::Format format = vk::Format::eUndefined;
uint32_t width = 0;
uint32_t height = 0;
bool htile = false;
@ -41,7 +41,7 @@ struct RenderDepthInfo {
float depth_clear_value = 0.0f;
bool depth_test_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;
float depth_min_bounds = 0.0f;
float depth_max_bounds = 0.0f;
@ -53,7 +53,7 @@ struct RenderDepthInfo {
PipelineStencilDynamicState stencil_dynamic_front;
PipelineStencilDynamicState stencil_dynamic_back;
DepthStencilVulkanImage* vulkan_buffer = nullptr;
VkImageView vulkan_view = nullptr;
vk::ImageView vulkan_view = nullptr;
uint64_t vaddr[3] = {};
uint64_t size[3] = {};
int vaddr_num = 0;
@ -68,9 +68,9 @@ inline bool depth_attachment_read_only(const RenderDepthInfo* depth) {
!depth->depth_write_enable && !stencil_write;
}
inline VkImageLayout depth_attachment_layout(const RenderDepthInfo* depth) {
return depth_attachment_read_only(depth) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
inline vk::ImageLayout depth_attachment_layout(const RenderDepthInfo* depth) {
return depth_attachment_read_only(depth) ? vk::ImageLayout::eDepthStencilReadOnlyOptimal
: vk::ImageLayout::eDepthStencilAttachmentOptimal;
}
void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const HW::Context& hw,

View File

@ -12,11 +12,11 @@ namespace {
using BindingKind = ShaderRecompiler::IR::DescriptorBindingKind;
VkShaderStageFlags StageFlags(DescriptorCache::Stage stage) {
vk::ShaderStageFlags StageFlags(DescriptorCache::Stage stage) {
switch (stage) {
case DescriptorCache::Stage::Vertex: return VK_SHADER_STAGE_VERTEX_BIT;
case DescriptorCache::Stage::Pixel: return VK_SHADER_STAGE_FRAGMENT_BIT;
case DescriptorCache::Stage::Compute: return VK_SHADER_STAGE_COMPUTE_BIT;
case DescriptorCache::Stage::Vertex: return vk::ShaderStageFlagBits::eVertex;
case DescriptorCache::Stage::Pixel: return vk::ShaderStageFlagBits::eFragment;
case DescriptorCache::Stage::Compute: return vk::ShaderStageFlagBits::eCompute;
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) {
return VK_DESCRIPTOR_TYPE_SAMPLER;
return vk::DescriptorType::eSampler;
}
if (IsSampledImage(kind)) {
return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
return vk::DescriptorType::eSampledImage;
}
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) {
@ -76,23 +76,23 @@ std::vector<uint32_t> LayoutKey(DescriptorCache::Stage stage,
return key;
}
VkImageLayout SampledLayout(const VulkanImage* image) {
vk::ImageLayout SampledLayout(const VulkanImage* image) {
EXIT_IF(image == nullptr);
switch (image->layout) {
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: return VK_IMAGE_LAYOUT_GENERAL;
case vk::ImageLayout::eTransferDstOptimal:
case vk::ImageLayout::eTransferSrcOptimal:
case vk::ImageLayout::eColorAttachmentOptimal: return vk::ImageLayout::eGeneral;
default: return image->layout;
}
}
VkDescriptorBufferInfo BufferInfo(const BufferView& view) {
vk::DescriptorBufferInfo BufferInfo(const BufferView& view) {
EXIT_IF(view.buffer == nullptr || view.buffer->buffer == nullptr);
return {view.buffer->buffer, view.offset, view.range};
}
VkDescriptorImageInfo MakeDescriptorImageInfo(const DescriptorCache::TextureBinding& texture,
VkImageLayout layout) {
vk::DescriptorImageInfo MakeDescriptorImageInfo(const DescriptorCache::TextureBinding& texture,
vk::ImageLayout layout) {
EXIT_IF(texture.image == nullptr || texture.view < 0 || texture.view >= VulkanImage::VIEW_MAX);
const auto view = texture.image_view != nullptr ? texture.image_view
: texture.image->image_view[texture.view];
@ -106,7 +106,7 @@ void DescriptorCache::Init() {
m_initialized = true;
}
VkDescriptorSetLayout
vk::DescriptorSetLayout
DescriptorCache::GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stage,
const ShaderRecompiler::IR::Program& program) {
EXIT_IF(gctx == nullptr);
@ -117,7 +117,7 @@ DescriptorCache::GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stag
return found->second;
}
std::vector<VkDescriptorSetLayoutBinding> bindings;
std::vector<vk::DescriptorSetLayoutBinding> bindings;
bindings.reserve(program.bindings.descriptors.size());
for (const auto& descriptor: program.bindings.descriptors) {
bindings.push_back({descriptor.binding, DescriptorType(descriptor.kind),
@ -127,12 +127,12 @@ DescriptorCache::GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stag
return nullptr;
}
VkDescriptorSetLayoutCreateInfo info {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = static_cast<uint32_t>(bindings.size());
info.pBindings = bindings.data();
VkDescriptorSetLayout layout = nullptr;
vkCreateDescriptorSetLayout(gctx->device, &info, nullptr, &layout);
vk::DescriptorSetLayoutCreateInfo info {};
info.sType = vk::StructureType::eDescriptorSetLayoutCreateInfo;
info.bindingCount = static_cast<uint32_t>(bindings.size());
info.pBindings = bindings.data();
vk::DescriptorSetLayout layout = nullptr;
gctx->device.createDescriptorSetLayout(&info, nullptr, &layout);
EXIT_NOT_IMPLEMENTED(layout == nullptr);
m_descriptor_set_layouts.emplace(key, layout);
return layout;
@ -141,23 +141,23 @@ DescriptorCache::GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stag
void DescriptorCache::CreatePool(GraphicContext* gctx) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(gctx == nullptr);
constexpr uint32_t MaxSets = 512;
const VkDescriptorPoolSize sizes[] = {
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
constexpr uint32_t MaxSets = 512;
const vk::DescriptorPoolSize sizes[] = {
{vk::DescriptorType::eStorageBuffer,
MaxSets * (ShaderRecompiler::IR::ShaderInfo::MaxBuffers +
ShaderRecompiler::IR::ShaderInfo::MaxAddresses + 3u)},
{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxImages},
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxImages},
{VK_DESCRIPTOR_TYPE_SAMPLER, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxSamplers},
{vk::DescriptorType::eSampledImage, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxImages},
{vk::DescriptorType::eStorageImage, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxImages},
{vk::DescriptorType::eSampler, MaxSets * ShaderRecompiler::IR::ShaderInfo::MaxSamplers},
};
VkDescriptorPoolCreateInfo info {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
vk::DescriptorPoolCreateInfo info {};
info.sType = vk::StructureType::eDescriptorPoolCreateInfo;
info.poolSizeCount = static_cast<uint32_t>(std::size(sizes));
info.pPoolSizes = sizes;
info.maxSets = MaxSets;
const auto pool_id = static_cast<int>(m_pools.size());
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);
pool.next_free_pool = m_first_free_pool;
m_first_free_pool = pool_id;
@ -182,16 +182,16 @@ VulkanDescriptorSet* DescriptorCache::Allocate(Stage
for (int attempt = 0; attempt < 2; attempt++) {
for (int pool_id = m_first_free_pool; pool_id != -1;
pool_id = m_pools[pool_id].next_free_pool) {
auto& pool = m_pools[pool_id];
std::array<VkDescriptorSetLayout, Batch> layouts;
auto& pool = m_pools[pool_id];
std::array<vk::DescriptorSetLayout, Batch> layouts;
layouts.fill(layout);
std::array<VkDescriptorSet, Batch> sets {};
VkDescriptorSetAllocateInfo info {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
std::array<vk::DescriptorSet, Batch> sets {};
vk::DescriptorSetAllocateInfo info {};
info.sType = vk::StructureType::eDescriptorSetAllocateInfo;
info.descriptorPool = pool.pool;
info.descriptorSetCount = Batch;
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);
for (uint32_t i = 0; i + 1u < Batch; i++) {
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() +
program.info.samplers.size() + program.info.addresses.size() + 3u;
std::vector<VkDescriptorBufferInfo> buffer_infos;
std::vector<VkDescriptorImageInfo> image_infos;
std::vector<VkWriteDescriptorSet> writes;
std::vector<vk::DescriptorBufferInfo> buffer_infos;
std::vector<vk::DescriptorImageInfo> image_infos;
std::vector<vk::WriteDescriptorSet> writes;
buffer_infos.reserve(descriptor_count);
image_infos.reserve(descriptor_count);
writes.reserve(program.bindings.descriptors.size());
for (const auto& binding: program.bindings.descriptors) {
VkWriteDescriptorSet write {};
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
vk::WriteDescriptorSet write {};
write.sType = vk::StructureType::eWriteDescriptorSet;
write.dstSet = set->set;
write.dstBinding = binding.binding;
write.descriptorType = DescriptorType(binding.kind);
@ -264,12 +264,12 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage
for (const auto resource: binding.resources) {
const auto sampler = data.samplers.at(resource);
EXIT_IF(sampler == nullptr);
image_infos.push_back({sampler, nullptr, VK_IMAGE_LAYOUT_UNDEFINED});
image_infos.push_back({sampler, nullptr, vk::ImageLayout::eUndefined});
}
break;
default: {
const auto layout = IsStorageImage(binding.kind) ? VK_IMAGE_LAYOUT_GENERAL
: VK_IMAGE_LAYOUT_UNDEFINED;
const auto layout = IsStorageImage(binding.kind) ? vk::ImageLayout::eGeneral
: vk::ImageLayout::eUndefined;
for (const auto resource: binding.resources) {
const auto& texture = data.images.at(resource);
image_infos.push_back(MakeDescriptorImageInfo(
@ -287,12 +287,12 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage
}
writes.push_back(write);
}
vkUpdateDescriptorSets(gctx->device, static_cast<uint32_t>(writes.size()), writes.data(), 0,
nullptr);
gctx->device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0,
nullptr);
return set;
}
VkDescriptorSetLayout
vk::DescriptorSetLayout
DescriptorCache::GetDescriptorSetLayout(Stage stage, const ShaderRecompiler::IR::Program& program) {
auto* gctx = g_render_ctx->GetGraphicCtx();
EXIT_IF(gctx == nullptr);

View File

@ -6,12 +6,12 @@
#include "common/common.h"
#include "common/threads.h"
#include "graphics/host_gpu/graphicContext.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/shaderBindings.h"
#include <map>
#include <unordered_map>
#include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -23,19 +23,19 @@ class CommandBuffer;
struct ShaderStageRuntime;
struct VulkanDescriptor {
VkDescriptorSet descriptor_set = nullptr;
vk::DescriptorSet descriptor_set = nullptr;
};
struct VulkanDescriptorSet {
VkDescriptorSet set = nullptr;
VkDescriptorSetLayout layout = nullptr;
int pool_id = -1;
vk::DescriptorSet set = nullptr;
vk::DescriptorSetLayout layout = nullptr;
int pool_id = -1;
};
struct BufferView {
VulkanBuffer* buffer = nullptr;
VkDeviceSize offset = 0;
VkDeviceSize range = VK_WHOLE_SIZE;
VulkanBuffer* buffer = nullptr;
vk::DeviceSize offset = 0;
vk::DeviceSize range = VK_WHOLE_SIZE;
};
struct ShaderAddressWriteRange {
@ -49,9 +49,9 @@ public:
enum class Stage { Unknown, Vertex, Pixel, Compute };
struct TextureBinding {
VulkanImage* image = nullptr;
int view = VulkanImage::VIEW_DEFAULT;
VkImageView image_view = nullptr;
VulkanImage* image = nullptr;
int view = VulkanImage::VIEW_DEFAULT;
vk::ImageView image_view = nullptr;
};
enum class TextureVariant : int {
@ -66,7 +66,7 @@ public:
struct NativeDescriptors {
std::vector<BufferView> buffers;
std::vector<TextureBinding> images;
std::vector<VkSampler> samplers;
std::vector<vk::Sampler> samplers;
std::vector<BufferView> addresses;
BufferView gds;
BufferView flattened_srt;
@ -77,41 +77,43 @@ public:
virtual ~DescriptorCache() { KYTY_NOT_IMPLEMENTED; }
KYTY_CLASS_NO_COPY(DescriptorCache);
VkDescriptorSetLayout GetDescriptorSetLayout(Stage stage,
const ShaderRecompiler::IR::Program& program);
void Recycle(VulkanDescriptorSet* set);
VulkanDescriptorSet* GetDescriptor(Stage stage, const ShaderRecompiler::IR::Program& program,
const NativeDescriptors& descriptors);
vk::DescriptorSetLayout GetDescriptorSetLayout(Stage stage,
const ShaderRecompiler::IR::Program& program);
void Recycle(VulkanDescriptorSet* set);
VulkanDescriptorSet* GetDescriptor(Stage stage, const ShaderRecompiler::IR::Program& program,
const NativeDescriptors& descriptors);
private:
struct Pool {
VkDescriptorPool pool = nullptr;
int next_free_pool = -1;
bool free = true;
vk::DescriptorPool pool = nullptr;
int next_free_pool = -1;
bool free = true;
};
void Init();
void CreatePool(GraphicContext* gctx);
VulkanDescriptorSet* Allocate(Stage stage, const ShaderRecompiler::IR::Program& program);
VkDescriptorSetLayout
vk::DescriptorSetLayout
GetDescriptorSetLayoutInternal(GraphicContext* gctx, Stage stage,
const ShaderRecompiler::IR::Program& program);
Common::Mutex m_mutex;
std::vector<Pool> m_pools;
int m_first_free_pool = -1;
std::unordered_map<VkDescriptorSetLayout, std::vector<VulkanDescriptorSet*>>
m_free_sets_by_layout;
std::map<std::vector<uint32_t>, VkDescriptorSetLayout> m_descriptor_set_layouts;
bool m_initialized = false;
std::unordered_map<vk::DescriptorSetLayout, std::vector<VulkanDescriptorSet*>>
m_free_sets_by_layout;
std::map<std::vector<uint32_t>, vk::DescriptorSetLayout> m_descriptor_set_layouts;
bool m_initialized = false;
};
const char* storage_usage_name(ShaderStorageUsage usage);
VkImageAspectFlags DepthStencilAspectMask(VkFormat format);
std::vector<ShaderAddressWriteRange>
BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint pipeline_bind_point,
VkPipelineLayout layout, const ShaderStageRuntime& runtime,
VkShaderStageFlags vk_stage, DescriptorCache::Stage stage);
const char* storage_usage_name(ShaderStorageUsage usage);
vk::ImageAspectFlags DepthStencilAspectMask(vk::Format format);
std::vector<ShaderAddressWriteRange> BindDescriptors(uint64_t submit_id, CommandBuffer* buffer,
vk::PipelineBindPoint pipeline_bind_point,
vk::PipelineLayout layout,
const ShaderStageRuntime& runtime,
vk::ShaderStageFlags vk_stage,
DescriptorCache::Stage stage);
} // namespace Libs::Graphics

View File

@ -25,6 +25,7 @@
#include "graphics/host_gpu/renderer/shaderResourceBarrier.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/displayBuffer.h"
#include "graphics/shader/recompiler/BindingLayout.h"
#include "graphics/shader/recompiler/ResourceMaterialization.h"
@ -36,7 +37,6 @@
#include <cstring>
#include <fmt/format.h>
#include <limits>
#include <vulkan/vk_enum_string_helper.h>
#ifdef min
#undef min
@ -71,10 +71,10 @@ static const char* VulkanImageTypeName(VulkanImageType type) {
}
}
VkImageAspectFlags DepthStencilAspectMask(VkFormat format) {
auto ret = static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT);
if (format == VK_FORMAT_D24_UNORM_S8_UINT || format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
ret |= VK_IMAGE_ASPECT_STENCIL_BIT;
vk::ImageAspectFlags DepthStencilAspectMask(vk::Format format) {
auto ret = static_cast<vk::ImageAspectFlags>(vk::ImageAspectFlagBits::eDepth);
if (format == vk::Format::eD24UnormS8Uint || format == vk::Format::eD32SfloatS8Uint) {
ret |= vk::ImageAspectFlagBits::eStencil;
}
return ret;
}
@ -229,7 +229,7 @@ static BufferView NativeStorageBuffer(uint64_t submit_id, CommandBuffer* command
}
result.buffer = binding.first;
result.offset = binding.second;
result.range = static_cast<VkDeviceSize>(size);
result.range = static_cast<vk::DeviceSize>(size);
return result;
}
@ -267,7 +267,7 @@ NativeAddressBuffer(uint64_t submit_id, CommandBuffer* command_buffer,
address.binding_base, size);
result.buffer = binding.first;
result.offset = binding.second;
result.range = static_cast<VkDeviceSize>(size);
result.range = static_cast<vk::DeviceSize>(size);
return result;
}
@ -306,16 +306,16 @@ TargetTextureViewInfo ResolveTargetTextureView(const ShaderRecompiler::IR::Image
case Prospero::ImageType::kColor2D:
return resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D &&
base_layer == 0 && image_layers == 1
? TargetTextureViewInfo {VK_IMAGE_VIEW_TYPE_2D, 0, 1}
? TargetTextureViewInfo {vk::ImageViewType::e2D, 0, 1}
: TargetTextureViewInfo {};
case Prospero::ImageType::kColor2DArray:
if (resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D &&
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 &&
base_layer < image_layers
? TargetTextureViewInfo {VK_IMAGE_VIEW_TYPE_2D_ARRAY, base_layer,
? TargetTextureViewInfo {vk::ImageViewType::e2DArray, base_layer,
image_layers - base_layer}
: TargetTextureViewInfo {};
default: return {};
@ -365,7 +365,7 @@ static bool IsSupportedDepthTextureEncoding(const ShaderTextureResource& descrip
static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource& resource,
const ShaderTextureResource& descriptor,
const VulkanImage* image, VkFormat view_format,
const VulkanImage* image, vk::Format view_format,
uint64_t size) {
const bool resource_ok = IsSupportedSampledDepthResource(resource);
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),
resource.read, resource.written, resource.atomic, resource.depth_compare,
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(),
descriptor.BaseArray5(), descriptor.Depth(), descriptor_pitch,
image == nullptr ? 0u : image->guest_pitch, descriptor.Base40(), size,
@ -559,11 +560,11 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer,
resource.written);
}
VulkanImage* image = nullptr;
int view = VulkanImage::VIEW_DEFAULT;
VkImageView image_view = nullptr;
const bool check_depth = static_cast<Prospero::TileMode>(tile) == Prospero::TileMode::kDepth ||
descriptor.MsaaDepth();
VulkanImage* image = nullptr;
int view = VulkanImage::VIEW_DEFAULT;
vk::ImageView image_view = nullptr;
const bool check_depth = static_cast<Prospero::TileMode>(tile) == Prospero::TileMode::kDepth ||
descriptor.MsaaDepth();
if (image == nullptr) {
if (check_depth) {
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(
resource, type, descriptor.BaseArray5(), image->layers);
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 "
"descriptor_type=%u "
"base_array=%u image_layers=%u\n",
@ -611,7 +613,8 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer,
height != image->extent.height ||
(storage ? levels != image->mip_levels || base_level != 0
: 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.layer_count > image->layers - target_view.base_layer) {
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.read && resource.written && !resource.atomic &&
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 &&
depth == 1 && levels == 1 && base_level == 0 && view_levels == 1 &&
type == Prospero::ImageType::kColor2D && video.size == size.size &&
video.pitch == pitch &&
(video.image->format == VK_FORMAT_R8G8B8A8_SRGB ||
video.image->format == VK_FORMAT_B8G8R8A8_SRGB) &&
(video.image->format == vk::Format::eR8G8B8A8Srgb ||
video.image->format == vk::Format::eB8G8R8A8Srgb) &&
video.image->image_view[VulkanImage::VIEW_STORAGE] != nullptr;
if (!exact) {
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_view = g_render_ctx->GetTextureCache()->GetSampledColorView(
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};
}
static VkSampler NativeSampler(const ShaderRecompiler::IR::Program& program, uint32_t index,
const ShaderRecompiler::IR::DescriptorValue& value) {
static vk::Sampler NativeSampler(const ShaderRecompiler::IR::Program& program, uint32_t index,
const ShaderRecompiler::IR::DescriptorValue& value) {
auto descriptor = NativeSamplerDescriptor(value);
const bool depth_compare = std::any_of(program.info.sampled_pairs.begin(),
program.info.sampled_pairs.end(), [&](const auto& pair) {
@ -773,10 +776,12 @@ static BufferView NativeUpload(CommandBuffer* command_buffer, std::span<const ui
return result;
}
std::vector<ShaderAddressWriteRange>
BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint pipeline_bind_point,
VkPipelineLayout layout, const ShaderStageRuntime& runtime,
VkShaderStageFlags vk_stage, DescriptorCache::Stage stage) {
std::vector<ShaderAddressWriteRange> BindDescriptors(uint64_t submit_id, CommandBuffer* buffer,
vk::PipelineBindPoint pipeline_bind_point,
vk::PipelineLayout layout,
const ShaderStageRuntime& runtime,
vk::ShaderStageFlags vk_stage,
DescriptorCache::Stage stage) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(buffer == nullptr || !runtime);
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)) {
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);
DescriptorCache::NativeDescriptors descriptors;
@ -800,7 +805,7 @@ BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint p
const auto kind = program.info.images[i].kind;
if ((kind == ShaderRecompiler::IR::ResourceKind::StorageImage ||
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");
}
descriptors.images.push_back(
@ -843,11 +848,10 @@ BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint p
descriptors.gds.buffer =
g_render_ctx->GetGdsBuffer()->GetBuffer(g_render_ctx->GetGraphicCtx());
const auto barrier = MakeGdsDependency(*descriptors.gds.buffer);
vkCmdPipelineBarrier(vk_buffer,
VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT |
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
shader_stages, 0, 0, nullptr, 1, &barrier, 0, nullptr);
vk_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eHost | vk::PipelineStageFlagBits::eTransfer |
vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader,
shader_stages, vk::DependencyFlags {}, 0, nullptr, 1, &barrier, 0, nullptr);
}
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 {
const auto barrier =
MakeStorageImageDependency(*image, resource.read, resource.written);
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, shader_stages, 0, 0,
nullptr, 0, nullptr, 1, &barrier);
image->layout = VK_IMAGE_LAYOUT_GENERAL;
vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, shader_stages,
vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1, &barrier);
image->layout = vk::ImageLayout::eGeneral;
}
}
if (!program.bindings.descriptors.empty()) {
auto* set = g_render_ctx->GetDescriptorCache()->GetDescriptor(stage, program, descriptors);
EXIT_IF(set == nullptr);
vkCmdBindDescriptorSets(vk_buffer, pipeline_bind_point, layout,
program.bindings.descriptor_set, 1, &set->set, 0, nullptr);
vk_buffer.bindDescriptorSets(pipeline_bind_point, layout, program.bindings.descriptor_set,
1, &set->set, 0, nullptr);
buffer->RecycleDescriptorAfterFence(set);
}
if (program.bindings.push_constant_size != 0) {
EXIT_IF(program.bindings.push_constant_size != user_data.size() * sizeof(uint32_t));
vkCmdPushConstants(vk_buffer, layout, vk_stage, program.bindings.push_constant_offset,
program.bindings.push_constant_size, user_data.data());
vk_buffer.pushConstants(layout, vk_stage, program.bindings.push_constant_offset,
program.bindings.push_constant_size, user_data.data());
}
return address_writes;
}

View File

@ -1,20 +1,20 @@
#ifndef 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/shaderBindings.h"
#include <cstdint>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
struct VulkanImage;
struct TargetTextureViewInfo {
VkImageViewType type = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
uint32_t base_layer = 0;
uint32_t layer_count = 0;
vk::ImageViewType type = static_cast<vk::ImageViewType>(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
uint32_t base_layer = 0;
uint32_t layer_count = 0;
};
[[nodiscard]] TargetTextureViewInfo

View File

@ -7,10 +7,10 @@
#include "graphics/host_gpu/renderer/depthRenderTarget.h"
#include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <algorithm>
#include <atomic>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics {
@ -26,11 +26,11 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(requested_color_count > RENDER_COLOR_ATTACHMENTS_MAX);
bool with_depth = (depth->format != VK_FORMAT_UNDEFINED && depth->vulkan_buffer != nullptr);
bool with_color[RENDER_COLOR_ATTACHMENTS_MAX] = {};
uint32_t color_count = 0;
VulkanImage* first_color = nullptr;
VkExtent2D first_color_extent = {};
bool with_depth = (depth->format != vk::Format::eUndefined && depth->vulkan_buffer != nullptr);
bool with_color[RENDER_COLOR_ATTACHMENTS_MAX] = {};
uint32_t color_count = 0;
VulkanImage* first_color = nullptr;
vk::Extent2D first_color_extent = {};
for (uint32_t i = 0; i < requested_color_count; i++) {
with_color[i] = (colors[i].vulkan_buffer != nullptr);
if (!with_color[i]) {
@ -50,14 +50,14 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
}
color_count++;
}
VkImageLayout color_layout[RENDER_COLOR_ATTACHMENTS_MAX] = {};
vk::ImageLayout color_layout[RENDER_COLOR_ATTACHMENTS_MAX] = {};
for (auto& layout: color_layout) {
layout = RENDER_COLOR_IMAGE_LAYOUT;
}
auto depth_layout = (with_depth ? depth_attachment_layout(depth)
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
: vk::ImageLayout::eDepthStencilAttachmentOptimal);
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 &&
(first_color_extent.width != depth->vulkan_buffer->extent.width ||
@ -68,9 +68,9 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
"depth=%ux%u format=%s\n",
first_color_extent.width, first_color_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_view = nullptr;
depth->depth_test_enable = false;
@ -81,7 +81,7 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
depth->depth_load_clear_enable = false;
depth->stencil_clear_enable = false;
with_depth = false;
depth_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depth_layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
depth_read_only = false;
}
@ -131,51 +131,53 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
first_color_extent.height != depth->vulkan_buffer->extent.height));
if (first_color == nullptr) {
first_color = CreateDummyBuffer(VK_FORMAT_B8G8R8A8_SRGB, depth->vulkan_buffer->extent.width,
depth->vulkan_buffer->extent.height);
first_color =
CreateDummyBuffer(vk::Format::eB8G8R8A8Srgb, depth->vulkan_buffer->extent.width,
depth->vulkan_buffer->extent.height);
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++) {
attachments[i].flags = 0;
attachments[i].format = colors[i].format;
attachments[i].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[i].loadOp = (colors[i].color_clear_enable ? VK_ATTACHMENT_LOAD_OP_CLEAR
: VK_ATTACHMENT_LOAD_OP_LOAD);
attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[i].flags = {};
attachments[i].format = colors[i].format;
attachments[i].samples = vk::SampleCountFlagBits::e1;
attachments[i].loadOp = (colors[i].color_clear_enable ? vk::AttachmentLoadOp::eClear
: vk::AttachmentLoadOp::eLoad);
attachments[i].storeOp = vk::AttachmentStoreOp::eStore;
attachments[i].stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
attachments[i].stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
attachments[i].initialLayout = color_layout[i];
attachments[i].finalLayout = RENDER_COLOR_IMAGE_LAYOUT;
}
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].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[depth_attachment].samples = vk::SampleCountFlagBits::e1;
attachments[depth_attachment].loadOp =
(depth->depth_load_clear_enable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
attachments[depth_attachment].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
(depth->depth_load_clear_enable ? vk::AttachmentLoadOp::eClear
: vk::AttachmentLoadOp::eLoad);
attachments[depth_attachment].storeOp = vk::AttachmentStoreOp::eStore;
attachments[depth_attachment].stencilLoadOp =
(depth->stencil_clear_enable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
attachments[depth_attachment].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
(depth->stencil_clear_enable ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad);
attachments[depth_attachment].stencilStoreOp = vk::AttachmentStoreOp::eStore;
attachments[depth_attachment].initialLayout = 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++) {
color_attachment_ref[i].attachment = (i < color_count ? i : VK_ATTACHMENT_UNUSED);
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.layout = depth_layout;
VkSubpassDescription subpass {};
subpass.flags = 0;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
vk::SubpassDescription subpass {};
subpass.flags = {};
subpass.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
subpass.inputAttachmentCount = 0;
subpass.pInputAttachments = nullptr;
subpass.colorAttachmentCount = color_count;
@ -185,34 +187,38 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = nullptr;
const auto attachment_stage_mask = static_cast<VkPipelineStageFlags>(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
const auto attachment_access_mask = static_cast<VkAccessFlags>(
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
const auto attachment_stage_mask =
static_cast<vk::PipelineStageFlags>(vk::PipelineStageFlagBits::eColorAttachmentOutput |
vk::PipelineStageFlagBits::eEarlyFragmentTests |
vk::PipelineStageFlagBits::eLateFragmentTests);
const auto attachment_access_mask = static_cast<vk::AccessFlags>(
vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite |
vk::AccessFlagBits::eDepthStencilAttachmentRead |
vk::AccessFlagBits::eDepthStencilAttachmentWrite);
VkSubpassDependency dependencies[2] = {};
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
dependencies[0].dstStageMask = attachment_stage_mask;
dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
dependencies[0].dstAccessMask = attachment_access_mask;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
vk::SubpassDependency dependencies[2] = {};
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = vk::PipelineStageFlagBits::eAllCommands;
dependencies[0].dstStageMask = attachment_stage_mask;
dependencies[0].srcAccessMask =
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
dependencies[0].dstAccessMask = attachment_access_mask;
dependencies[0].dependencyFlags = vk::DependencyFlagBits::eByRegion;
dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = attachment_stage_mask;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
dependencies[1].srcAccessMask = attachment_access_mask;
dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = attachment_stage_mask;
dependencies[1].dstStageMask = vk::PipelineStageFlagBits::eAllCommands;
dependencies[1].srcAccessMask = attachment_access_mask;
dependencies[1].dstAccessMask =
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
dependencies[1].dependencyFlags = vk::DependencyFlagBits::eByRegion;
VkRenderPassCreateInfo render_pass_info {};
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
vk::RenderPassCreateInfo render_pass_info {};
render_pass_info.sType = vk::StructureType::eRenderPassCreateInfo;
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.pAttachments = attachments;
render_pass_info.subpassCount = 1;
@ -221,10 +227,10 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
render_pass_info.pDependencies = dependencies;
auto result =
vkCreateRenderPass(gctx->device, &render_pass_info, nullptr, &framebuffer->render_pass);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
gctx->device.createRenderPass(&render_pass_info, nullptr, &framebuffer->render_pass);
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++) {
color_formats[i] = colors[i].format;
}
@ -233,7 +239,7 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
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++) {
if (colors[i].vulkan_view == nullptr) {
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;
}
VkFramebufferCreateInfo framebuffer_info {};
framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
vk::FramebufferCreateInfo framebuffer_info {};
framebuffer_info.sType = vk::StructureType::eFramebufferCreateInfo;
framebuffer_info.pNext = nullptr;
framebuffer_info.flags = 0;
framebuffer_info.flags = {};
framebuffer_info.renderPass = framebuffer->render_pass;
framebuffer_info.attachmentCount = color_count + (with_depth ? 1u : 0u);
framebuffer_info.pAttachments = views;
@ -258,9 +264,8 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* colors,
framebuffer_info.height = first_color_extent.height;
framebuffer_info.layers = 1;
result =
vkCreateFramebuffer(gctx->device, &framebuffer_info, nullptr, &framebuffer->framebuffer);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
result = gctx->device.createFramebuffer(&framebuffer_info, nullptr, &framebuffer->framebuffer);
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
EXIT_NOT_IMPLEMENTED(framebuffer->framebuffer == nullptr);
@ -316,9 +321,9 @@ void FramebufferCache::FreeFramebufferByColor(VulkanImage* image) {
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;
@ -339,9 +344,9 @@ void FramebufferCache::FreeFramebufferByDepth(DepthStencilVulkanImage* image) {
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;
@ -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) {
for (auto* b: m_dummy_buffers) {
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->format = format;
vk_obj->image = nullptr;
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED;
vk_obj->layout = vk::ImageLayout::eUndefined;
UtilResetImageViews(vk_obj);
VkImageCreateInfo image_info {};
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
vk::ImageCreateInfo image_info {};
image_info.sType = vk::StructureType::eImageCreateInfo;
image_info.pNext = nullptr;
image_info.flags = 0;
image_info.imageType = VK_IMAGE_TYPE_2D;
image_info.flags = {};
image_info.imageType = vk::ImageType::e2D;
image_info.extent.width = vk_obj->extent.width;
image_info.extent.height = vk_obj->extent.height;
image_info.extent.depth = 1;
image_info.mipLevels = 1;
image_info.arrayLayers = 1;
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.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_info.usage = vk::ImageUsageFlagBits::eColorAttachment;
image_info.sharingMode = vk::SharingMode::eExclusive;
image_info.samples = vk::SampleCountFlagBits::e1;
VulkanMemory mem;
mem.property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
mem.property = vk::MemoryPropertyFlagBits::eDeviceLocal;
bool created = VulkanCreateImage(ctx, &image_info, vk_obj, &mem);
EXIT_NOT_IMPLEMENTED(!created);
vk_obj->memory = mem;
VkImageViewCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
vk::ImageViewCreateInfo create_info {};
create_info.sType = vk::StructureType::eImageViewCreateInfo;
create_info.pNext = nullptr;
create_info.flags = 0;
create_info.flags = {};
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.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
create_info.components.r = vk::ComponentSwizzle::eIdentity;
create_info.components.g = vk::ComponentSwizzle::eIdentity;
create_info.components.b = vk::ComponentSwizzle::eIdentity;
create_info.components.a = vk::ComponentSwizzle::eIdentity;
create_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
create_info.subresourceRange.baseArrayLayer = 0;
create_info.subresourceRange.baseMipLevel = 0;
create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = 1;
vkCreateImageView(ctx->device, &create_info, nullptr,
&vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
ctx->device.createImageView(&create_info, nullptr,
&vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);

View File

@ -7,28 +7,28 @@
#include "common/threads.h"
#include "graphics/host_gpu/graphicContext.h"
#include "graphics/host_gpu/renderer/renderTarget.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
struct RenderColorInfo;
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 {
VkRenderPass render_pass = nullptr;
uint64_t render_pass_id = 0;
VkFramebuffer framebuffer = nullptr;
VkImageLayout color_layout[RENDER_COLOR_ATTACHMENTS_MAX] = {};
VkImageLayout depth_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
vk::RenderPass render_pass = nullptr;
uint64_t render_pass_id = 0;
vk::Framebuffer framebuffer = nullptr;
vk::ImageLayout color_layout[RENDER_COLOR_ATTACHMENTS_MAX] = {};
vk::ImageLayout depth_layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
};
inline uint64_t render_pass_compat_id(uint32_t color_count, const VkFormat* color_formats,
bool with_depth, VkFormat depth_format,
VkImageLayout depth_layout) {
inline uint64_t render_pass_compat_id(uint32_t color_count, const vk::Format* color_formats,
bool with_depth, vk::Format depth_format,
vk::ImageLayout depth_layout) {
uint64_t id = 0xcbf29ce484222325ull;
auto mix = [&id](uint64_t 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(static_cast<uint32_t>(depth_format));
mix(static_cast<uint32_t>(depth_layout));
mix(VK_SAMPLE_COUNT_1_BIT);
mix(static_cast<uint32_t>(vk::SampleCountFlagBits::e1));
return id;
}
@ -59,16 +59,16 @@ public:
void FreeFramebufferByDepth(DepthStencilVulkanImage* image);
private:
VideoOutVulkanImage* CreateDummyBuffer(VkFormat format, uint32_t width, uint32_t height);
VideoOutVulkanImage* CreateDummyBuffer(vk::Format format, uint32_t width, uint32_t height);
struct Framebuffer {
VulkanFramebuffer* framebuffer = nullptr;
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;
VkImageView depth_view = nullptr;
vk::ImageView depth_view = nullptr;
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 stencil_clear_enable = false;
bool depth_read_only = false;

View File

@ -10,10 +10,10 @@ void GdsBuffer::Init(GraphicContext* ctx) {
if (m_buffer == nullptr) {
m_buffer = std::make_unique<VulkanBuffer>();
m_buffer->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
m_buffer->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
m_buffer->usage = vk::BufferUsageFlagBits::eStorageBuffer;
m_buffer->memory.property = vk::MemoryPropertyFlagBits::eHostVisible |
vk::MemoryPropertyFlagBits::eHostCoherent |
vk::MemoryPropertyFlagBits::eHostCached;
VulkanCreateBuffer(ctx, DW_SIZE * 4, m_buffer.get());
}
}

View File

@ -47,42 +47,43 @@ TextureImageCreateParams MakeImageParams(const ImageInfo& info, bool storage) {
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 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;
return ImageViewOps::FormatSupportsStorage(ctx, format) ||
(compatible_views && compatible != VK_FORMAT_UNDEFINED &&
(compatible_views && compatible != vk::Format::eUndefined &&
ImageViewOps::FormatSupportsStorage(ctx, compatible));
}
VkImageCreateFlags RenderTargetCreateFlags(VkFormat format) {
vk::ImageCreateFlags RenderTargetCreateFlags(vk::Format format) {
const bool compatible_format_view =
IsRgba8SrgbViewFormat(format) ||
BgraToRgbaSampledViewFormat(format) != VK_FORMAT_UNDEFINED ||
format == VK_FORMAT_R8G8B8A8_UINT || format == VK_FORMAT_R16G16B16A16_SFLOAT ||
format == VK_FORMAT_R16G16B16A16_UINT;
BgraToRgbaSampledViewFormat(format) != vk::Format::eUndefined ||
format == vk::Format::eR8G8B8A8Uint || format == vk::Format::eR16G16B16A16Sfloat ||
format == vk::Format::eR16G16B16A16Uint;
return compatible_format_view
? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT
: VkImageCreateFlags {0};
? vk::ImageCreateFlagBits::eMutableFormat | vk::ImageCreateFlagBits::eExtendedUsage
: vk::ImageCreateFlags {0};
}
VkImageUsageFlags RenderTargetUsage(GraphicContext* ctx, VkFormat format,
VkImageCreateFlags flags) {
auto usage = static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) |
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_SRC_BIT) |
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_DST_BIT) |
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_SAMPLED_BIT);
vk::ImageUsageFlags RenderTargetUsage(GraphicContext* ctx, vk::Format format,
vk::ImageCreateFlags flags) {
auto usage = static_cast<vk::ImageUsageFlags>(vk::ImageUsageFlagBits::eColorAttachment) |
static_cast<vk::ImageUsageFlags>(vk::ImageUsageFlagBits::eTransferSrc) |
static_cast<vk::ImageUsageFlags>(vk::ImageUsageFlagBits::eTransferDst) |
static_cast<vk::ImageUsageFlags>(vk::ImageUsageFlagBits::eSampled);
if (RenderTargetSupportsStorage(ctx, format, flags)) {
usage |= VK_IMAGE_USAGE_STORAGE_BIT;
usage |= vk::ImageUsageFlagBits::eStorage;
}
VkImageFormatProperties properties {};
if (ctx->GetImageFormatProperties(format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage,
flags, &properties) != VK_SUCCESS) {
vk::ImageFormatProperties properties {};
if (ctx->GetImageFormatProperties(format, vk::ImageType::e2D, vk::ImageTiling::eOptimal, usage,
flags, &properties) != vk::Result::eSuccess) {
EXIT("TextureCache: render-target format does not support required usage, format=%d "
"usage=0x%x\n",
static_cast<int>(format), usage);
static_cast<int>(format), static_cast<vk::ImageUsageFlags::MaskType>(usage));
}
return usage;
}
@ -139,7 +140,7 @@ uint32_t RenderTargetTransferFormat(uint32_t bytes_per_element) {
}
GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info, bool storage,
VulkanMemory* memory, VkComponentMapping* components) {
VulkanMemory* memory, vk::ComponentMapping* components) {
if (components == nullptr) {
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,
bool storage, VkComponentMapping components) {
bool storage, vk::ComponentMapping components) {
if (storage) {
TextureCreateImageViews(ctx, image, components, info.type, 0, 0, 1, info.depth, false,
TextureFormatUsage::Sampled | TextureFormatUsage::Storage);
@ -195,11 +196,11 @@ void UploadRenderTargetLayers(GraphicContext* ctx, RenderTextureVulkanImage* ima
region.dst_layer += base_layer;
}
const auto source_address = info.address + slice_size * base_layer;
TextureUploadGuestImage(
ctx, image, reinterpret_cast<const void*>(source_address), upload_size, regions, layout,
format, info.width, info.height, layer_count, info.levels,
TextureUploadSliceLayout::MipChainPerSlice, "TextureCache render target",
static_cast<uint64_t>(VK_IMAGE_LAYOUT_GENERAL));
TextureUploadGuestImage(ctx, image, reinterpret_cast<const void*>(source_address),
upload_size, regions, layout, format, info.width, info.height,
layer_count, info.levels,
TextureUploadSliceLayout::MipChainPerSlice,
"TextureCache render target", vk::ImageLayout::eGeneral);
return;
}
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,
info.pitch, info.bytes_per_element, slice_size);
UtilFillImage(ctx, image, scratch.Data(), slice_size, info.pitch,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_GENERAL));
vk::ImageLayout::eGeneral);
} else {
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->mip_levels = info.levels;
image->layers = info.layers;
image->layout = VK_IMAGE_LAYOUT_UNDEFINED;
image->layout = vk::ImageLayout::eUndefined;
UtilResetImageViews(image);
VkImageCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
vk::ImageCreateInfo create {};
create.sType = vk::StructureType::eImageCreateInfo;
create.flags = RenderTargetCreateFlags(info.format);
create.imageType = VK_IMAGE_TYPE_2D;
create.imageType = vk::ImageType::e2D;
create.extent = {info.width, info.height, 1};
create.mipLevels = info.levels;
create.arrayLayers = info.layers;
create.format = info.format;
create.tiling = VK_IMAGE_TILING_OPTIMAL;
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
create.tiling = vk::ImageTiling::eOptimal;
create.initialLayout = vk::ImageLayout::eUndefined;
create.usage = RenderTargetUsage(ctx, info.format, create.flags);
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
create.samples = VK_SAMPLE_COUNT_1_BIT;
memory->property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
create.sharingMode = vk::SharingMode::eExclusive;
create.samples = vk::SampleCountFlagBits::e1;
memory->property = vk::MemoryPropertyFlagBits::eDeviceLocal;
if (!VulkanCreateImage(ctx, &create, image, memory)) {
EXIT("TextureCache: failed to create render target, addr=0x%016" PRIx64
" extent=%ux%u format=%d\n",
@ -257,23 +258,25 @@ RenderTextureVulkanImage* CreateRenderTarget(GraphicContext* ctx, const RenderTa
DepthStencilVulkanImage* CreateDepthTarget(GraphicContext* ctx, const DepthTargetInfo& info,
VulkanMemory* memory) {
VkImageCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
create.imageType = VK_IMAGE_TYPE_2D;
vk::ImageCreateInfo create {};
create.sType = vk::StructureType::eImageCreateInfo;
create.imageType = vk::ImageType::e2D;
create.extent = {info.width, info.height, 1};
create.mipLevels = 1;
create.arrayLayers = info.layers;
create.format = info.format;
create.tiling = VK_IMAGE_TILING_OPTIMAL;
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
create.tiling = vk::ImageTiling::eOptimal;
create.initialLayout = vk::ImageLayout::eUndefined;
create.usage = DepthTargetImageUsage();
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
create.samples = VK_SAMPLE_COUNT_1_BIT;
VkImageFormatProperties properties {};
if (ctx->GetImageFormatProperties(info.format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
create.usage, 0, &properties) != VK_SUCCESS) {
create.sharingMode = vk::SharingMode::eExclusive;
create.samples = vk::SampleCountFlagBits::e1;
vk::ImageFormatProperties properties {};
if (ctx->GetImageFormatProperties(info.format, vk::ImageType::e2D, vk::ImageTiling::eOptimal,
create.usage, vk::ImageCreateFlags {},
&properties) != vk::Result::eSuccess) {
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;
image->extent.width = info.width;
@ -281,10 +284,10 @@ DepthStencilVulkanImage* CreateDepthTarget(GraphicContext* ctx, const DepthTarge
image->guest_pitch = info.pitch;
image->layers = info.layers;
image->format = info.format;
image->layout = VK_IMAGE_LAYOUT_UNDEFINED;
image->layout = vk::ImageLayout::eUndefined;
image->compressed = false;
UtilResetImageViews(image);
memory->property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
memory->property = vk::MemoryPropertyFlagBits::eDeviceLocal;
if (!VulkanCreateImage(ctx, &create, image, memory)) {
EXIT("TextureCache: failed to create depth target, addr=0x%016" PRIx64
" extent=%ux%u format=%d\n",
@ -328,7 +331,7 @@ void ValidateVideoOut(GraphicContext* ctx, const VideoOutInfo& info) {
" pitch=%u\n",
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,
@ -337,22 +340,22 @@ VideoOutVulkanImage* CreateVideoOut(GraphicContext* ctx, const VideoOutInfo& inf
image->extent.width = info.width;
image->extent.height = info.height;
image->format = info.format;
image->layout = VK_IMAGE_LAYOUT_UNDEFINED;
image->layout = vk::ImageLayout::eUndefined;
UtilResetImageViews(image);
VkImageCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
create.imageType = VK_IMAGE_TYPE_2D;
vk::ImageCreateInfo create {};
create.sType = vk::StructureType::eImageCreateInfo;
create.imageType = vk::ImageType::e2D;
create.extent = {info.width, info.height, 1};
create.mipLevels = 1;
create.arrayLayers = 1;
create.format = info.format;
create.tiling = VK_IMAGE_TILING_OPTIMAL;
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
create.tiling = vk::ImageTiling::eOptimal;
create.initialLayout = vk::ImageLayout::eUndefined;
create.flags = RenderTargetCreateFlags(info.format);
create.usage = RenderTargetUsage(ctx, info.format, create.flags);
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
create.samples = VK_SAMPLE_COUNT_1_BIT;
memory->property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
create.sharingMode = vk::SharingMode::eExclusive;
create.samples = vk::SampleCountFlagBits::e1;
memory->property = vk::MemoryPropertyFlagBits::eDeviceLocal;
if (!VulkanCreateImage(ctx, &create, image, memory)) {
EXIT("TextureCache: failed to create video-out image, addr=0x%016" PRIx64
" extent=%ux%u format=%d\n",
@ -373,7 +376,7 @@ void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const Video
if (refresh) {
VulkanDeviceWaitIdle(ctx);
}
image->layout = VK_IMAGE_LAYOUT_UNDEFINED;
image->layout = vk::ImageLayout::eUndefined;
UtilScratchBuffer scratch(info.size);
TileConvertTiledToLinearRenderTarget(
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]);
}
}
UtilFillImage(ctx, image, scratch.Data(), info.size, info.pitch,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_GENERAL));
UtilFillImage(ctx, image, scratch.Data(), info.size, info.pitch, vk::ImageLayout::eGeneral);
}
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)
: new TextureVulkanImage;
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 params = MakeDummyTextureParams(uint_format, image_3d, usage, owner);
auto components = TextureCreateImage(ctx, image, memory, params);
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,
params.levels, params.depth, params.allow_cube_view, params.view_usage);
return image;

View File

@ -102,9 +102,9 @@ namespace ImageOps {
[[nodiscard]] GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info,
bool storage, VulkanMemory* memory,
VkComponentMapping* components);
vk::ComponentMapping* components);
void CreateTextureViews(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info,
bool storage, VkComponentMapping components);
bool storage, vk::ComponentMapping components);
[[nodiscard]] RenderTextureVulkanImage*
CreateRenderTarget(GraphicContext* ctx, const RenderTargetInfo& info, VulkanMemory* memory);

View File

@ -4,12 +4,12 @@
#include "common/assert.h"
#include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/host_gpu/regionDefinitions.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <array>
#include <bit>
#include <cmath>
#include <cstdint>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -31,34 +31,34 @@ struct ImageInfo {
};
struct RenderTargetInfo {
uint64_t address = 0;
uint64_t size = 0;
VkFormat format = VK_FORMAT_UNDEFINED;
uint32_t width = 0;
uint32_t height = 0;
uint32_t pitch = 0;
uint32_t bytes_per_element = 0;
uint32_t tile_mode = 0;
uint32_t levels = 1;
uint32_t layers = 1;
uint64_t address = 0;
uint64_t size = 0;
vk::Format format = vk::Format::eUndefined;
uint32_t width = 0;
uint32_t height = 0;
uint32_t pitch = 0;
uint32_t bytes_per_element = 0;
uint32_t tile_mode = 0;
uint32_t levels = 1;
uint32_t layers = 1;
};
// 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.
struct ColorImageTransferInfo {
uint64_t address = 0;
uint64_t size = 0;
VkFormat format = VK_FORMAT_UNDEFINED;
uint32_t width = 0;
uint32_t height = 0;
uint32_t pitch = 0;
uint32_t bytes_per_element = 0;
uint32_t tile_mode = 0;
uint32_t levels = 1;
uint64_t address = 0;
uint64_t size = 0;
vk::Format format = vk::Format::eUndefined;
uint32_t width = 0;
uint32_t height = 0;
uint32_t pitch = 0;
uint32_t bytes_per_element = 0;
uint32_t tile_mode = 0;
uint32_t levels = 1;
};
[[nodiscard]] inline ColorImageTransferInfo
MakeColorImageTransferInfo(const ImageInfo& info, VkFormat format,
MakeColorImageTransferInfo(const ImageInfo& info, vk::Format format,
uint32_t bytes_per_element) noexcept {
return {info.address, info.size, format, info.width, info.height,
info.pitch, bytes_per_element, info.tile, info.levels};
@ -72,48 +72,48 @@ MakeColorImageTransferInfo(const RenderTargetInfo& info) noexcept {
}
struct DepthTargetInfo {
uint64_t address = 0;
uint64_t size = 0;
uint64_t stencil_address = 0;
uint64_t stencil_size = 0;
uint64_t htile_address = 0;
uint64_t htile_size = 0;
VkFormat format = VK_FORMAT_UNDEFINED;
uint32_t guest_format = 0;
uint32_t width = 0;
uint32_t height = 0;
uint32_t pitch = 0;
uint32_t bytes_per_element = 0;
uint32_t tile_mode = 0;
uint32_t layers = 1;
bool depth_load_clear = false;
bool stencil_load_clear = false;
bool stencil_access = false;
bool stencil_htile_compressed = false;
uint64_t address = 0;
uint64_t size = 0;
uint64_t stencil_address = 0;
uint64_t stencil_size = 0;
uint64_t htile_address = 0;
uint64_t htile_size = 0;
vk::Format format = vk::Format::eUndefined;
uint32_t guest_format = 0;
uint32_t width = 0;
uint32_t height = 0;
uint32_t pitch = 0;
uint32_t bytes_per_element = 0;
uint32_t tile_mode = 0;
uint32_t layers = 1;
bool depth_load_clear = false;
bool stencil_load_clear = false;
bool stencil_access = false;
bool stencil_htile_compressed = false;
};
struct DepthFormatPolicy {
Prospero::DepthFormat depth_format;
Prospero::BufferFormat guest_format;
uint32_t bytes_per_element;
VkFormat sampled_view_format;
VkFormat depth_attachment_format;
std::array<VkFormat, 3> stencil_attachment_formats;
Prospero::DepthFormat depth_format;
Prospero::BufferFormat guest_format;
uint32_t bytes_per_element;
vk::Format sampled_view_format;
vk::Format depth_attachment_format;
std::array<vk::Format, 3> stencil_attachment_formats;
};
inline constexpr std::array<DepthFormatPolicy, 2> DEPTH_FORMAT_POLICIES {{
{Prospero::DepthFormat::kZ16,
Prospero::BufferFormat::k16UNorm,
2,
VK_FORMAT_R16_UNORM,
VK_FORMAT_D16_UNORM,
{VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT}},
vk::Format::eR16Unorm,
vk::Format::eD16Unorm,
{vk::Format::eD16UnormS8Uint, vk::Format::eD24UnormS8Uint, vk::Format::eD32SfloatS8Uint}},
{Prospero::DepthFormat::kZ32F,
Prospero::BufferFormat::k32Float,
4,
VK_FORMAT_R32_SFLOAT,
VK_FORMAT_D32_SFLOAT,
{VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED}},
vk::Format::eR32Sfloat,
vk::Format::eD32Sfloat,
{vk::Format::eD32SfloatS8Uint, vk::Format::eUndefined, vk::Format::eUndefined}},
}};
[[nodiscard]] inline constexpr const DepthFormatPolicy*
@ -137,53 +137,53 @@ FindGuestDepthFormatPolicy(uint32_t guest_format) noexcept {
}
[[nodiscard]] inline constexpr bool IsStencilAttachmentFormat(const DepthFormatPolicy& policy,
VkFormat format) noexcept {
vk::Format format) noexcept {
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 false;
}
[[nodiscard]] inline constexpr VkFormat DepthAttachmentFormat(const DepthFormatPolicy& policy,
bool has_stencil) noexcept {
[[nodiscard]] inline constexpr vk::Format DepthAttachmentFormat(const DepthFormatPolicy& policy,
bool has_stencil) noexcept {
return has_stencil ? policy.stencil_attachment_formats.front() : policy.depth_attachment_format;
}
[[nodiscard]] inline constexpr VkFormat DepthAttachmentFormat(uint32_t depth_format,
uint32_t stencil_format) noexcept {
[[nodiscard]] inline constexpr vk::Format DepthAttachmentFormat(uint32_t depth_format,
uint32_t stencil_format) noexcept {
bool has_stencil = false;
switch (static_cast<Prospero::StencilFormat>(stencil_format)) {
case Prospero::StencilFormat::kInvalid: 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);
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 {
return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
[[nodiscard]] inline constexpr vk::ImageUsageFlags DepthTargetImageUsage() noexcept {
return vk::ImageUsageFlagBits::eDepthStencilAttachment | vk::ImageUsageFlagBits::eSampled |
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) {
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_D16_UNORM_S8_UINT: return VK_FORMAT_D16_UNORM;
case VK_FORMAT_D24_UNORM_S8_UINT: return VK_FORMAT_X8_D24_UNORM_PACK32;
case VK_FORMAT_D32_SFLOAT:
case VK_FORMAT_D32_SFLOAT_S8_UINT: return VK_FORMAT_D32_SFLOAT;
default: return VK_FORMAT_UNDEFINED;
case vk::Format::eD16Unorm:
case vk::Format::eD16UnormS8Uint: return vk::Format::eD16Unorm;
case vk::Format::eD24UnormS8Uint: return vk::Format::eX8D24UnormPack32;
case vk::Format::eD32Sfloat:
case vk::Format::eD32SfloatS8Uint: return vk::Format::eD32Sfloat;
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)) {
case VK_FORMAT_D16_UNORM: return 2;
case VK_FORMAT_X8_D24_UNORM_PACK32:
case VK_FORMAT_D32_SFLOAT: return 4;
case vk::Format::eD16Unorm: return 2;
case vk::Format::eX8D24UnormPack32:
case vk::Format::eD32Sfloat: return 4;
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);
}
[[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(VkFormat image_format,
uint32_t guest_format,
VkFormat view_format) noexcept {
[[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(vk::Format image_format,
uint32_t guest_format,
vk::Format view_format) noexcept {
const auto* policy = FindGuestDepthFormatPolicy(guest_format);
return policy != nullptr && view_format == policy->sampled_view_format &&
(image_format == policy->depth_attachment_format ||
IsStencilAttachmentFormat(*policy, image_format));
}
[[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(VkFormat image_format,
VkFormat view_format) noexcept {
[[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(vk::Format image_format,
vk::Format view_format) noexcept {
for (const auto& policy: DEPTH_FORMAT_POLICIES) {
if (IsSupportedSampledDepthFormat(image_format, Prospero::GpuEnumValue(policy.guest_format),
view_format)) {
@ -231,7 +231,7 @@ struct VideoOutInfo {
uint64_t address = 0;
uint64_t size = 0;
uint64_t metadata_address = 0;
VkFormat format = VK_FORMAT_UNDEFINED;
vk::Format format = vk::Format::eUndefined;
uint32_t guest_format = 0;
uint32_t width = 0;
uint32_t height = 0;
@ -272,10 +272,10 @@ CanUseVideoOutNativeWithoutUpload(VideoOutCompression compression, bool render_t
}
struct VideoOutPixelFormatInfo {
VkFormat format = VK_FORMAT_UNDEFINED;
uint32_t guest_format = 0;
uint32_t bytes_per_element = 0;
bool bgra16 = false;
vk::Format format = vk::Format::eUndefined;
uint32_t guest_format = 0;
uint32_t bytes_per_element = 0;
bool bgra16 = false;
};
struct VideoOutFormatPolicy {
@ -285,22 +285,22 @@ struct VideoOutFormatPolicy {
inline constexpr std::array<VideoOutFormatPolicy, 6> VIDEO_OUT_FORMAT_POLICIES {{
{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}},
{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}},
{0x8100000022000000ull,
{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
{vk::Format::eA2B10G10R10UnormPack32,
Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm), 4, false}},
{0x8100000000000000ull,
{VK_FORMAT_A2R10G10B10_UNORM_PACK32,
{vk::Format::eA2R10G10B10UnormPack32,
Prospero::GpuEnumValue(Prospero::BufferFormat::k10_10_10_2UNorm), 4, false}},
{0xc001000622000000ull,
{VK_FORMAT_R16G16B16A16_SFLOAT,
{vk::Format::eR16G16B16A16Sfloat,
Prospero::GpuEnumValue(Prospero::BufferFormat::k16_16_16_16Float), 8, false}},
{0xc001000600000000ull,
{VK_FORMAT_R16G16B16A16_SFLOAT,
{vk::Format::eR16G16B16A16Sfloat,
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
IsDepthUintTextureReinterpretation(VkFormat image_format, uint32_t guest_format,
VkFormat view_format) noexcept {
IsDepthUintTextureReinterpretation(vk::Format image_format, uint32_t guest_format,
vk::Format view_format) noexcept {
switch (image_format) {
case VK_FORMAT_D32_SFLOAT:
case vk::Format::eD32Sfloat:
return guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) &&
view_format == VK_FORMAT_R32_UINT;
view_format == vk::Format::eR32Uint;
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);
}
[[nodiscard]] inline bool DecodePackedColorClear(VkFormat format, uint32_t packed,
VkClearColorValue* clear) {
[[nodiscard]] inline bool DecodePackedColorClear(vk::Format format, uint32_t packed,
vk::ClearColorValue* clear) {
if (clear == nullptr) {
return false;
}
VkClearColorValue next {};
vk::ClearColorValue next {};
const auto unorm8 = [](uint32_t value) { return static_cast<float>(value & 0xffu) / 255.0f; };
switch (format) {
case VK_FORMAT_R8G8B8A8_SRGB:
case vk::Format::eR8G8B8A8Srgb:
next.float32[0] = DecodeSrgbClearComponent(packed);
next.float32[1] = DecodeSrgbClearComponent(packed >> 8u);
next.float32[2] = DecodeSrgbClearComponent(packed >> 16u);
next.float32[3] = unorm8(packed >> 24u);
break;
case VK_FORMAT_B8G8R8A8_SRGB:
case vk::Format::eB8G8R8A8Srgb:
next.float32[0] = DecodeSrgbClearComponent(packed >> 16u);
next.float32[1] = DecodeSrgbClearComponent(packed >> 8u);
next.float32[2] = DecodeSrgbClearComponent(packed);
next.float32[3] = unorm8(packed >> 24u);
break;
case VK_FORMAT_R8G8B8A8_UNORM:
case vk::Format::eR8G8B8A8Unorm:
next.float32[0] = unorm8(packed);
next.float32[1] = unorm8(packed >> 8u);
next.float32[2] = unorm8(packed >> 16u);
next.float32[3] = unorm8(packed >> 24u);
break;
case VK_FORMAT_B8G8R8A8_UNORM:
case vk::Format::eB8G8R8A8Unorm:
next.float32[0] = unorm8(packed >> 16u);
next.float32[1] = unorm8(packed >> 8u);
next.float32[2] = unorm8(packed);
next.float32[3] = unorm8(packed >> 24u);
break;
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
case vk::Format::eA2B10G10R10UnormPack32:
next.float32[0] = static_cast<float>(packed & 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[3] = static_cast<float>((packed >> 30u) & 0x3u) / 3.0f;
break;
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
case vk::Format::eA2R10G10B10UnormPack32:
next.float32[0] = static_cast<float>((packed >> 20u) & 0x3ffu) / 1023.0f;
next.float32[1] = static_cast<float>((packed >> 10u) & 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;
}
[[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 ||
(format != VK_FORMAT_D32_SFLOAT && format != VK_FORMAT_D32_SFLOAT_S8_UINT)) {
(format != vk::Format::eD32Sfloat && format != vk::Format::eD32SfloatS8Uint)) {
return false;
}
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,
uint64_t address, uint64_t size) {
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 &&
target.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
target.bytes_per_element == 4 &&
@ -621,31 +621,32 @@ SelectDepthTransitionSource(bool depth_load_clear, bool sampled_native_available
: 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,
VkFormat requested) noexcept {
[[nodiscard]] inline bool IsR32UintFloatReinterpretation(vk::Format cached,
vk::Format requested) noexcept {
switch (cached) {
case VK_FORMAT_R32_UINT: return requested == VK_FORMAT_R32_SFLOAT;
case VK_FORMAT_R32_SFLOAT: return requested == VK_FORMAT_R32_UINT;
case vk::Format::eR32Uint: return requested == vk::Format::eR32Sfloat;
case vk::Format::eR32Sfloat: return requested == vk::Format::eR32Uint;
default: return false;
}
}
[[nodiscard]] inline bool IsRgba16UintFloatReinterpretation(VkFormat cached,
VkFormat requested) noexcept {
[[nodiscard]] inline bool IsRgba16UintFloatReinterpretation(vk::Format cached,
vk::Format requested) noexcept {
switch (cached) {
case VK_FORMAT_R16G16B16A16_SFLOAT: return requested == VK_FORMAT_R16G16B16A16_UINT;
case VK_FORMAT_R16G16B16A16_UINT: return requested == VK_FORMAT_R16G16B16A16_SFLOAT;
case vk::Format::eR16G16B16A16Sfloat: return requested == vk::Format::eR16G16B16A16Uint;
case vk::Format::eR16G16B16A16Uint: return requested == vk::Format::eR16G16B16A16Sfloat;
default: return false;
}
}
[[nodiscard]] inline bool IsRgba8UnormUintReinterpretation(VkFormat cached,
VkFormat requested) noexcept {
[[nodiscard]] inline bool IsRgba8UnormUintReinterpretation(vk::Format cached,
vk::Format requested) noexcept {
switch (cached) {
case VK_FORMAT_R8G8B8A8_UNORM: return requested == VK_FORMAT_R8G8B8A8_UINT;
case VK_FORMAT_R8G8B8A8_UINT: return requested == VK_FORMAT_R8G8B8A8_UNORM;
case vk::Format::eR8G8B8A8Unorm: return requested == vk::Format::eR8G8B8A8Uint;
case vk::Format::eR8G8B8A8Uint: return requested == vk::Format::eR8G8B8A8Unorm;
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.height == target.height && sampled.pitch == target.pitch;
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.bytes_per_element == 4 && target.stencil_address == 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
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) {
if (!ImagePageRangesOverlap(requested.address, requested.size, cached.address, cached.size)) {
return StorageSampledOverlap::None;
@ -854,7 +855,7 @@ ClassifyRenderTargetOverlap(const ImageInfo& sampled, bool sampled_gpu_modified,
}
[[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_cpu_dirty, bool same_context,
const RenderTargetInfo& target) {
@ -875,18 +876,18 @@ ClassifyStorageRenderTargetOverlap(const ImageInfo& storage, VkFormat storage_fo
: RenderTargetOverlap::Unsupported;
}
[[nodiscard]] inline bool IsRgba8SrgbViewFormat(VkFormat format) noexcept {
return format == VK_FORMAT_R8G8B8A8_UNORM || format == VK_FORMAT_R8G8B8A8_SRGB ||
format == VK_FORMAT_B8G8R8A8_UNORM || format == VK_FORMAT_B8G8R8A8_SRGB;
[[nodiscard]] inline bool IsRgba8SrgbViewFormat(vk::Format format) noexcept {
return format == vk::Format::eR8G8B8A8Unorm || format == vk::Format::eR8G8B8A8Srgb ||
format == vk::Format::eB8G8R8A8Unorm || format == vk::Format::eB8G8R8A8Srgb;
}
[[nodiscard]] inline bool IsRgba8SrgbReinterpretation(VkFormat cached,
VkFormat requested) noexcept {
[[nodiscard]] inline bool IsRgba8SrgbReinterpretation(vk::Format cached,
vk::Format requested) noexcept {
switch (cached) {
case VK_FORMAT_R8G8B8A8_UNORM: return requested == VK_FORMAT_R8G8B8A8_SRGB;
case VK_FORMAT_R8G8B8A8_SRGB: return requested == VK_FORMAT_R8G8B8A8_UNORM;
case VK_FORMAT_B8G8R8A8_UNORM: return requested == VK_FORMAT_B8G8R8A8_SRGB;
case VK_FORMAT_B8G8R8A8_SRGB: return requested == VK_FORMAT_B8G8R8A8_UNORM;
case vk::Format::eR8G8B8A8Unorm: return requested == vk::Format::eR8G8B8A8Srgb;
case vk::Format::eR8G8B8A8Srgb: return requested == vk::Format::eR8G8B8A8Unorm;
case vk::Format::eB8G8R8A8Unorm: return requested == vk::Format::eB8G8R8A8Srgb;
case vk::Format::eB8G8R8A8Srgb: return requested == vk::Format::eB8G8R8A8Unorm;
default: return false;
}
}

View File

@ -12,13 +12,13 @@ namespace Libs::Graphics {
namespace {
void CreateRenderTargetView(GraphicContext* ctx, VulkanImage* image, int index,
VkComponentSwizzle r, VkComponentSwizzle g, VkComponentSwizzle b,
VkComponentSwizzle a, VkImageViewType type = VK_IMAGE_VIEW_TYPE_2D,
VkFormat view_format = VK_FORMAT_UNDEFINED,
VkImageUsageFlags view_usage = 0, uint32_t level_count = 0) {
const auto layer_count = type == VK_IMAGE_VIEW_TYPE_2D_ARRAY ? image->layers : 1u;
UtilCreateImageView(ctx, image, index, type, VK_IMAGE_ASPECT_COLOR_BIT, {r, g, b, a}, 0, 0,
layer_count, level_count == 0 ? image->mip_levels : level_count,
vk::ComponentSwizzle r, vk::ComponentSwizzle g, vk::ComponentSwizzle b,
vk::ComponentSwizzle a, vk::ImageViewType type = vk::ImageViewType::e2D,
vk::Format view_format = vk::Format::eUndefined,
vk::ImageUsageFlags view_usage = {}, uint32_t level_count = 0) {
const auto layer_count = type == vk::ImageViewType::e2DArray ? image->layers : 1u;
UtilCreateImageView(ctx, image, index, type, vk::ImageAspectFlagBits::eColor, {r, g, b, a}, 0,
0, layer_count, level_count == 0 ? image->mip_levels : level_count,
view_format, view_usage);
}
@ -26,61 +26,67 @@ void CreateRenderTargetView(GraphicContext* ctx, VulkanImage* image, int index,
namespace ImageViewOps {
VkImageAspectFlags DepthAspectMask(VkFormat format) noexcept {
return VK_IMAGE_ASPECT_DEPTH_BIT |
(format == VK_FORMAT_D16_UNORM_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT ||
format == VK_FORMAT_D32_SFLOAT_S8_UINT
? VK_IMAGE_ASPECT_STENCIL_BIT
: 0u);
vk::ImageAspectFlags DepthAspectMask(vk::Format format) noexcept {
auto aspects = vk::ImageAspectFlags {vk::ImageAspectFlagBits::eDepth};
if (format == vk::Format::eD16UnormS8Uint || format == vk::Format::eD24UnormS8Uint ||
format == vk::Format::eD32SfloatS8Uint) {
aspects |= vk::ImageAspectFlagBits::eStencil;
}
return aspects;
}
bool FormatSupportsStorage(GraphicContext* ctx, VkFormat format) {
bool FormatSupportsStorage(GraphicContext* ctx, vk::Format 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) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY);
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT, vk::ComponentSwizzle::eIdentity,
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
vk::ComponentSwizzle::eIdentity);
if (image->layers > 1) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT_ARRAY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_IMAGE_VIEW_TYPE_2D_ARRAY);
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
vk::ImageViewType::e2DArray);
}
if (FormatSupportsStorage(ctx, image->format)) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_IMAGE_VIEW_TYPE_2D,
VK_FORMAT_UNDEFINED, 0, 1);
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE,
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
vk::ImageViewType::e2D, vk::Format::eUndefined,
vk::ImageUsageFlags {}, 1);
if (image->layers > 1) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE_ARRAY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_UNDEFINED, 0, 1);
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
vk::ImageViewType::e2DArray, vk::Format::eUndefined,
vk::ImageUsageFlags {}, 1);
}
}
}
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),
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
{vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity},
0, 0, 1, 1);
}
void CreateVideoOutViews(GraphicContext* ctx, VideoOutVulkanImage* image) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY);
if ((image->format == VK_FORMAT_R8G8B8A8_SRGB || image->format == VK_FORMAT_B8G8R8A8_SRGB) &&
FormatSupportsStorage(ctx, VK_FORMAT_R8G8B8A8_UINT)) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_IMAGE_VIEW_TYPE_2D,
VK_FORMAT_R8G8B8A8_UINT, VK_IMAGE_USAGE_STORAGE_BIT, 1);
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_DEFAULT, vk::ComponentSwizzle::eIdentity,
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
vk::ComponentSwizzle::eIdentity);
if ((image->format == vk::Format::eR8G8B8A8Srgb ||
image->format == vk::Format::eB8G8R8A8Srgb) &&
FormatSupportsStorage(ctx, vk::Format::eR8G8B8A8Uint)) {
CreateRenderTargetView(ctx, image, VulkanImage::VIEW_STORAGE,
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity,
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) {
if (cached.view != nullptr) {
vkDestroyImageView(ctx->device, cached.view, nullptr);
ctx->device.destroyImageView(cached.view, nullptr);
cached.view = nullptr;
}
}
image->view_cache.views.clear();
for (auto& view: image->image_view) {
if (view != nullptr) {
vkDestroyImageView(ctx->device, view, nullptr);
ctx->device.destroyImageView(view, nullptr);
view = nullptr;
}
}
@ -105,12 +111,13 @@ void DestroyViews(GraphicContext* ctx, VulkanImage* image) {
} // namespace ImageViewOps
VkImageView TextureCache::GetRenderTargetAttachmentView(GraphicContext* ctx,
RenderTextureVulkanImage* image,
VkFormat format, uint32_t level,
uint32_t base_layer, uint32_t layer_count) {
vk::ImageView TextureCache::GetRenderTargetAttachmentView(GraphicContext* ctx,
RenderTextureVulkanImage* image,
vk::Format format, uint32_t level,
uint32_t base_layer,
uint32_t layer_count) {
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 > image->layers - base_layer) {
EXIT("TextureCache: invalid render-target attachment view, image=%p format=%d"
@ -127,14 +134,15 @@ VkImageView TextureCache::GetRenderTargetAttachmentView(GraphicContext*
return GetImageView(ctx, image,
{format,
layer_count == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY,
VK_IMAGE_ASPECT_COLOR_BIT, level, 1, base_layer, layer_count,
DstSel(4, 5, 6, 7), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT});
layer_count == 1 ? vk::ImageViewType::e2D : vk::ImageViewType::e2DArray,
vk::ImageAspectFlagBits::eColor, level, 1, base_layer, layer_count,
DstSel(4, 5, 6, 7), vk::ImageUsageFlagBits::eColorAttachment});
}
VkImageView TextureCache::GetDepthTargetAttachmentView(GraphicContext* ctx,
DepthStencilVulkanImage* image,
uint32_t base_layer, uint32_t layer_count) {
vk::ImageView TextureCache::GetDepthTargetAttachmentView(GraphicContext* ctx,
DepthStencilVulkanImage* image,
uint32_t base_layer,
uint32_t layer_count) {
if (ctx == nullptr || image == nullptr || image->image == nullptr || layer_count == 0 ||
base_layer >= image->layers || layer_count > image->layers - base_layer) {
EXIT("TextureCache: invalid depth-target attachment view, image=%p base_layer=%u "
@ -144,26 +152,26 @@ VkImageView TextureCache::GetDepthTargetAttachmentView(GraphicContext*
}
return GetImageView(
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,
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,
const ImageViewInfo& info) {
const bool supported_type = info.type == VK_IMAGE_VIEW_TYPE_2D ||
info.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
info.type == VK_IMAGE_VIEW_TYPE_3D;
const bool supported_usage = info.usage == VK_IMAGE_USAGE_SAMPLED_BIT ||
info.usage == VK_IMAGE_USAGE_STORAGE_BIT ||
info.usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ||
info.usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
vk::ImageView TextureCache::GetImageView(GraphicContext* ctx, VulkanImage* image,
const ImageViewInfo& info) {
const bool supported_type = info.type == vk::ImageViewType::e2D ||
info.type == vk::ImageViewType::e2DArray ||
info.type == vk::ImageViewType::e3D;
const bool supported_usage = info.usage == vk::ImageUsageFlagBits::eSampled ||
info.usage == vk::ImageUsageFlagBits::eStorage ||
info.usage == vk::ImageUsageFlagBits::eColorAttachment ||
info.usage == vk::ImageUsageFlagBits::eDepthStencilAttachment;
const bool valid_shape =
(info.type == VK_IMAGE_VIEW_TYPE_2D && info.layer_count == 1) ||
info.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
(info.type == VK_IMAGE_VIEW_TYPE_3D && info.base_layer == 0 && info.layer_count == 1);
(info.type == vk::ImageViewType::e2D && info.layer_count == 1) ||
info.type == vk::ImageViewType::e2DArray ||
(info.type == vk::ImageViewType::e3D && info.base_layer == 0 && info.layer_count == 1);
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.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 ||
@ -171,10 +179,11 @@ VkImageView TextureCache::GetImageView(GraphicContext* ctx, VulkanImage* image,
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"
" image_levels=%u image_layers=%u\n",
static_cast<const void*>(image), static_cast<int>(info.format), info.aspect,
info.swizzle, info.base_level, info.level_count, info.base_layer, info.layer_count,
static_cast<int>(info.type), info.usage, image != nullptr ? image->mip_levels : 0,
image != nullptr ? image->layers : 0);
static_cast<const void*>(image), 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,
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;
@ -185,67 +194,69 @@ VkImageView TextureCache::GetImageView(GraphicContext* ctx, VulkanImage* image,
}
}
VkImageViewUsageCreateInfo usage {};
usage.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;
vk::ImageViewUsageCreateInfo usage {};
usage.sType = vk::StructureType::eImageViewUsageCreateInfo;
usage.usage = info.usage;
VkImageViewCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
vk::ImageViewCreateInfo create {};
create.sType = vk::StructureType::eImageViewCreateInfo;
create.pNext = &usage;
create.image = image->image;
create.viewType = info.type;
create.format = info.format;
create.components = info.usage == VK_IMAGE_USAGE_SAMPLED_BIT
create.components = info.usage == vk::ImageUsageFlagBits::eSampled
? TextureGetComponentMapping(info.swizzle)
: VkComponentMapping {};
: vk::ComponentMapping {};
create.subresourceRange.aspectMask = info.aspect;
create.subresourceRange.baseMipLevel = info.base_level;
create.subresourceRange.levelCount = info.level_count;
create.subresourceRange.baseArrayLayer = info.base_layer;
create.subresourceRange.layerCount = info.layer_count;
VkImageView view = nullptr;
const auto result = vkCreateImageView(ctx->device, &create, nullptr, &view);
if (result != VK_SUCCESS || view == nullptr) {
vk::ImageView view = nullptr;
const auto result = ctx->device.createImageView(&create, nullptr, &view);
if (result != vk::Result::eSuccess || view == nullptr) {
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",
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,
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});
return view;
}
VkImageView TextureCache::GetDepthTargetSampledView(GraphicContext* ctx,
DepthStencilVulkanImage* image,
VkFormat view_format, uint32_t swizzle,
uint32_t base_level, uint32_t level_count,
VkImageViewType type, uint32_t base_layer,
uint32_t layer_count) {
vk::ImageView TextureCache::GetDepthTargetSampledView(GraphicContext* ctx,
DepthStencilVulkanImage* image,
vk::Format view_format, uint32_t swizzle,
uint32_t base_level, uint32_t level_count,
vk::ImageViewType type, uint32_t base_layer,
uint32_t layer_count) {
if (ctx == nullptr || image == nullptr || image->image == nullptr ||
view_format == VK_FORMAT_UNDEFINED ||
view_format == vk::Format::eUndefined ||
!IsSupportedSampledDepthView(image->format, view_format, swizzle)) {
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"
" image_levels=%u image_layers=%u\n",
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,
layer_count, static_cast<int>(type), image != nullptr ? image->mip_levels : 0,
image != nullptr ? image->layers : 0);
}
return GetImageView(ctx, image,
{image->format, type, VK_IMAGE_ASPECT_DEPTH_BIT, base_level, level_count,
base_layer, layer_count, swizzle});
{image->format, type, vk::ImageAspectFlagBits::eDepth, base_level,
level_count, base_layer, layer_count, swizzle});
}
VkImageView TextureCache::GetSampledColorView(GraphicContext* ctx, VulkanImage* image,
VkFormat view_format, uint32_t swizzle,
uint32_t base_level, uint32_t level_count,
VkImageViewType type, uint32_t base_layer,
uint32_t layer_count) {
vk::ImageView TextureCache::GetSampledColorView(GraphicContext* ctx, VulkanImage* image,
vk::Format view_format, uint32_t swizzle,
uint32_t base_level, uint32_t level_count,
vk::ImageViewType type, uint32_t base_layer,
uint32_t layer_count) {
if (ctx == nullptr || image == nullptr || image->image == nullptr ||
view_format == VK_FORMAT_UNDEFINED || base_level >= 16 ||
(type != VK_IMAGE_VIEW_TYPE_2D && type != VK_IMAGE_VIEW_TYPE_2D_ARRAY) ||
view_format == vk::Format::eUndefined || base_level >= 16 ||
(type != vk::ImageViewType::e2D && type != vk::ImageViewType::e2DArray) ||
!IsSupportedSampledColorView(image->format, view_format, swizzle)) {
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",
@ -253,29 +264,29 @@ VkImageView TextureCache::GetSampledColorView(GraphicContext* ctx, VulkanImage*
level_count, base_layer, layer_count, static_cast<int>(type),
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;
const bool full_view =
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 &&
image->image_view[precreated_view] != nullptr) {
return image->image_view[precreated_view];
}
return GetImageView(ctx, image,
{view_format, type, VK_IMAGE_ASPECT_COLOR_BIT, base_level, level_count,
base_layer, layer_count, swizzle});
{view_format, type, vk::ImageAspectFlagBits::eColor, base_level,
level_count, base_layer, layer_count, swizzle});
}
VkImageView TextureCache::GetRenderTargetStorageView(GraphicContext* ctx,
RenderTextureVulkanImage* image,
VkFormat view_format, uint32_t base_level,
uint32_t level_count, VkImageViewType type,
uint32_t base_layer, uint32_t layer_count) {
vk::ImageView TextureCache::GetRenderTargetStorageView(GraphicContext* ctx,
RenderTextureVulkanImage* image,
vk::Format view_format, uint32_t base_level,
uint32_t level_count, vk::ImageViewType type,
uint32_t base_layer, uint32_t layer_count) {
if (ctx == nullptr || image == nullptr || image->image == nullptr ||
view_format == VK_FORMAT_UNDEFINED ||
(type != VK_IMAGE_VIEW_TYPE_2D && type != VK_IMAGE_VIEW_TYPE_2D_ARRAY)) {
view_format == vk::Format::eUndefined ||
(type != vk::ImageViewType::e2D && type != vk::ImageViewType::e2DArray)) {
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",
static_cast<const void*>(image), static_cast<int>(view_format), base_level,
@ -291,11 +302,11 @@ VkImageView TextureCache::GetRenderTargetStorageView(GraphicContext* c
level_count);
}
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;
const bool full_view =
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) {
return image->image_view[index];
}
@ -308,13 +319,14 @@ VkImageView TextureCache::GetRenderTargetStorageView(GraphicContext* c
level_count);
}
return GetImageView(ctx, image,
{view_format, type, VK_IMAGE_ASPECT_COLOR_BIT, base_level, level_count,
base_layer, layer_count, DstSel(4, 5, 6, 7), VK_IMAGE_USAGE_STORAGE_BIT});
{view_format, type, vk::ImageAspectFlagBits::eColor, base_level,
level_count, base_layer, layer_count, DstSel(4, 5, 6, 7),
vk::ImageUsageFlagBits::eStorage});
}
VkImageView TextureCache::GetStorageTextureSampledView(GraphicContext* ctx,
StorageTextureVulkanImage* image,
const ImageInfo& info) {
vk::ImageView TextureCache::GetStorageTextureSampledView(GraphicContext* ctx,
StorageTextureVulkanImage* image,
const ImageInfo& info) {
const auto shape =
SelectStorageSampledViewShape(info.type, info.depth, image != nullptr ? image->layers : 0);
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);
}
VkImageViewType type = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
vk::ImageViewType type = static_cast<vk::ImageViewType>(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
switch (shape) {
case StorageSampledViewShape::Image2D: type = VK_IMAGE_VIEW_TYPE_2D; break;
case StorageSampledViewShape::Image2DArray: type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; break;
case StorageSampledViewShape::Image3D: type = VK_IMAGE_VIEW_TYPE_3D; break;
case StorageSampledViewShape::Image2D: type = vk::ImageViewType::e2D; break;
case StorageSampledViewShape::Image2DArray: type = vk::ImageViewType::e2DArray; break;
case StorageSampledViewShape::Image3D: type = vk::ImageViewType::e3D; break;
case StorageSampledViewShape::Unsupported:
EXIT("TextureCache: unsupported sampled storage-image view shape\n");
}
const auto layer_count = shape == StorageSampledViewShape::Image2DArray ? info.depth : 1u;
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});
}
VkImageView TextureCache::GetStorageTextureStorageView(GraphicContext* ctx,
StorageTextureVulkanImage* image,
uint32_t base_level) {
vk::ImageView TextureCache::GetStorageTextureStorageView(GraphicContext* ctx,
StorageTextureVulkanImage* image,
uint32_t base_level) {
if (ctx == nullptr || image == nullptr || image->image == nullptr ||
base_level >= (image != nullptr ? image->mip_levels : 0)) {
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 GetImageView(ctx, image,
{image->format, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT,
base_level, 1, 0, 1, DstSel(4, 5, 6, 7), VK_IMAGE_USAGE_STORAGE_BIT});
{image->format, vk::ImageViewType::e2D, vk::ImageAspectFlagBits::eColor,
base_level, 1, 0, 1, DstSel(4, 5, 6, 7),
vk::ImageUsageFlagBits::eStorage});
}
} // namespace Libs::Graphics

View File

@ -40,47 +40,48 @@ namespace Libs::Graphics {
height != 0 && depth == 1);
}
[[noreturn]] inline void UnsupportedColorView(const char* usage, VkFormat image_format,
VkFormat view_format, uint32_t swizzle) noexcept {
[[noreturn]] inline void UnsupportedColorView(const char* usage, vk::Format image_format,
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,
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) {
case VK_FORMAT_B8G8R8A8_UNORM: return VK_FORMAT_R8G8B8A8_UNORM;
case VK_FORMAT_B8G8R8A8_SRGB: return VK_FORMAT_R8G8B8A8_SRGB;
case VK_FORMAT_A2R10G10B10_UNORM_PACK32: return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
default: return VK_FORMAT_UNDEFINED;
case vk::Format::eB8G8R8A8Unorm: return vk::Format::eR8G8B8A8Unorm;
case vk::Format::eB8G8R8A8Srgb: return vk::Format::eR8G8B8A8Srgb;
case vk::Format::eA2R10G10B10UnormPack32: return vk::Format::eA2B10G10R10UnormPack32;
default: return vk::Format::eUndefined;
}
}
[[nodiscard]] inline bool IsBgraToRgbaSampledView(VkFormat image_format,
VkFormat view_format) noexcept {
[[nodiscard]] inline bool IsBgraToRgbaSampledView(vk::Format image_format,
vk::Format view_format) noexcept {
switch (image_format) {
case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_B8G8R8A8_SRGB:
case vk::Format::eB8G8R8A8Unorm:
case vk::Format::eB8G8R8A8Srgb:
switch (view_format) {
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_R8G8B8A8_SRGB: return true;
case vk::Format::eR8G8B8A8Unorm:
case vk::Format::eR8G8B8A8Srgb: return true;
default: return false;
}
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
return view_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32;
case vk::Format::eA2R10G10B10UnormPack32:
return view_format == vk::Format::eA2B10G10R10UnormPack32;
default: return false;
}
}
[[nodiscard]] inline VkFormat BgraSrgbStorageViewFormat(VkFormat image_format) noexcept {
return image_format == VK_FORMAT_B8G8R8A8_SRGB ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED;
[[nodiscard]] inline vk::Format BgraSrgbStorageViewFormat(vk::Format image_format) noexcept {
return image_format == vk::Format::eB8G8R8A8Srgb ? vk::Format::eR8G8B8A8Unorm
: vk::Format::eUndefined;
}
[[nodiscard]] inline VkFormat SrgbStorageViewFormat(VkFormat image_format) noexcept {
return image_format == VK_FORMAT_R8G8B8A8_SRGB ? VK_FORMAT_R8G8B8A8_UNORM
: BgraSrgbStorageViewFormat(image_format);
[[nodiscard]] inline vk::Format SrgbStorageViewFormat(vk::Format image_format) noexcept {
return image_format == vk::Format::eR8G8B8A8Srgb ? vk::Format::eR8G8B8A8Unorm
: 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 {
return view_format == BgraSrgbStorageViewFormat(image_format) && swizzle == DstSel(6, 5, 4, 7);
}
@ -103,8 +104,9 @@ namespace Libs::Graphics {
return true;
}
[[nodiscard]] inline bool IsSupportedSampledColorView(VkFormat image_format, VkFormat view_format,
uint32_t swizzle) noexcept {
[[nodiscard]] inline bool IsSupportedSampledColorView(vk::Format image_format,
vk::Format view_format,
uint32_t swizzle) noexcept {
if (!IsValidSampledColorSwizzle(swizzle)) {
return false;
}
@ -119,16 +121,17 @@ namespace Libs::Graphics {
return IsBgraToRgbaSampledView(image_format, view_format) && swizzle == DstSel(6, 5, 4, 7);
}
[[nodiscard]] inline uint32_t SelectSampledColorView(VkFormat image_format, VkFormat view_format,
uint32_t swizzle) noexcept {
[[nodiscard]] inline uint32_t
SelectSampledColorView(vk::Format image_format, vk::Format view_format, uint32_t swizzle) noexcept {
if (IsSupportedSampledColorView(image_format, view_format, swizzle)) {
return swizzle;
}
UnsupportedColorView("sampled", image_format, view_format, swizzle);
}
[[nodiscard]] inline bool IsSupportedSampledDepthView(VkFormat image_format, VkFormat view_format,
uint32_t swizzle) noexcept {
[[nodiscard]] inline bool IsSupportedSampledDepthView(vk::Format image_format,
vk::Format view_format,
uint32_t swizzle) noexcept {
if (!IsSupportedSampledDepthFormat(image_format, view_format)) {
return false;
}
@ -140,8 +143,8 @@ namespace Libs::Graphics {
}
}
[[nodiscard]] inline uint32_t SelectSampledDepthView(VkFormat image_format, VkFormat view_format,
uint32_t swizzle) noexcept {
[[nodiscard]] inline uint32_t
SelectSampledDepthView(vk::Format image_format, vk::Format view_format, uint32_t swizzle) noexcept {
if (IsSupportedSampledDepthView(image_format, view_format, swizzle)) {
return swizzle;
}
@ -166,20 +169,20 @@ IsSupportedSampledDepthUintResource(const ShaderRecompiler::IR::ImageResource& r
!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 {
const bool single_channel =
view_format == VK_FORMAT_R8_UNORM || view_format == VK_FORMAT_R8_UINT ||
view_format == VK_FORMAT_R16_UINT || view_format == VK_FORMAT_R32_UINT ||
view_format == VK_FORMAT_R16_SFLOAT || view_format == VK_FORMAT_R32_SFLOAT;
view_format == vk::Format::eR8Unorm || view_format == vk::Format::eR8Uint ||
view_format == vk::Format::eR16Uint || view_format == vk::Format::eR32Uint ||
view_format == vk::Format::eR16Sfloat || view_format == vk::Format::eR32Sfloat;
const bool swizzle_ok =
swizzle == DstSel(4, 5, 6, 7) ||
(single_channel && (swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1) ||
swizzle == DstSel(4, 4, 4, 4))) ||
(view_format == VK_FORMAT_R32G32_UINT && swizzle == DstSel(4, 5, 0, 1)) ||
((view_format == VK_FORMAT_R8G8B8A8_UNORM || view_format == VK_FORMAT_R8G8B8A8_UINT) &&
(view_format == vk::Format::eR32G32Uint && swizzle == DstSel(4, 5, 0, 1)) ||
((view_format == vk::Format::eR8G8B8A8Unorm || view_format == vk::Format::eR8G8B8A8Uint) &&
(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 &&
!IsBgraSrgbStorageView(image_format, view_format, swizzle)) ||
!swizzle_ok) {
@ -212,8 +215,8 @@ ValidateStorageImageResource(const ShaderRecompiler::IR::ImageResource& resource
namespace ImageViewOps {
[[nodiscard]] VkImageAspectFlags DepthAspectMask(VkFormat format) noexcept;
[[nodiscard]] bool FormatSupportsStorage(GraphicContext* ctx, VkFormat format);
[[nodiscard]] vk::ImageAspectFlags DepthAspectMask(vk::Format format) noexcept;
[[nodiscard]] bool FormatSupportsStorage(GraphicContext* ctx, vk::Format format);
void CreateRenderTargetViews(GraphicContext* ctx, RenderTextureVulkanImage* image);
void CreateDepthViews(GraphicContext* ctx, DepthStencilVulkanImage* image);

View File

@ -57,8 +57,8 @@ void PipelineCache::DeletePipelineInternal(Pipeline* p) {
EXIT_IF(gctx == nullptr);
VulkanDeviceWaitIdle(gctx);
vkDestroyPipeline(gctx->device, p->pipeline, nullptr);
vkDestroyPipelineLayout(gctx->device, p->pipeline_layout, nullptr);
gctx->device.destroyPipeline(p->pipeline, nullptr);
gctx->device.destroyPipelineLayout(p->pipeline_layout, nullptr);
p->pipeline = nullptr;
p->pipeline_layout = nullptr;
@ -67,7 +67,7 @@ void PipelineCache::DeletePipelineInternal(Pipeline* p) {
PipelineCache::GraphicsPipeline* PipelineCache::CreateGraphicsPipeline(
VulkanFramebuffer* framebuffer, RenderColorInfo* colors, uint32_t color_count,
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) {
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.topology = topology;
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_write_enable = (depth->depth_write_enable && !depth->depth_clear_enable);
static_params.depth_compare_op = depth->depth_compare_op;

View File

@ -7,6 +7,7 @@
#include "common/file.h"
#include "common/threads.h"
#include "graphics/host_gpu/renderer/renderTarget.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/shader.h"
#include <cstddef>
@ -15,7 +16,6 @@
#include <type_traits>
#include <unordered_map>
#include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -36,11 +36,11 @@ struct PipelineStaticParameters {
float viewport_offset[3] = {};
bool negative_one_to_one = false;
int scissor_ltrb[4] = {0};
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
vk::PrimitiveTopology topology = vk::PrimitiveTopology::ePointList;
bool with_depth = false;
bool depth_test_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;
float depth_min_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(sizeof(PipelineStaticParameters) ==
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(PipelineStencilStaticState) * 2 + sizeof(uint32_t) +
sizeof(uint32_t[RENDER_COLOR_ATTACHMENTS_MAX]) + sizeof(bool) * 3 +
@ -90,8 +90,8 @@ public:
KYTY_CLASS_NO_COPY(PipelineCache);
struct Pipeline {
VkPipelineLayout pipeline_layout = nullptr;
VkPipeline pipeline = nullptr;
vk::PipelineLayout pipeline_layout = nullptr;
vk::Pipeline pipeline = nullptr;
};
struct GraphicsPipeline: Pipeline {
@ -107,7 +107,7 @@ public:
GraphicsPipeline* CreateGraphicsPipeline(
VulkanFramebuffer* framebuffer, RenderColorInfo* colors, uint32_t color_count,
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);
ComputePipeline* CreateComputePipeline(ShaderComputeInputInfo* input_info,
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,
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,
std::span<const uint32_t> vs_shader,
const ShaderPixelInputInfo* ps_input_info,

View File

@ -4,10 +4,10 @@
#include "common/abi.h"
#include "common/common.h"
#include "graphics/host_gpu/renderer/streamBuffer.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <memory>
#include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -80,9 +80,9 @@ public:
void Begin() const;
void End() const;
void Execute();
void ExecuteWithSemaphore(VkSemaphore signal_semaphore = nullptr);
void ExecuteWithSemaphore(VkSemaphore wait_semaphore, VkPipelineStageFlags wait_stage,
VkSemaphore signal_semaphore);
void ExecuteWithSemaphore(vk::Semaphore signal_semaphore = nullptr);
void ExecuteWithSemaphore(vk::Semaphore wait_semaphore, vk::PipelineStageFlags wait_stage,
vk::Semaphore signal_semaphore);
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);
void BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorInfo* colors,

View File

@ -23,6 +23,7 @@
#include "graphics/host_gpu/renderer/shaderResourceBarrier.h"
#include "graphics/host_gpu/renderer/shaderSubgroup.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/recompiler/ResourceMaterialization.h"
#include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/shader.h"
@ -38,9 +39,6 @@
#include <span>
#include <unordered_map>
#include <vector>
#include <vulkan/vk_enum_string_helper.h>
// IWYU pragma: no_forward_declare VkImageView_T
namespace Libs::Graphics {
static uint64_t BufferDescriptorSize(const ShaderBufferResource& descriptor) {
@ -530,20 +528,20 @@ void RenderDispatchDirect(uint64_t submit_id, CommandBuffer* buffer, HW::Context
for (;;) {
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(
&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(
submit_id, buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->pipeline_layout,
input_info.stage, VK_SHADER_STAGE_COMPUTE_BIT, DescriptorCache::Stage::Compute);
submit_id, buffer, vk::PipelineBindPoint::eCompute, pipeline->pipeline_layout,
input_info.stage, vk::ShaderStageFlagBits::eCompute, DescriptorCache::Stage::Compute);
if (buffer->GetRecordingGeneration() != recording_generation) {
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);
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;
if (has_storage_writes) {
ShaderWriteBarrier(vk_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
ShaderWriteBarrier(vk_buffer, vk::PipelineStageFlagBits::eComputeShader);
}
break;
}

View File

@ -27,6 +27,7 @@
#include "graphics/host_gpu/renderer/shaderResourceBarrier.h"
#include "graphics/host_gpu/renderer/shaderSubgroup.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/recompiler/ResourceMaterialization.h"
#include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/shader.h"
@ -43,9 +44,6 @@
#include <span>
#include <unordered_map>
#include <vector>
#include <vulkan/vk_enum_string_helper.h>
// IWYU pragma: no_forward_declare VkImageView_T
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
" prim=%u index_count=%u flags=0x%08" PRIx32 "\n",
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,
ctx != nullptr ? ctx->GetRenderTargetMask() : 0, ucfg != nullptr ? ucfg->GetPrimType() : 0,
index_count, flags);
@ -184,8 +182,8 @@ static void LogDrawTargetState(const char* draw_name, const RenderColorInfo& col
image.kind == ShaderRecompiler::IR::ResourceKind::ImageUint;
});
VkExtent2D extent = color.vulkan_buffer != nullptr ? color.extent : VkExtent2D {};
auto sc = calc_final_scissor(vp, ctx->GetScanModeControl(), extent);
vk::Extent2D extent = color.vulkan_buffer != nullptr ? color.extent : vk::Extent2D {};
auto sc = calc_final_scissor(vp, ctx->GetScanModeControl(), extent);
LOGF(
"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,
uint32_t attachment_count,
const VkBool32* p_color_write_enables) {
static void VulkanCmdSetColorWriteEnableEXT(GraphicContext* ctx, vk::CommandBuffer command_buffer,
uint32_t attachment_count,
const vk::Bool32* p_color_write_enables) {
EXIT_IF(ctx == nullptr);
EXIT_IF(ctx->instance == nullptr);
EXIT_IF(ctx->device == nullptr);
static auto func = reinterpret_cast<PFN_vkCmdSetColorWriteEnableEXT>(
vkGetInstanceProcAddr(ctx->instance, "vkCmdSetColorWriteEnableEXT"));
if (func != nullptr) {
func(command_buffer, attachment_count, p_color_write_enables);
} else {
if (VULKAN_HPP_DEFAULT_DISPATCHER.vkCmdSetColorWriteEnableEXT == nullptr) {
EXIT("vkCmdSetColorWriteEnableEXT not present\n");
}
command_buffer.setColorWriteEnableEXT(attachment_count, p_color_write_enables);
}
static PipelineDynamicParameters BuildGraphicsDynamicParams(const HW::Context& ctx,
@ -376,8 +370,8 @@ static PipelineDynamicParameters BuildGraphicsDynamicParams(const HW::Context&
ret.color_write_count = color_count;
ret.stencil_test_enable = depth.stencil_test_enable;
const auto& vp = ctx.GetScreenViewport();
VkExtent2D framebuffer_extent {};
const auto& vp = ctx.GetScreenViewport();
vk::Extent2D framebuffer_extent {};
if (color_count > 0 && colors[0].vulkan_buffer != nullptr) {
framebuffer_extent = colors[0].extent;
} else if (depth.vulkan_buffer != nullptr) {
@ -411,25 +405,25 @@ static PipelineDynamicParameters BuildGraphicsDynamicParams(const HW::Context&
return ret;
}
static void SetDynamicParams(VkCommandBuffer vk_buffer,
static void SetDynamicParams(vk::CommandBuffer vk_buffer,
const PipelineDynamicParameters& dynamic_params) {
KYTY_PROFILER_FUNCTION();
VkViewport viewport {};
vk::Viewport viewport {};
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.width = dynamic_params.viewport_scale[0] * 2.0f;
viewport.height = dynamic_params.viewport_scale[1] * 2.0f;
viewport.minDepth = 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.extent = {
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])};
vkCmdSetScissor(vk_buffer, 0, 1, &scissor);
vk_buffer.setScissor(0, 1, &scissor);
float line_width = dynamic_params.line_width;
if (line_width != 1.0f) {
@ -442,24 +436,24 @@ static void SetDynamicParams(VkCommandBuffer vk_buffer,
}
line_width = 1.0f;
}
vkCmdSetLineWidth(vk_buffer, line_width);
vk_buffer.setLineWidth(line_width);
if (dynamic_params.stencil_test_enable) {
vkCmdSetStencilCompareMask(vk_buffer, VK_STENCIL_FACE_FRONT_BIT,
dynamic_params.stencil_front.compareMask);
vkCmdSetStencilCompareMask(vk_buffer, VK_STENCIL_FACE_BACK_BIT,
dynamic_params.stencil_back.compareMask);
vkCmdSetStencilWriteMask(vk_buffer, VK_STENCIL_FACE_FRONT_BIT,
dynamic_params.stencil_front.writeMask);
vkCmdSetStencilWriteMask(vk_buffer, VK_STENCIL_FACE_BACK_BIT,
dynamic_params.stencil_back.writeMask);
vkCmdSetStencilReference(vk_buffer, VK_STENCIL_FACE_FRONT_BIT,
dynamic_params.stencil_front.reference);
vkCmdSetStencilReference(vk_buffer, VK_STENCIL_FACE_BACK_BIT,
dynamic_params.stencil_back.reference);
vk_buffer.setStencilCompareMask(vk::StencilFaceFlagBits::eFront,
dynamic_params.stencil_front.compareMask);
vk_buffer.setStencilCompareMask(vk::StencilFaceFlagBits::eBack,
dynamic_params.stencil_back.compareMask);
vk_buffer.setStencilWriteMask(vk::StencilFaceFlagBits::eFront,
dynamic_params.stencil_front.writeMask);
vk_buffer.setStencilWriteMask(vk::StencilFaceFlagBits::eBack,
dynamic_params.stencil_back.writeMask);
vk_buffer.setStencilReference(vk::StencilFaceFlagBits::eFront,
dynamic_params.stencil_front.reference);
vk_buffer.setStencilReference(vk::StencilFaceFlagBits::eBack,
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++) {
enable[i] = (dynamic_params.color_write_enable[i] ? VK_TRUE : VK_FALSE);
}
@ -544,7 +538,7 @@ struct DrawRenderState {
uint32_t color_count = 0;
bool ps_active = true;
VulkanFramebuffer* framebuffer = nullptr;
VkCommandBuffer vk_buffer = nullptr;
vk::CommandBuffer vk_buffer = nullptr;
ShaderVertexInputInfo vs_input_info;
ShaderPixelInputInfo ps_input_info;
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(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);
if (state.color_count != 0 || !with_depth) {
return true;
@ -607,11 +601,11 @@ struct DrawEmitInfo {
};
struct DrawIndexBufferSource {
bool enabled = false;
uint64_t address = 0;
const void* host_data = nullptr;
uint64_t size = 0;
VkIndexType type = VK_INDEX_TYPE_UINT16;
bool enabled = false;
uint64_t address = 0;
const void* host_data = nullptr;
uint64_t size = 0;
vk::IndexType type = vk::IndexType::eUint16;
};
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,
VkPrimitiveTopology* topology) {
vk::PrimitiveTopology* topology) {
EXIT_IF(ucfg == nullptr);
EXIT_IF(topology == nullptr);
*topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
*topology = vk::PrimitiveTopology::ePointList;
switch (static_cast<Prospero::PrimitiveType>(ucfg->GetPrimType())) {
case Prospero::PrimitiveType::kNone: return false;
case Prospero::PrimitiveType::kPointList:
*topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
*topology = vk::PrimitiveTopology::ePointList;
break;
case Prospero::PrimitiveType::kLineList:
*topology = vk::PrimitiveTopology::eLineList;
break;
case Prospero::PrimitiveType::kLineList: *topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; break;
case Prospero::PrimitiveType::kLineStrip:
*topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
*topology = vk::PrimitiveTopology::eLineStrip;
break;
case Prospero::PrimitiveType::kTriList:
*topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
*topology = vk::PrimitiveTopology::eTriangleList;
break;
case Prospero::PrimitiveType::kTriFan:
*topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
*topology = vk::PrimitiveTopology::eTriangleFan;
break;
case Prospero::PrimitiveType::kTriStrip:
*topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
*topology = vk::PrimitiveTopology::eTriangleStrip;
break;
case Prospero::PrimitiveType::kRectList:
*topology = (auto_draw && use_ngg_rectlist_draw ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
*topology = (auto_draw && use_ngg_rectlist_draw ? vk::PrimitiveTopology::eTriangleStrip
: vk::PrimitiveTopology::eTriangleList);
break;
case Prospero::PrimitiveType::kRectListLegacy:
if (!auto_draw) {
EXIT("unknown primitive type: %u\n", ucfg->GetPrimType());
}
*topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
*topology = vk::PrimitiveTopology::eTriangleStrip;
break;
case Prospero::PrimitiveType::kQuadListLegacy:
*topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
*topology = vk::PrimitiveTopology::eTriangleFan;
break;
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);
if (state->color_count == 0 && !with_depth) {
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,
const DrawCallInfo& draw, VkCommandBuffer vk_buffer,
const DrawCallInfo& draw, vk::CommandBuffer vk_buffer,
const ShaderVertexInputInfo& vs_input_info) {
EXIT_IF(buffer == nullptr);
EXIT_IF(draw.name == nullptr);
@ -792,11 +788,11 @@ static void BindDrawVertexBuffers(uint64_t submit_id, CommandBuffer* buffer,
LogDrawPhase(draw.name, "BindVertexBuffers");
for (int i = 0; i < vs_input_info.buffers_num; i++) {
const auto& b = vs_input_info.buffers[i];
uint64_t addr = b.addr;
uint64_t size = VertexBufferDescriptorSize(b);
VulkanBuffer* vertices = nullptr;
VkDeviceSize offset = 0;
const auto& b = vs_input_info.buffers[i];
uint64_t addr = b.addr;
uint64_t size = VertexBufferDescriptorSize(b);
VulkanBuffer* vertices = nullptr;
vk::DeviceSize offset = 0;
if (size == 0) {
vertices = g_render_ctx->GetBufferCache()->ObtainNullBuffer(
@ -809,21 +805,21 @@ static void BindDrawVertexBuffers(uint64_t submit_id, CommandBuffer* buffer,
}
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) {
if (!source.enabled) {
return;
}
EXIT_IF(source.size == 0);
VulkanBuffer* index_buffer = nullptr;
VkDeviceSize index_offset = 0;
VulkanBuffer* index_buffer = nullptr;
vk::DeviceSize index_offset = 0;
if (source.host_data != nullptr) {
VkDeviceSize range = 0;
vk::DeviceSize range = 0;
if (!g_render_ctx->GetBufferCache()->UploadHostData(buffer, g_render_ctx->GetGraphicCtx(),
source.host_data, source.size, 16,
&index_buffer, &index_offset, &range)) {
@ -836,7 +832,7 @@ static void BindDrawIndexBuffer(CommandBuffer* buffer, VkCommandBuffer vk_buffer
index_offset = binding.second;
}
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,
@ -876,7 +872,7 @@ static bool IsHostExpandedRectListDrawSupported(const ShaderVertexInputInfo& vs_
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 DrawEmitInfo& emit) {
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::kTriStrip:
if (emit.indexed) {
vkCmdDrawIndexed(vk_buffer, draw.index_count, draw.instance_count, 0,
emit.vertex_offset, draw.first_instance);
vk_buffer.drawIndexed(draw.index_count, draw.instance_count, 0, emit.vertex_offset,
draw.first_instance);
} else {
vkCmdDraw(vk_buffer, draw.index_count, draw.instance_count, emit.first_vertex,
draw.first_instance);
vk_buffer.draw(draw.index_count, draw.instance_count, emit.first_vertex,
draw.first_instance);
}
break;
case Prospero::PrimitiveType::kRectList:
if (emit.indexed) {
vkCmdDrawIndexed(vk_buffer, draw.index_count, draw.instance_count, 0,
emit.vertex_offset, draw.first_instance);
vk_buffer.drawIndexed(draw.index_count, draw.instance_count, 0, emit.vertex_offset,
draw.first_instance);
} else {
EXIT_NOT_IMPLEMENTED(
!IsHostExpandedRectListDrawSupported(vs_input_info, draw, emit));
vkCmdDraw(vk_buffer, emit.draw_vertex_count, draw.instance_count, emit.first_vertex,
draw.first_instance);
vk_buffer.draw(emit.draw_vertex_count, draw.instance_count, emit.first_vertex,
draw.first_instance);
}
break;
case Prospero::PrimitiveType::kRectListLegacy:
@ -914,17 +910,17 @@ static void EmitDrawPrimitives(const HW::UserConfig* ucfg, VkCommandBuffer vk_bu
}
// Sarah
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;
case Prospero::PrimitiveType::kQuadListLegacy:
EXIT_NOT_IMPLEMENTED((draw.index_count & 0x3u) != 0);
for (uint32_t i = 0; i < draw.index_count; i += 4) {
if (emit.indexed) {
vkCmdDrawIndexed(vk_buffer, 4, draw.instance_count, i, emit.vertex_offset,
draw.first_instance);
vk_buffer.drawIndexed(4, draw.instance_count, i, emit.vertex_offset,
draw.first_instance);
} else {
vkCmdDraw(vk_buffer, 4, draw.instance_count, i + emit.first_vertex,
draw.first_instance);
vk_buffer.draw(4, draw.instance_count, i + emit.first_vertex,
draw.first_instance);
}
}
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,
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,
bool log_pipeline_phase, bool set_bind_debug, bool set_auto_debug) {
EXIT_IF(buffer == nullptr);
@ -957,7 +953,7 @@ static void ExecutePreparedDraw(uint64_t submit_id, CommandBuffer* buffer, HW::C
if (set_bind_debug) {
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(
*ctx, state->color_info, state->color_count, state->depth_info);
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) {
SetDrawDebugPhase(buffer, submit_id, draw, 0x200u);
}
const auto vs_address_writes = BindDescriptors(
submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout,
state->vs_input_info.stage, VK_SHADER_STAGE_VERTEX_BIT, DescriptorCache::Stage::Vertex);
const auto vs_address_writes =
BindDescriptors(submit_id, buffer, vk::PipelineBindPoint::eGraphics,
pipeline->pipeline_layout, state->vs_input_info.stage,
vk::ShaderStageFlagBits::eVertex, DescriptorCache::Stage::Vertex);
std::vector<ShaderAddressWriteRange> ps_address_writes;
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);
}
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,
VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel);
vk::ShaderStageFlagBits::eFragment, DescriptorCache::Stage::Pixel);
}
if (buffer->GetRecordingGeneration() != recording_generation) {
continue;
@ -1010,20 +1007,20 @@ static void ExecutePreparedDraw(uint64_t submit_id, CommandBuffer* buffer, HW::C
SetDrawDebugPhase(buffer, submit_id, draw, 0x600u);
}
buffer->EndRenderPass();
VkPipelineStageFlags shader_write_stages = 0;
const bool vs_wrote_buffers = HasShaderBufferWrites(state->vs_input_info.stage);
const bool vs_wrote_addresses = MarkShaderAddressWrites(vs_address_writes);
vk::PipelineStageFlags shader_write_stages = {};
const bool vs_wrote_buffers = HasShaderBufferWrites(state->vs_input_info.stage);
const bool vs_wrote_addresses = MarkShaderAddressWrites(vs_address_writes);
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) {
const bool ps_wrote_buffers = HasShaderBufferWrites(state->ps_input_info.stage);
const bool ps_wrote_addresses = MarkShaderAddressWrites(ps_address_writes);
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);
}
LogDrawPhase(draw.name, "EndRenderPass");
@ -1094,27 +1091,27 @@ void RenderDrawIndex(uint64_t submit_id, CommandBuffer* buffer, HW::Context* ctx
hw_check(*ctx);
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
vk::PrimitiveTopology topology = vk::PrimitiveTopology::ePointList;
if (!GetDrawTopology(ucfg, false, false, &topology)) {
return;
}
VkIndexType index_type = VK_INDEX_TYPE_UINT16;
uint64_t index_size = 0;
bool expand_index8_to_u16 = false;
vk::IndexType index_type = vk::IndexType::eUint16;
uint64_t index_size = 0;
bool expand_index8_to_u16 = false;
switch (static_cast<Prospero::IndexType>(index_type_and_size)) {
case Prospero::IndexType::kIndex16:
index_type = VK_INDEX_TYPE_UINT16;
index_type = vk::IndexType::eUint16;
index_size = 2 * static_cast<uint64_t>(index_count);
break;
case Prospero::IndexType::kIndex32:
index_type = VK_INDEX_TYPE_UINT32;
index_type = vk::IndexType::eUint32;
index_size = 4 * static_cast<uint64_t>(index_count);
break;
// Some games use it - need vulkan extension
case Prospero::IndexType::kIndex8:
index_type = VK_INDEX_TYPE_UINT16;
index_type = vk::IndexType::eUint16;
index_size = static_cast<uint64_t>(index_count);
expand_index8_to_u16 = true;
break;
@ -1238,8 +1235,8 @@ void RenderDrawIndexAuto(uint64_t submit_id, CommandBuffer* buffer, HW::Context*
return;
}
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
const bool use_ngg_rectlist_draw = Config::NggRectlistDrawEnabled();
vk::PrimitiveTopology topology = vk::PrimitiveTopology::ePointList;
const bool use_ngg_rectlist_draw = Config::NggRectlistDrawEnabled();
if (!GetDrawTopology(ucfg, true, use_ngg_rectlist_draw, &topology)) {
return;

View File

@ -1,9 +1,10 @@
#ifndef 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 <type_traits>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -40,10 +41,10 @@ inline constexpr TargetViewInfo ResolveTargetViewInfo(uint32_t base_layer, uint3
#pragma pack(push, 1)
struct PipelineStencilStaticState {
VkStencilOp failOp = VK_STENCIL_OP_KEEP;
VkStencilOp passOp = VK_STENCIL_OP_KEEP;
VkStencilOp depthFailOp = VK_STENCIL_OP_KEEP;
VkCompareOp compareOp = VK_COMPARE_OP_NEVER;
vk::StencilOp failOp = vk::StencilOp::eKeep;
vk::StencilOp passOp = vk::StencilOp::eKeep;
vk::StencilOp depthFailOp = vk::StencilOp::eKeep;
vk::CompareOp compareOp = vk::CompareOp::eNever;
};
struct PipelineStencilDynamicState {
@ -56,16 +57,17 @@ struct PipelineStencilDynamicState {
inline constexpr bool stencil_face_accesses_attachment(const PipelineStencilStaticState& state,
const PipelineStencilDynamicState& dynamic) {
return state.compareOp != VK_COMPARE_OP_ALWAYS ||
return state.compareOp != vk::CompareOp::eAlways ||
(dynamic.writeMask != 0 &&
(state.failOp != VK_STENCIL_OP_KEEP || state.passOp != VK_STENCIL_OP_KEEP ||
state.depthFailOp != VK_STENCIL_OP_KEEP));
(state.failOp != vk::StencilOp::eKeep || state.passOp != vk::StencilOp::eKeep ||
state.depthFailOp != vk::StencilOp::eKeep));
}
static_assert(std::is_trivially_copyable_v<PipelineStencilStaticState>);
static_assert(std::is_standard_layout_v<PipelineStencilStaticState>);
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_standard_layout_v<PipelineStencilDynamicState>);
static_assert(alignof(PipelineStencilDynamicState) == 1);

View File

@ -16,6 +16,7 @@
#include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/displayBuffer.h"
#include <algorithm>
@ -24,7 +25,6 @@
#include <cstdarg>
#include <cstdio>
#include <limits>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics {
@ -34,123 +34,127 @@ void GraphicsRenderMemoryBarrier(CommandBuffer* buffer) {
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 {};
mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
VulkanMemoryBarrier mem_barrier {};
mem_barrier.sType = vk::StructureType::eMemoryBarrier;
mem_barrier.pNext = nullptr;
mem_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
mem_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
mem_barrier.srcAccessMask = vk::AccessFlagBits::eMemoryWrite;
mem_barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1, &mem_barrier, 0, nullptr, 0,
nullptr);
vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eAllCommands, vk::DependencyFlags {}, 1,
&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);
VkImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_MEMORY_READ_BIT;
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
image_memory_barrier.oldLayout = image->layout;
image_memory_barrier.newLayout = RENDER_COLOR_IMAGE_LAYOUT;
vk::ImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = vk::StructureType::eImageMemoryBarrier;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask =
vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eTransferWrite |
vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eMemoryRead;
image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
image_memory_barrier.oldLayout = image->layout;
image_memory_barrier.newLayout = RENDER_COLOR_IMAGE_LAYOUT;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
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.levelCount = VK_REMAINING_MIP_LEVELS;
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
image_memory_barrier.subresourceRange.layerCount = image->layers;
vkCmdPipelineBarrier(
vk_buffer,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
vk_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput |
vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eTransfer |
vk::PipelineStageFlagBits::eFragmentShader,
vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eFragmentShader |
vk::PipelineStageFlagBits::eComputeShader,
vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
image->layout = image_memory_barrier.newLayout;
}
void GraphicsRenderColorImageBarrier(VkCommandBuffer vk_buffer, VulkanImage* image,
VkImageLayout new_layout) {
void GraphicsRenderColorImageBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image,
vk::ImageLayout new_layout) {
EXIT_IF(image == nullptr);
if (image->layout != new_layout) {
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};
if (log_count.fetch_add(1, std::memory_order_relaxed) < 128) {
LOGF("GraphicsRenderColorImageBarrier: image=%p type=%d layout=%s -> %s\n",
reinterpret_cast<void*>(image->image), static_cast<int>(image->type),
string_VkImageLayout(image->layout), string_VkImageLayout(new_layout));
VulkanHandleToPointer(image->image), static_cast<int>(image->type),
VulkanToString(image->layout).c_str(), VulkanToString(new_layout).c_str());
}
}
VkImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT;
image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT;
image_memory_barrier.oldLayout = image->layout;
image_memory_barrier.newLayout = new_layout;
vk::ImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = vk::StructureType::eImageMemoryBarrier;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask =
vk::AccessFlagBits::eMemoryWrite | vk::AccessFlagBits::eMemoryRead;
image_memory_barrier.dstAccessMask =
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.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
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.levelCount = VK_REMAINING_MIP_LEVELS;
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
image_memory_barrier.subresourceRange.layerCount = image->layers;
const auto stages = static_cast<VkPipelineStageFlags>(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT);
vkCmdPipelineBarrier(vk_buffer, stages, stages, 0, 0, nullptr, 0, nullptr, 1,
&image_memory_barrier);
const auto stages = static_cast<vk::PipelineStageFlags>(
vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader |
vk::PipelineStageFlagBits::eTransfer);
vk_buffer.pipelineBarrier(stages, stages, vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1,
&image_memory_barrier);
image->layout = image_memory_barrier.newLayout;
}
}
VkImageAspectFlags DepthStencilAspectMask(VkFormat format);
vk::ImageAspectFlags DepthStencilAspectMask(vk::Format format);
void GraphicsRenderDepthStencilImageBarrier(VkCommandBuffer vk_buffer, VulkanImage* image,
VkImageLayout new_layout) {
void GraphicsRenderDepthStencilImageBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image,
vk::ImageLayout new_layout) {
EXIT_IF(image == nullptr);
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",
string_VkImageLayout(new_layout));
VulkanToString(new_layout).c_str());
}
if (image->layout == new_layout) {
return;
}
VkImageMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
barrier.oldLayout = image->layout;
barrier.newLayout = new_layout;
vk::ImageMemoryBarrier barrier {};
barrier.sType = vk::StructureType::eImageMemoryBarrier;
barrier.srcAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
barrier.oldLayout = image->layout;
barrier.newLayout = new_layout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image->image;
barrier.subresourceRange = {DepthStencilAspectMask(image->format), 0, VK_REMAINING_MIP_LEVELS,
0, image->layers};
const auto stages = static_cast<VkPipelineStageFlags>(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT);
vkCmdPipelineBarrier(vk_buffer, stages, stages, 0, 0, nullptr, 0, nullptr, 1, &barrier);
const auto stages = static_cast<vk::PipelineStageFlags>(
vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader |
vk::PipelineStageFlagBits::eTransfer);
vk_buffer.pipelineBarrier(stages, stages, vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1,
&barrier);
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->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) {
LOGF(
"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;
}
if (image->layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) {
VkImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
image_memory_barrier.oldLayout = image->layout;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = image->image;
if (image->layout != vk::ImageLayout::eDepthStencilReadOnlyOptimal) {
vk::ImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = vk::StructureType::eImageMemoryBarrier;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask =
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
image_memory_barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
image_memory_barrier.oldLayout = image->layout;
image_memory_barrier.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
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.baseMipLevel = 0;
image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
image_memory_barrier.subresourceRange.layerCount = image->layers;
vkCmdPipelineBarrier(
vk_buffer,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
vk_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eAllGraphics | vk::PipelineStageFlagBits::eComputeShader |
vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eFragmentShader |
vk::PipelineStageFlagBits::eComputeShader,
vk::DependencyFlags {}, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
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());
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);
if (native == nullptr) {
@ -216,7 +220,7 @@ void GraphicsRenderDepthStencilBarrier(CommandBuffer* buffer, uint64_t vaddr, ui
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);
if (native == nullptr) {
EXIT("depth-target barrier range has no cached image\n");

View File

@ -1,18 +1,18 @@
#ifndef 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 {
struct VulkanImage;
void GraphicsRenderTextureBarrier(VkCommandBuffer vk_buffer, VulkanImage* image);
void GraphicsRenderColorImageBarrier(VkCommandBuffer vk_buffer, VulkanImage* image,
VkImageLayout new_layout);
void GraphicsRenderDepthStencilImageBarrier(VkCommandBuffer vk_buffer, VulkanImage* image,
VkImageLayout new_layout);
void GraphicsRenderDepthStencilBarrier(VkCommandBuffer vk_buffer, VulkanImage* image);
void GraphicsRenderTextureBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image);
void GraphicsRenderColorImageBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image,
vk::ImageLayout new_layout);
void GraphicsRenderDepthStencilImageBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image,
vk::ImageLayout new_layout);
void GraphicsRenderDepthStencilBarrier(vk::CommandBuffer vk_buffer, VulkanImage* image);
} // namespace Libs::Graphics

View File

@ -7,7 +7,7 @@
namespace Libs::Graphics {
VkSampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
vk::Sampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
Common::LockGuard lock(m_mutex);
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) {
switch (static_cast<Prospero::SamplerFilter>(filter)) {
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::kAnisoLinear: return VK_FILTER_LINEAR;
case Prospero::SamplerFilter::kAnisoLinear: return vk::Filter::eLinear;
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);
@ -61,60 +61,60 @@ VkSampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
max_lod = static_cast<float>(r.MaxLod()) / 256.0f;
}
VkSamplerCreateInfo sampler_info {};
vk::SamplerCreateInfo sampler_info {};
auto to_vk_address_mode = [](uint8_t 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:
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
return vk::SamplerAddressMode::eMirroredRepeat;
case Prospero::SamplerClampMode::kClampLastTexel:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
return vk::SamplerAddressMode::eClampToEdge;
case Prospero::SamplerClampMode::kMirrorOnceLastTexel:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
return vk::SamplerAddressMode::eMirrorClampToEdge;
case Prospero::SamplerClampMode::kClampHalfBorder:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
return vk::SamplerAddressMode::eClampToBorder;
case Prospero::SamplerClampMode::kMirrorOnceHalfBorder:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
return vk::SamplerAddressMode::eMirrorClampToEdge;
case Prospero::SamplerClampMode::kClampBorder:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
return vk::SamplerAddressMode::eClampToBorder;
case Prospero::SamplerClampMode::kMirrorOnceBorder:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
return vk::SamplerAddressMode::eMirrorClampToEdge;
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())) {
case Prospero::SamplerBorderColor::kTransBlack:
border = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
border = vk::BorderColor::eIntTransparentBlack;
break;
case Prospero::SamplerBorderColor::kOpaqueBlack:
border = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
border = vk::BorderColor::eIntOpaqueBlack;
break;
case Prospero::SamplerBorderColor::kOpaqueWhite:
border = VK_BORDER_COLOR_INT_OPAQUE_WHITE;
border = vk::BorderColor::eIntOpaqueWhite;
break;
case Prospero::SamplerBorderColor::kFromTable:
LOGF(
"temporary: approximating table border color as transparent black, index = %" PRIu16
"\n",
r.BorderColorPtr());
border = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
border = vk::BorderColor::eIntTransparentBlack;
break;
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.flags = 0;
sampler_info.flags = {};
sampler_info.magFilter = to_vk_filter(mag_filter);
sampler_info.minFilter = to_vk_filter(min_filter);
sampler_info.mipmapMode =
(static_cast<Prospero::SamplerMipFilter>(mip_filter) == Prospero::SamplerMipFilter::kLinear
? VK_SAMPLER_MIPMAP_MODE_LINEAR
: VK_SAMPLER_MIPMAP_MODE_NEAREST);
? vk::SamplerMipmapMode::eLinear
: vk::SamplerMipmapMode::eNearest);
sampler_info.addressModeU = to_vk_address_mode(r.ClampX());
sampler_info.addressModeV = to_vk_address_mode(r.ClampY());
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.maxAnisotropy = aniso_ratio;
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.maxLod = max_lod;
sampler_info.borderColor = border;
sampler_info.unnormalizedCoordinates = (r.ForceUnormCoords() ? VK_TRUE : VK_FALSE);
if (r.ForceUnormCoords()) {
sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
sampler_info.addressModeU = vk::SamplerAddressMode::eClampToEdge;
sampler_info.addressModeV = vk::SamplerAddressMode::eClampToEdge;
sampler_info.addressModeW = vk::SamplerAddressMode::eClampToEdge;
sampler_info.mipmapMode = vk::SamplerMipmapMode::eNearest;
sampler_info.minLod = 0.0f;
sampler_info.maxLod = 0.0f;
sampler_info.anisotropyEnable = VK_FALSE;
@ -142,8 +142,8 @@ VkSampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
sampler_info.mipLodBias = 0.0f;
}
VkSampler vk_sampler = nullptr;
vkCreateSampler(g_render_ctx->GetGraphicCtx()->device, &sampler_info, nullptr, &vk_sampler);
vk::Sampler vk_sampler = nullptr;
g_render_ctx->GetGraphicCtx()->device.createSampler(&sampler_info, nullptr, &vk_sampler);
EXIT_NOT_IMPLEMENTED(vk_sampler == nullptr);
m_samplers.emplace(key, vk_sampler);

View File

@ -5,12 +5,12 @@
#include "common/assert.h"
#include "common/common.h"
#include "common/threads.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/shader/shaderBindings.h"
#include <array>
#include <cstddef>
#include <unordered_map>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -20,7 +20,7 @@ public:
virtual ~SamplerCache() { KYTY_NOT_IMPLEMENTED; }
KYTY_CLASS_NO_COPY(SamplerCache);
VkSampler GetSampler(const ShaderSamplerResource& r);
vk::Sampler GetSampler(const ShaderSamplerResource& r);
private:
using SamplerKey = std::array<uint32_t, 4>;
@ -37,8 +37,8 @@ private:
}
};
Common::Mutex m_mutex;
std::unordered_map<SamplerKey, VkSampler, SamplerKeyHash> m_samplers;
Common::Mutex m_mutex;
std::unordered_map<SamplerKey, vk::Sampler, SamplerKeyHash> m_samplers;
};
} // namespace Libs::Graphics

View File

@ -9,63 +9,70 @@
namespace Libs::Graphics {
VkPipelineStageFlags ShaderPipelineStages(VkShaderStageFlags stages) {
VkPipelineStageFlags result = 0;
if ((stages & VK_SHADER_STAGE_VERTEX_BIT) != 0) {
result |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
vk::PipelineStageFlags ShaderPipelineStages(vk::ShaderStageFlags stages) {
vk::PipelineStageFlags result = {};
if (stages & vk::ShaderStageFlagBits::eVertex) {
result |= vk::PipelineStageFlagBits::eVertexShader;
}
if ((stages & VK_SHADER_STAGE_FRAGMENT_BIT) != 0) {
result |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
if (stages & vk::ShaderStageFlagBits::eFragment) {
result |= vk::PipelineStageFlagBits::eFragmentShader;
}
if ((stages & VK_SHADER_STAGE_COMPUTE_BIT) != 0) {
result |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
if (stages & vk::ShaderStageFlagBits::eCompute) {
result |= vk::PipelineStageFlagBits::eComputeShader;
}
EXIT_IF(result == 0);
EXIT_IF(!result);
return result;
}
VkMemoryBarrier MakeShaderWriteDependency() {
VkMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDEX_READ_BIT |
VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
VulkanMemoryBarrier MakeShaderWriteDependency() {
VulkanMemoryBarrier barrier {};
barrier.sType = vk::StructureType::eMemoryBarrier;
barrier.srcAccessMask = vk::AccessFlagBits::eShaderWrite;
barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eVertexAttributeRead |
vk::AccessFlagBits::eIndexRead | vk::AccessFlagBits::eUniformRead |
vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite |
vk::AccessFlagBits::eColorAttachmentRead |
vk::AccessFlagBits::eColorAttachmentWrite;
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);
VkImageMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
barrier.dstAccessMask =
(read ? VK_ACCESS_SHADER_READ_BIT : 0) | (written ? VK_ACCESS_SHADER_WRITE_BIT : 0);
vk::ImageMemoryBarrier barrier {};
barrier.sType = vk::StructureType::eImageMemoryBarrier;
barrier.srcAccessMask = vk::AccessFlagBits::eMemoryWrite;
barrier.dstAccessMask = {};
if (read) {
barrier.dstAccessMask |= vk::AccessFlagBits::eShaderRead;
}
if (written) {
barrier.dstAccessMask |= vk::AccessFlagBits::eShaderWrite;
}
barrier.oldLayout = image.layout;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.newLayout = vk::ImageLayout::eGeneral;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image.image;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = image.layers;
EXIT_IF(barrier.dstAccessMask == 0 || barrier.subresourceRange.layerCount == 0);
EXIT_IF(!barrier.dstAccessMask || barrier.subresourceRange.layerCount == 0);
return barrier;
}
VkBufferMemoryBarrier MakeGdsDependency(const VulkanBuffer& buffer) {
vk::BufferMemoryBarrier MakeGdsDependency(const VulkanBuffer& buffer) {
EXIT_IF(buffer.buffer == nullptr);
VkBufferMemoryBarrier barrier {};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
barrier.srcAccessMask =
VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
vk::BufferMemoryBarrier barrier {};
barrier.sType = vk::StructureType::eBufferMemoryBarrier;
barrier.srcAccessMask = vk::AccessFlagBits::eHostWrite | vk::AccessFlagBits::eTransferWrite |
vk::AccessFlagBits::eShaderWrite;
barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.buffer = buffer.buffer;
@ -113,15 +120,16 @@ bool HasShaderBufferWrites(const ShaderStageRuntime& runtime) {
return !CollectShaderBufferWrites(*runtime.program, *runtime.resources).empty();
}
void ShaderWriteBarrier(VkCommandBuffer vk_buffer, VkPipelineStageFlags source_stages) {
EXIT_IF(vk_buffer == nullptr || source_stages == 0);
void ShaderWriteBarrier(vk::CommandBuffer vk_buffer, vk::PipelineStageFlags source_stages) {
EXIT_IF(vk_buffer == nullptr || !source_stages);
const auto barrier = MakeShaderWriteDependency();
vkCmdPipelineBarrier(
vk_buffer, source_stages,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0, 1, &barrier, 0, nullptr, 0, nullptr);
vk_buffer.pipelineBarrier(
source_stages,
vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eVertexInput |
vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eFragmentShader |
vk::PipelineStageFlagBits::eTransfer |
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::DependencyFlags {}, 1, &barrier, 0, nullptr, 0, nullptr);
}
} // namespace Libs::Graphics

View File

@ -18,16 +18,17 @@ struct ShaderBufferWriteRange {
bool operator==(const ShaderBufferWriteRange& other) const = default;
};
VkPipelineStageFlags ShaderPipelineStages(VkShaderStageFlags stages);
VkMemoryBarrier MakeShaderWriteDependency();
VkImageMemoryBarrier MakeStorageImageDependency(const VulkanImage& image, bool read, bool written);
VkBufferMemoryBarrier MakeGdsDependency(const VulkanBuffer& buffer);
vk::PipelineStageFlags ShaderPipelineStages(vk::ShaderStageFlags stages);
VulkanMemoryBarrier MakeShaderWriteDependency();
vk::ImageMemoryBarrier MakeStorageImageDependency(const VulkanImage& image, bool read,
bool written);
vk::BufferMemoryBarrier MakeGdsDependency(const VulkanBuffer& buffer);
std::vector<ShaderBufferWriteRange>
CollectShaderBufferWrites(const ShaderRecompiler::IR::Program& program,
const ShaderRecompiler::IR::ResourceSnapshot& resources);
bool MarkShaderAddressWrites(const std::vector<ShaderAddressWriteRange>& writes);
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

View File

@ -17,13 +17,13 @@ ShaderLaneMaskMode SelectGraphicsLaneMaskMode(const GraphicContext& context,
}
ShaderSubgroupConfiguration ConfigureShaderSubgroup(const GraphicContext& context,
VkShaderStageFlagBits stage,
vk::ShaderStageFlagBits stage,
const ShaderRecompiler::IR::Program& program) {
const auto guest_wave_size = program.wave_size;
if (guest_wave_size != 32u && guest_wave_size != 64u) {
return {};
}
if (stage != VK_SHADER_STAGE_COMPUTE_BIT) {
if (stage != vk::ShaderStageFlagBits::eCompute) {
const auto expected = SelectGraphicsLaneMaskMode(context, guest_wave_size);
if (program.lane_mask_mode != expected || (context.subgroup_size != guest_wave_size &&
expected != ShaderLaneMaskMode::PerInvocation)) {
@ -40,8 +40,7 @@ ShaderSubgroupConfiguration ConfigureShaderSubgroup(const GraphicContext&
if (context.subgroup_size == guest_wave_size) {
return {ShaderSubgroupMode::Natural, 0};
}
if (context.subgroup_size_control_enabled &&
(context.required_subgroup_size_stages & stage) != 0 &&
if (context.subgroup_size_control_enabled && (context.required_subgroup_size_stages & stage) &&
guest_wave_size >= context.min_subgroup_size &&
guest_wave_size <= context.max_subgroup_size) {
return {ShaderSubgroupMode::Controlled, guest_wave_size};

View File

@ -23,7 +23,7 @@ ShaderLaneMaskMode SelectGraphicsLaneMaskMode(const GraphicContext& context,
uint32_t guest_wave_size);
ShaderSubgroupConfiguration ConfigureShaderSubgroup(const GraphicContext& context,
VkShaderStageFlagBits stage,
vk::ShaderStageFlagBits stage,
const ShaderRecompiler::IR::Program& program);
} // namespace Libs::Graphics

File diff suppressed because it is too large Load Diff

View File

@ -32,12 +32,13 @@ void HostStreamBuffer::EnsureBuffer(GraphicContext* ctx) {
KYTY_PROFILER_BLOCK("HostStreamBuffer::create");
m_ctx = ctx;
m_buffer = std::make_unique<VulkanBuffer>();
m_buffer->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT;
m_buffer->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
m_buffer->usage = vk::BufferUsageFlagBits::eStorageBuffer |
vk::BufferUsageFlagBits::eVertexBuffer |
vk::BufferUsageFlagBits::eIndexBuffer |
vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst;
m_buffer->memory.property = vk::MemoryPropertyFlagBits::eHostVisible |
vk::MemoryPropertyFlagBits::eHostCoherent |
vk::MemoryPropertyFlagBits::eHostCached;
VulkanCreateBuffer(ctx, CAPACITY, m_buffer.get());
VulkanMapMemory(ctx, &m_buffer->memory, &m_mapped);
const auto count = g_stream_buffer_count.fetch_add(1, std::memory_order_relaxed) + 1;

View File

@ -251,7 +251,7 @@ VulkanImage* TextureCache::PublishImage(CommandBuffer* command,
image != nullptr ? static_cast<const void*>(image->image) : nullptr,
image != nullptr && image->registered);
}
auto* result = image->image;
auto result = image->image;
command->RetainResourceUntilFence(image);
m_images.push_back(std::move(image));
RegisterImageLocked(*m_images.back());
@ -397,10 +397,10 @@ struct TextureCache::ReadbackWorker {
size <= info.address + info.size - vaddr;
const bool d16 =
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 =
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_htile {};
TileSizeAlign expected_depth {};
@ -466,7 +466,7 @@ struct TextureCache::ReadbackWorker {
std::fill(download.begin(), download.end(), 0);
const auto regions =
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,
cached.image->layout);
guest.resize(info.size);
@ -820,7 +820,7 @@ bool Equal(const DepthTargetInfo& left, const DepthTargetInfo& right) {
}
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 level = 0; level < source->mip_levels; level++) {
ImageImageCopy region {};
@ -1060,7 +1060,7 @@ void TextureCache::RetireStorageDepthAliasLocked(GraphicContext* ctx, const Imag
cached.ctx == ctx && cached.gpu_modified && !cached.buffer_modified &&
depth.address == requested.address && depth.size == requested.size &&
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.bytes_per_element == 4 && depth.width == requested.width &&
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->info = info;
cached->ctx = ctx;
VkComponentMapping components {};
vk::ComponentMapping components {};
cached->image = ImageOps::CreateTexture(ctx, info, false, &cached->memory, &components);
m_memory_tracker.ForEachUploadRange(
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->info = info;
cached->ctx = ctx;
VkComponentMapping components {};
vk::ComponentMapping components {};
cached->image = ImageOps::CreateTexture(ctx, info, true, &cached->memory, &components);
m_memory_tracker.ForEachUploadRange(
info.address, info.size, true, [](uint64_t, uint64_t) noexcept {},
@ -1420,7 +1420,7 @@ RenderTextureVulkanImage* TextureCache::FindRenderTarget(CommandBuffer*
const RenderTargetInfo& info) {
const bool standard64 = IsSupportedStandard64RenderTarget(info);
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.bytes_per_element == 0 || info.levels == 0 || info.levels > 16 || info.layers == 0 ||
info.size % info.layers != 0 ||
@ -1635,9 +1635,8 @@ RenderTextureVulkanImage* TextureCache::FindRenderTarget(CommandBuffer*
std::vector<ImageImageCopy> regions;
regions.reserve(static_cast<size_t>(native_image_source->image->layers) *
native_image_source->image->mip_levels);
AppendLayerCopies(regions, native_image_source->image, VK_IMAGE_ASPECT_COLOR_BIT);
UtilImageToImage(command, regions, cached->image,
static_cast<uint64_t>(RENDER_COLOR_IMAGE_LAYOUT));
AppendLayerCopies(regions, native_image_source->image, vk::ImageAspectFlagBits::eColor);
UtilImageToImage(command, regions, cached->image, RENDER_COLOR_IMAGE_LAYOUT);
} else {
m_memory_tracker.ForEachUploadRange(
info.address, info.size, false, [](uint64_t, uint64_t) noexcept {},
@ -1935,12 +1934,13 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
}
std::vector<ImageImageCopy> regions;
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) {
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,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
vk::ImageLayout::eDepthStencilAttachmentOptimal);
cached->gpu_modified = true;
} else {
if (sampled_depth_source != nullptr &&
@ -1967,11 +1967,11 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
break;
case DepthTransitionSource::Native:
command->RetainResourceUntilFence(sampled_depth_source);
UtilCopyImageWithBuffer(
command, ctx, sampled_depth_source->image, VK_IMAGE_ASPECT_COLOR_BIT,
cached->image, VK_IMAGE_ASPECT_DEPTH_BIT, info.bytes_per_element,
static_cast<uint64_t>(
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
UtilCopyImageWithBuffer(command, ctx, sampled_depth_source->image,
vk::ImageAspectFlagBits::eColor, cached->image,
vk::ImageAspectFlagBits::eDepth,
info.bytes_per_element,
vk::ImageLayout::eDepthStencilAttachmentOptimal);
break;
}
});
@ -2269,18 +2269,17 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer* command, uint64_t vaddr,
image_cpu_modified);
}
auto* vk_buffer = command->GetPool()->buffers[command->GetIndex()];
auto vk_buffer = command->GetPool()->buffers[command->GetIndex()];
if (aspect == ClearAspect::Color) {
VkClearColorValue clear {};
vk::ClearColorValue clear {};
if (!DecodePackedColorClear(match->image->format, packed_clear, &clear)) {
return false;
}
GraphicsRenderColorImageBarrier(vk_buffer, match->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
const VkImageSubresourceRange range {VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS,
0, match->image->layers};
vkCmdClearColorImage(vk_buffer, match->image->image, match->image->layout, &clear, 1,
&range);
vk::ImageLayout::eTransferDstOptimal);
const vk::ImageSubresourceRange range {vk::ImageAspectFlagBits::eColor, 0,
VK_REMAINING_MIP_LEVELS, 0, match->image->layers};
vk_buffer.clearColorImage(match->image->image, match->image->layout, &clear, 1, &range);
GraphicsRenderColorImageBarrier(vk_buffer, match->image, RENDER_COLOR_IMAGE_LAYOUT);
if (!match->gpu_modified) {
m_memory_tracker.MarkRegionAsGpuModified(vaddr, size);
@ -2290,22 +2289,22 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer* command, uint64_t vaddr,
return true;
}
if (match->image->layout == VK_IMAGE_LAYOUT_UNDEFINED ||
match->image->layout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
if (match->image->layout == vk::ImageLayout::eUndefined ||
match->image->layout == vk::ImageLayout::ePreinitialized) {
EXIT("TextureCache: compute %s clear has invalid source layout %u\n",
aspect == ClearAspect::Depth ? "depth" : "stencil",
static_cast<uint32_t>(match->image->layout));
}
const auto old_layout = match->image->layout;
GraphicsRenderDepthStencilImageBarrier(vk_buffer, match->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
const VkClearDepthStencilValue clear {depth_clear, stencil_clear};
const auto clear_aspect = static_cast<VkImageAspectFlags>(
aspect == ClearAspect::Depth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT);
const VkImageSubresourceRange range {clear_aspect, 0, VK_REMAINING_MIP_LEVELS, 0,
match->image->layers};
vkCmdClearDepthStencilImage(vk_buffer, match->image->image, match->image->layout, &clear, 1,
&range);
vk::ImageLayout::eTransferDstOptimal);
const vk::ClearDepthStencilValue clear {depth_clear, stencil_clear};
const auto clear_aspect = static_cast<vk::ImageAspectFlags>(
aspect == ClearAspect::Depth ? vk::ImageAspectFlagBits::eDepth
: vk::ImageAspectFlagBits::eStencil);
const vk::ImageSubresourceRange range {clear_aspect, 0, VK_REMAINING_MIP_LEVELS, 0,
match->image->layers};
vk_buffer.clearDepthStencilImage(match->image->image, match->image->layout, &clear, 1, &range);
GraphicsRenderDepthStencilImageBarrier(vk_buffer, match->image, old_layout);
if (aspect == ClearAspect::Stencil) {
match->stencil_initialized = true;
@ -2575,10 +2574,10 @@ void TextureCache::SynchronizeDepthImageToBufferLocked(CachedImage& cached, uint
TileSizeAlign expected_depth {};
const bool d16 =
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 =
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 =
(d16 || d32) &&
TileGetDepthSize(info.width, info.height, 0,
@ -2604,7 +2603,7 @@ void TextureCache::SynchronizeDepthImageToBufferLocked(CachedImage& cached, uint
m_buffer_transition_linear.resize(info.size);
std::fill(m_buffer_transition_linear.begin(), m_buffer_transition_linear.end(), 0);
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,
cached.image->layout);
m_buffer_transition_guest.resize(info.size);

View File

@ -8,12 +8,12 @@
#include "graphics/host_gpu/renderer/imageInfo.h"
#include "graphics/host_gpu/renderer/multiLevelPageTable.h"
#include "graphics/host_gpu/renderer/tiler.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <map>
#include <memory>
#include <mutex>
#include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -68,37 +68,35 @@ public:
bool formatted_buffer_write = false);
[[nodiscard]] RenderTextureVulkanImage* FindRenderTargetByRange(CommandBuffer* command,
uint64_t vaddr, uint64_t size);
[[nodiscard]] VkImageView GetRenderTargetAttachmentView(GraphicContext* ctx,
RenderTextureVulkanImage* image,
VkFormat format, uint32_t level,
uint32_t base_layer,
uint32_t layer_count);
[[nodiscard]] VkImageView GetDepthTargetAttachmentView(GraphicContext* ctx,
DepthStencilVulkanImage* image,
uint32_t base_layer,
uint32_t layer_count);
[[nodiscard]] VkImageView GetDepthTargetSampledView(GraphicContext* ctx,
DepthStencilVulkanImage* image,
VkFormat view_format, uint32_t swizzle,
uint32_t base_level, uint32_t level_count,
VkImageViewType type, uint32_t base_layer,
uint32_t layer_count);
[[nodiscard]] VkImageView GetSampledColorView(GraphicContext* ctx, VulkanImage* image,
VkFormat view_format, uint32_t swizzle,
uint32_t base_level, uint32_t level_count,
VkImageViewType type, uint32_t base_layer,
uint32_t layer_count);
[[nodiscard]] VkImageView GetRenderTargetStorageView(GraphicContext* ctx,
RenderTextureVulkanImage* image,
VkFormat view_format, uint32_t base_level,
uint32_t level_count, VkImageViewType type,
uint32_t base_layer, uint32_t layer_count);
[[nodiscard]] VkImageView GetStorageTextureSampledView(GraphicContext* ctx,
StorageTextureVulkanImage* image,
const ImageInfo& info);
[[nodiscard]] VkImageView GetStorageTextureStorageView(GraphicContext* ctx,
StorageTextureVulkanImage* image,
uint32_t base_level);
[[nodiscard]] vk::ImageView GetRenderTargetAttachmentView(GraphicContext* ctx,
RenderTextureVulkanImage* image,
vk::Format format, uint32_t level,
uint32_t base_layer,
uint32_t layer_count);
[[nodiscard]] vk::ImageView GetDepthTargetAttachmentView(GraphicContext* ctx,
DepthStencilVulkanImage* image,
uint32_t base_layer,
uint32_t layer_count);
[[nodiscard]] vk::ImageView
GetDepthTargetSampledView(GraphicContext* ctx, DepthStencilVulkanImage* image,
vk::Format view_format, uint32_t swizzle, uint32_t base_level,
uint32_t level_count, vk::ImageViewType type, uint32_t base_layer,
uint32_t layer_count);
[[nodiscard]] vk::ImageView GetSampledColorView(GraphicContext* ctx, VulkanImage* image,
vk::Format view_format, uint32_t swizzle,
uint32_t base_level, uint32_t level_count,
vk::ImageViewType type, uint32_t base_layer,
uint32_t layer_count);
[[nodiscard]] vk::ImageView
GetRenderTargetStorageView(GraphicContext* ctx, RenderTextureVulkanImage* image,
vk::Format view_format, uint32_t base_level, uint32_t level_count,
vk::ImageViewType type, uint32_t base_layer, uint32_t layer_count);
[[nodiscard]] vk::ImageView GetStorageTextureSampledView(GraphicContext* ctx,
StorageTextureVulkanImage* image,
const ImageInfo& info);
[[nodiscard]] vk::ImageView GetStorageTextureStorageView(GraphicContext* ctx,
StorageTextureVulkanImage* image,
uint32_t base_level);
[[nodiscard]] DepthStencilVulkanImage*
FindDepthTargetByRange(CommandBuffer* command, uint64_t vaddr, uint64_t size,
bool allow_containing_sampled = false);
@ -126,12 +124,12 @@ private:
uint32_t clear_mask = 0;
bool gpu_modified = false;
};
[[nodiscard]] VkImageView GetImageView(GraphicContext* ctx, VulkanImage* image,
const ImageViewInfo& info);
[[nodiscard]] bool HasMetaOverlapLocked(uint64_t vaddr, uint64_t size) const;
[[nodiscard]] CachedImage* FindGpuReadbackPageCandidateLocked(uint64_t vaddr, uint64_t size);
void RequireNoMetaOverlapLocked(uint64_t vaddr, uint64_t size) const;
void MarkSampledAliasesCpuDirtyLocked(uint64_t vaddr, uint64_t size);
[[nodiscard]] vk::ImageView GetImageView(GraphicContext* ctx, VulkanImage* image,
const ImageViewInfo& info);
[[nodiscard]] bool HasMetaOverlapLocked(uint64_t vaddr, uint64_t size) const;
[[nodiscard]] CachedImage* FindGpuReadbackPageCandidateLocked(uint64_t vaddr, uint64_t size);
void RequireNoMetaOverlapLocked(uint64_t vaddr, uint64_t size) const;
void MarkSampledAliasesCpuDirtyLocked(uint64_t vaddr, uint64_t size);
void RetireSampledTargetAliases(GraphicContext* ctx, const ImageInfo& requested);
void ResolveStorageImageOverlaps(GraphicContext* ctx, const ImageInfo& requested);
void RetireStorageDepthAliasLocked(GraphicContext* ctx, const ImageInfo& requested);

View File

@ -45,11 +45,11 @@ static void UploadPromotedD16Depth(GraphicContext* ctx, DepthStencilVulkanImage*
region.width = info.width;
region.height = info.height;
region.dst_layer = base_layer + layer;
region.aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
region.aspect = vk::ImageAspectFlagBits::eDepth;
regions.push_back(region);
}
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,
@ -70,8 +70,7 @@ void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image, const
ctx, image, reinterpret_cast<const void*>(source.address), info.size, regions, layout,
info.format, info.width, info.height, info.depth, info.levels, slice_layout,
storage ? "StorageTextureCache" : "TextureCache",
static_cast<uint64_t>(storage ? VK_IMAGE_LAYOUT_GENERAL
: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
storage ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal);
}
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) {
switch (info.format) {
case VK_FORMAT_D24_UNORM_S8_UINT:
case vk::Format::eD24UnormS8Uint:
UploadPromotedD16Depth<EncodeD16AsD24>(ctx, image, info, source, base_layer);
return;
case VK_FORMAT_D32_SFLOAT_S8_UINT:
case vk::Format::eD32SfloatS8Uint:
UploadPromotedD16Depth<EncodeD16AsD32>(ctx, image, info, source, base_layer);
return;
default:
@ -108,11 +107,11 @@ void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
region.width = info.width;
region.height = info.height;
region.dst_layer = base_layer + layer;
region.aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
region.aspect = vk::ImageAspectFlagBits::eDepth;
regions.push_back(region);
}
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,
@ -139,11 +138,11 @@ void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
region.width = info.width;
region.height = info.height;
region.dst_layer = base_layer + layer;
region.aspect = VK_IMAGE_ASPECT_STENCIL_BIT;
region.aspect = vk::ImageAspectFlagBits::eStencil;
regions.push_back(region);
}
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 {

File diff suppressed because it is too large Load Diff

View File

@ -3,11 +3,11 @@
#include "common/abi.h"
#include "common/common.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <span>
#include <utility>
#include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -20,55 +20,55 @@ struct DepthStencilVulkanImage;
struct VulkanSwapchain;
struct BufferImageCopy {
uint32_t offset;
uint32_t pitch;
uint32_t dst_level;
uint32_t width;
uint32_t height;
uint32_t copy_height = 0;
uint32_t dst_layer = 0;
int dst_x;
int dst_y;
int dst_z = 0;
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
uint32_t offset;
uint32_t pitch;
uint32_t dst_level;
uint32_t width;
uint32_t height;
uint32_t copy_height = 0;
uint32_t dst_layer = 0;
int dst_x;
int dst_y;
int dst_z = 0;
vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor;
};
struct ImageBufferCopy {
uint32_t offset;
uint32_t pitch;
uint32_t src_level;
uint32_t width;
uint32_t height;
uint32_t copy_height = 0;
uint32_t src_layer = 0;
int src_x;
int src_y;
int src_z = 0;
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
uint32_t offset;
uint32_t pitch;
uint32_t src_level;
uint32_t width;
uint32_t height;
uint32_t copy_height = 0;
uint32_t src_layer = 0;
int src_x;
int src_y;
int src_z = 0;
vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor;
};
struct ImageImageCopy {
VulkanImage* src_image;
uint32_t src_level;
uint32_t dst_level;
uint32_t width;
uint32_t height;
uint32_t src_layer = 0;
uint32_t dst_layer = 0;
VkImageAspectFlags src_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
VkImageAspectFlags dst_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
int src_x;
int src_y;
int src_z = 0;
int dst_x;
int dst_y;
int dst_z = 0;
VulkanImage* src_image;
uint32_t src_level;
uint32_t dst_level;
uint32_t width;
uint32_t height;
uint32_t src_layer = 0;
uint32_t dst_layer = 0;
vk::ImageAspectFlags src_aspect = vk::ImageAspectFlagBits::eColor;
vk::ImageAspectFlags dst_aspect = vk::ImageAspectFlagBits::eColor;
int src_x;
int src_y;
int src_z = 0;
int dst_x;
int dst_y;
int dst_z = 0;
};
[[nodiscard]] std::vector<ImageBufferCopy>
MakeLayeredImageBufferCopies(uint32_t layers, uint64_t slice_size, uint32_t pitch, uint32_t width,
uint32_t height,
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT);
uint32_t height,
vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor);
enum class StagingBufferType { Texture, Vertex, ReadBack };
@ -85,28 +85,29 @@ private:
};
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,
VkImageAspectFlags src_aspect, VulkanImage* dst_image,
VkImageAspectFlags dst_aspect, uint32_t bytes_per_element,
uint64_t dst_layout);
vk::ImageAspectFlags src_aspect, VulkanImage* dst_image,
vk::ImageAspectFlags dst_aspect, uint32_t bytes_per_element,
vk::ImageLayout dst_layout);
void UtilBlitPreparedImage(CommandBuffer* buffer, VulkanImage* src_image,
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,
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,
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,
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,
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,
VulkanImage* src_image, uint64_t src_layout,
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT);
VulkanImage* src_image, vk::ImageLayout src_layout,
vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor);
void UtilFillBuffer(GraphicContext* ctx, void* dst_data, uint64_t size,
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,
uint64_t dst_offset, const void* src_data, uint64_t size);
void UtilReleaseCachedResources(GraphicContext* ctx);
@ -117,17 +118,17 @@ bool UtilBufferIsTiled(uint64_t vaddr, uint64_t size);
void UtilSetImageLayoutOptimal(VulkanImage* image);
void UtilResetImageViews(VulkanImage* image);
void UtilCreateImageView(GraphicContext* ctx, VulkanImage* image, int view_index,
VkImageViewType view_type, VkImageAspectFlags aspect_mask,
VkComponentMapping components, uint32_t base_array_layer,
vk::ImageViewType view_type, vk::ImageAspectFlags aspect_mask,
vk::ComponentMapping components, uint32_t base_array_layer,
uint32_t base_mip_level, uint32_t layer_count, uint32_t level_count,
VkFormat view_format = VK_FORMAT_UNDEFINED,
VkImageUsageFlags view_usage = 0);
bool UtilIsBcFormat(VkFormat format);
uint32_t UtilGetBcBlockSize(VkFormat format);
vk::Format view_format = vk::Format::eUndefined,
vk::ImageUsageFlags view_usage = {});
bool UtilIsBcFormat(vk::Format format);
uint32_t UtilGetBcBlockSize(vk::Format format);
void VulkanCreateBuffer(GraphicContext* gctx, uint64_t size, 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);
void VulkanDeleteImage(GraphicContext* gctx, VulkanImage* image, VulkanMemory* memory);
void VulkanDeviceWaitIdle(GraphicContext* ctx);

View File

@ -1,3 +1,5 @@
#include "graphics/host_gpu/vulkanCommon.h"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnullability-completeness"
@ -24,7 +26,6 @@
#include <fmt/format.h>
#include <string>
#include <vector>
#include <vulkan/vk_enum_string_helper.h>
namespace Libs::Graphics {
@ -66,16 +67,21 @@ bool VulkanCreateAllocator(GraphicContext* ctx) {
EXIT_IF(ctx == nullptr || ctx->instance == nullptr || ctx->physical_device == 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 {};
info.instance = ctx->instance;
info.physicalDevice = ctx->physical_device;
info.device = ctx->device;
info.pVulkanFunctions = &functions;
info.vulkanApiVersion = VULKAN_TARGET_API_VERSION;
info.flags = ctx->memory_budget_ext_enabled ? VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT : 0;
const auto result = vmaCreateAllocator(&info, &ctx->allocator);
if (result != VK_SUCCESS) {
LOGF("vmaCreateAllocator failed: %s\n", string_VkResult(result));
const auto result = static_cast<vk::Result>(vmaCreateAllocator(&info, &ctx->allocator));
if (result != vk::Result::eSuccess) {
LOGF("vmaCreateAllocator failed: %s\n", VulkanToString(result).c_str());
return false;
}
return true;
@ -127,11 +133,13 @@ bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* memory) {
}
VmaAllocationCreateInfo info {};
info.requiredFlags = memory->property;
info.requiredFlags = static_cast<vk::MemoryPropertyFlags::MaskType>(memory->property);
memory->unique_id = VulkanNextMemoryUniqueId();
const auto result = vmaAllocateMemory(ctx->allocator, &memory->requirements, &info,
&memory->allocation, &memory->allocation_info);
if (result == VK_SUCCESS) {
const auto result = static_cast<vk::Result>(vmaAllocateMemory(
ctx->allocator,
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->memory = memory->allocation_info.deviceMemory;
memory->offset = memory->allocation_info.offset;
@ -146,7 +154,7 @@ bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* memory) {
g_memory_stats.allocated[i].load()));
}
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;
}
@ -166,7 +174,8 @@ void VulkanMapMemory(GraphicContext* ctx, VulkanMemory* memory, void** data) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(ctx == nullptr || memory == nullptr || data == nullptr || ctx->allocator == 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) {
@ -180,16 +189,18 @@ void VulkanBindImageMemory(GraphicContext* ctx, VulkanImage* image, VulkanMemory
KYTY_PROFILER_FUNCTION();
EXIT_IF(ctx == nullptr || image == nullptr || memory == nullptr || ctx->allocator == nullptr ||
memory->allocation == nullptr);
EXIT_NOT_IMPLEMENTED(vmaBindImageMemory(ctx->allocator, memory->allocation, image->image) !=
VK_SUCCESS);
EXIT_NOT_IMPLEMENTED(
static_cast<vk::Result>(vmaBindImageMemory(ctx->allocator, memory->allocation,
image->image)) != vk::Result::eSuccess);
}
void VulkanBindBufferMemory(GraphicContext* ctx, VulkanBuffer* buffer, VulkanMemory* memory) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(ctx == nullptr || buffer == nullptr || memory == nullptr || ctx->allocator == nullptr ||
memory->allocation == nullptr);
EXIT_NOT_IMPLEMENTED(vmaBindBufferMemory(ctx->allocator, memory->allocation, buffer->buffer) !=
VK_SUCCESS);
EXIT_NOT_IMPLEMENTED(
static_cast<vk::Result>(vmaBindBufferMemory(ctx->allocator, memory->allocation,
buffer->buffer)) != vk::Result::eSuccess);
}
} // namespace Libs::Graphics

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

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_

View File

@ -4,12 +4,12 @@
#include "common/abi.h"
#include "common/common.h"
#include "common/threads.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <map>
#include <mutex>
#include <tuple>
#include <vk_mem_alloc.h>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
@ -19,7 +19,7 @@ struct VulkanQueueInfo {
Common::Mutex* mutex = nullptr;
uint32_t family = static_cast<uint32_t>(-1);
uint32_t index = static_cast<uint32_t>(-1);
VkQueue vk_queue = nullptr;
vk::Queue vk_queue = nullptr;
};
struct VulkanInstance {
@ -33,51 +33,53 @@ struct VulkanInstance {
static constexpr int QUEUE_COMPUTE_START = 0;
static constexpr int QUEUE_COMPUTE_NUM = 8;
VkInstance instance = nullptr;
VkDebugUtilsMessengerEXT debug_messenger = nullptr;
VkPhysicalDevice physical_device = nullptr;
VkPhysicalDeviceProperties physical_device_properties = {};
VkPhysicalDeviceMemoryProperties physical_device_memory_properties = {};
VkDevice device = nullptr;
VmaAllocator allocator = nullptr;
bool memory_budget_ext_enabled = false;
bool subgroup_size_control_enabled = false;
uint32_t subgroup_size = 0;
uint32_t min_subgroup_size = 0;
uint32_t max_subgroup_size = 0;
VkShaderStageFlags required_subgroup_size_stages = 0;
VulkanQueueInfo queues[QUEUES_NUM];
vk::Instance instance = nullptr;
vk::DebugUtilsMessengerEXT debug_messenger = nullptr;
vk::PhysicalDevice physical_device = nullptr;
vk::PhysicalDeviceProperties physical_device_properties = {};
vk::PhysicalDeviceMemoryProperties physical_device_memory_properties = {};
vk::Device device = nullptr;
VmaAllocator allocator = nullptr;
bool memory_budget_ext_enabled = false;
bool rt_extensions_enabled = false;
bool subgroup_size_control_enabled = false;
uint32_t subgroup_size = 0;
uint32_t min_subgroup_size = 0;
uint32_t max_subgroup_size = 0;
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;
}
[[nodiscard]] const VkPhysicalDeviceMemoryProperties&
[[nodiscard]] const vk::PhysicalDeviceMemoryProperties&
GetPhysicalDeviceMemoryProperties() const {
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);
auto [it, inserted] = m_format_properties.try_emplace(format);
if (inserted) {
vkGetPhysicalDeviceFormatProperties(physical_device, format, &it->second);
physical_device.getFormatProperties(format, &it->second);
}
return it->second;
}
[[nodiscard]] VkResult GetImageFormatProperties(VkFormat format, VkImageType type,
VkImageTiling tiling, VkImageUsageFlags usage,
VkImageCreateFlags flags,
VkImageFormatProperties* properties) const {
using Key =
std::tuple<VkFormat, VkImageType, VkImageTiling, VkImageUsageFlags, VkImageCreateFlags>;
[[nodiscard]] vk::Result GetImageFormatProperties(vk::Format format, vk::ImageType type,
vk::ImageTiling tiling,
vk::ImageUsageFlags usage,
vk::ImageCreateFlags flags,
vk::ImageFormatProperties* properties) const {
using Key = std::tuple<vk::Format, vk::ImageType, vk::ImageTiling, vk::ImageUsageFlags,
vk::ImageCreateFlags>;
std::scoped_lock lock(m_image_format_properties_mutex);
auto [it, inserted] =
m_image_format_properties.try_emplace(Key {format, type, tiling, usage, flags});
if (inserted) {
it->second.first = vkGetPhysicalDeviceImageFormatProperties(
physical_device, format, type, tiling, usage, flags, &it->second.second);
it->second.first = physical_device.getImageFormatProperties(format, type, tiling, usage,
flags, &it->second.second);
}
if (properties != nullptr) {
*properties = it->second.second;
@ -85,18 +87,18 @@ struct VulkanInstance {
return it->second.first;
}
[[nodiscard]] VkDeviceSize StorageMinAlignment() const {
[[nodiscard]] vk::DeviceSize StorageMinAlignment() const {
const auto alignment = physical_device_properties.limits.minStorageBufferOffsetAlignment;
return alignment != 0 ? alignment : 1;
}
private:
mutable std::mutex m_format_properties_mutex;
mutable std::map<VkFormat, VkFormatProperties> m_format_properties;
mutable std::mutex m_image_format_properties_mutex;
mutable std::map<
std::tuple<VkFormat, VkImageType, VkImageTiling, VkImageUsageFlags, VkImageCreateFlags>,
std::pair<VkResult, VkImageFormatProperties>>
mutable std::mutex m_format_properties_mutex;
mutable std::map<vk::Format, vk::FormatProperties> m_format_properties;
mutable std::mutex m_image_format_properties_mutex;
mutable std::map<std::tuple<vk::Format, vk::ImageType, vk::ImageTiling, vk::ImageUsageFlags,
vk::ImageCreateFlags>,
std::pair<vk::Result, vk::ImageFormatProperties>>
m_image_format_properties;
};

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_unavailable_log = false;
static RenderDocDevicePointer GetRenderDocDevicePointer(VkInstance instance) {
static RenderDocDevicePointer GetRenderDocDevicePointer(vk::Instance instance) {
if (instance == nullptr) {
return nullptr;
}
return reinterpret_cast<void*>(instance);
return VulkanHandleToPointer(instance);
}
static bool BindRenderDocApi(HMODULE module) {
@ -191,7 +191,7 @@ bool RenderDocIsLoaded() {
return g_api != nullptr;
}
void RenderDocSetActiveWindow(VkInstance instance, SDL_Window* window) {
void RenderDocSetActiveWindow(vk::Instance instance, SDL_Window* window) {
if (g_api == nullptr) {
return;
}
@ -284,7 +284,7 @@ void RenderDocInit() {}
bool RenderDocIsLoaded() {
return false;
}
void RenderDocSetActiveWindow(VkInstance /*instance*/, SDL_Window* /*window*/) {}
void RenderDocSetActiveWindow(vk::Instance /*instance*/, SDL_Window* /*window*/) {}
void RenderDocRequestCapture() {}
void RenderDocOnPresent() {}

View File

@ -2,8 +2,7 @@
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_RENDERDOC_H_
#include "common/common.h"
#include <vulkan/vulkan_core.h>
#include "graphics/host_gpu/vulkanCommon.h"
struct SDL_Window;
@ -11,7 +10,7 @@ namespace Libs::Graphics {
void RenderDocInit();
bool RenderDocIsLoaded();
void RenderDocSetActiveWindow(VkInstance instance, SDL_Window* window);
void RenderDocSetActiveWindow(vk::Instance instance, SDL_Window* window);
void RenderDocRequestCapture();
void RenderDocOnPresent();

View File

@ -3,8 +3,7 @@
#include "common/abi.h"
#include "common/common.h"
struct VkSurfaceCapabilitiesKHR;
#include "graphics/host_gpu/vulkanCommon.h"
namespace Libs::Graphics {
@ -13,7 +12,7 @@ class CommandBuffer;
struct VideoOutVulkanImage;
struct PreparedFrame;
VkSurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities();
vk::SurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities();
GraphicContext* WindowGetGraphicContext();

View File

@ -31,6 +31,7 @@
#include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/renderDoc.h"
#include "graphics/presentation/videoOut.h"
#include "graphics/presentation/window.h"
@ -48,7 +49,6 @@
#include <memory>
#include <string>
#include <vector>
#include <vulkan/vk_enum_string_helper.h>
#include <vulkan/vk_platform.h>
// IWYU pragma: no_include <intrin.h>
@ -66,8 +66,8 @@ struct PreparedFrame {
class PreparedFramePool {
public:
void EnsureCapacity(uint32_t count, VkFormat format) {
if (count == 0 || format == VK_FORMAT_UNDEFINED) {
void EnsureCapacity(uint32_t count, vk::Format format) {
if (count == 0 || format == vk::Format::eUndefined) {
EXIT("prepared-frame pool requires at least one frame\n");
}
Common::LockGuard lock(m_mutex);
@ -79,9 +79,9 @@ public:
}
}
VkFormat GetFormat() {
vk::Format GetFormat() {
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");
}
return m_format;
@ -130,7 +130,7 @@ private:
Common::CondVar m_available;
std::vector<std::unique_ptr<PreparedFrame>> m_frames;
std::deque<PreparedFrame*> m_free;
VkFormat m_format = VK_FORMAT_UNDEFINED;
vk::Format m_format = vk::Format::eUndefined;
};
static PreparedFramePool* GetPreparedFramePool() {
@ -138,10 +138,10 @@ static PreparedFramePool* GetPreparedFramePool() {
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(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,
static_cast<int>(format));
}
@ -163,21 +163,21 @@ static void ConfigurePreparedFrame(PreparedFrame* frame, VkExtent2D extent, VkFo
dst.format = format;
dst.layers = 1;
dst.mip_levels = 1;
dst.layout = VK_IMAGE_LAYOUT_UNDEFINED;
dst.memory.property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
dst.layout = vk::ImageLayout::eUndefined;
dst.memory.property = vk::MemoryPropertyFlagBits::eDeviceLocal;
VkImageCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
create.imageType = VK_IMAGE_TYPE_2D;
vk::ImageCreateInfo create {};
create.sType = vk::StructureType::eImageCreateInfo;
create.imageType = vk::ImageType::e2D;
create.extent = {dst.extent.width, dst.extent.height, 1};
create.mipLevels = 1;
create.arrayLayers = 1;
create.format = dst.format;
create.tiling = VK_IMAGE_TILING_OPTIMAL;
create.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
create.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
create.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
create.samples = VK_SAMPLE_COUNT_1_BIT;
create.tiling = vk::ImageTiling::eOptimal;
create.initialLayout = vk::ImageLayout::eUndefined;
create.usage = vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst;
create.sharingMode = vk::SharingMode::eExclusive;
create.samples = vk::SampleCountFlagBits::e1;
if (!VulkanCreateImage(ctx, &create, &dst, &dst.memory)) {
EXIT("failed to allocate prepared presentation image, extent=%ux%u format=%d\n",
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;
[[maybe_unused]] static VkSwapchainKHR VulkanCreateSwapchainInternal(
VkDevice device, VkSurfaceKHR surface, uint32_t width, uint32_t height, uint32_t image_count,
SurfaceCapabilities* r, VkFormat* swapchain_format, VkExtent2D* swapchain_extent,
std::unique_ptr<VkImage[]>* swapchain_images,
std::unique_ptr<VkImageView[]>* swapchain_image_views, uint32_t* swapchain_images_count) {
[[maybe_unused]] static vk::SwapchainKHR VulkanCreateSwapchainInternal(
vk::Device device, vk::SurfaceKHR surface, uint32_t width, uint32_t height,
uint32_t image_count, SurfaceCapabilities* r, vk::Format* swapchain_format,
vk::Extent2D* swapchain_extent, std::unique_ptr<vk::Image[]>* swapchain_images,
std::unique_ptr<vk::ImageView[]>* swapchain_image_views, uint32_t* swapchain_images_count) {
EXIT_IF(device == nullptr);
EXIT_IF(surface == nullptr);
EXIT_IF(r == nullptr);
@ -202,7 +202,7 @@ VulkanSwapchain::~VulkanSwapchain() = default;
EXIT_NOT_IMPLEMENTED(r->formats.empty());
VkExtent2D extent {};
vk::Extent2D extent {};
extent.width = std::clamp(width, r->capabilities.minImageExtent.width,
r->capabilities.maxImageExtent.width);
extent.height = std::clamp(height, r->capabilities.minImageExtent.height,
@ -211,19 +211,19 @@ VulkanSwapchain::~VulkanSwapchain() = default;
image_count =
std::clamp(image_count, r->capabilities.minImageCount, r->capabilities.maxImageCount);
VkSwapchainCreateInfoKHR create_info {};
create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
vk::SwapchainCreateInfoKHR create_info {};
create_info.sType = vk::StructureType::eSwapchainCreateInfoKHR;
create_info.pNext = nullptr;
create_info.flags = 0;
create_info.flags = {};
create_info.surface = surface;
create_info.minImageCount = image_count;
if (r->format_unorm_bgra32) {
create_info.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
create_info.imageFormat = vk::Format::eB8G8R8A8Unorm;
create_info.imageColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
} else if (r->format_srgb_bgra32) {
create_info.imageFormat = VK_FORMAT_B8G8R8A8_SRGB;
create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
create_info.imageFormat = vk::Format::eB8G8R8A8Srgb;
create_info.imageColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
} else {
const auto& format = r->formats[0];
create_info.imageFormat = format.format;
@ -232,49 +232,50 @@ VulkanSwapchain::~VulkanSwapchain() = default;
create_info.imageExtent = extent;
create_info.imageArrayLayers = 1;
create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
create_info.imageUsage =
vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferDst;
create_info.imageSharingMode = vk::SharingMode::eExclusive;
create_info.queueFamilyIndexCount = 0;
create_info.pQueueFamilyIndices = nullptr;
create_info.preTransform = r->capabilities.currentTransform;
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
create_info.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
create_info.presentMode = vk::PresentModeKHR::eFifo;
create_info.clipped = VK_TRUE;
create_info.oldSwapchain = nullptr;
*swapchain_format = create_info.imageFormat;
*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);
*swapchain_images = std::make_unique<VkImage[]>(*swapchain_images_count);
vkGetSwapchainImagesKHR(device, swapchain, swapchain_images_count, swapchain_images->get());
*swapchain_images = std::make_unique<vk::Image[]>(*swapchain_images_count);
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++) {
VkImageViewCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
vk::ImageViewCreateInfo create_info {};
create_info.sType = vk::StructureType::eImageViewCreateInfo;
create_info.pNext = nullptr;
create_info.flags = 0;
create_info.flags = {};
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.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
create_info.components.r = vk::ComponentSwizzle::eIdentity;
create_info.components.g = vk::ComponentSwizzle::eIdentity;
create_info.components.b = vk::ComponentSwizzle::eIdentity;
create_info.components.a = vk::ComponentSwizzle::eIdentity;
create_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
create_info.subresourceRange.baseArrayLayer = 0;
create_info.subresourceRange.baseMipLevel = 0;
create_info.subresourceRange.layerCount = 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;
@ -302,21 +303,21 @@ VulkanSwapchain* VulkanCreateSwapchain(GraphicContext* ctx, uint32_t image_count
s->current_index = static_cast<uint32_t>(-1);
s->present_frame = 0;
VkSemaphoreCreateInfo semaphore_info {};
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
vk::SemaphoreCreateInfo semaphore_info {};
semaphore_info.sType = vk::StructureType::eSemaphoreCreateInfo;
semaphore_info.pNext = nullptr;
semaphore_info.flags = 0;
semaphore_info.flags = {};
s->image_acquired_semaphores = std::make_unique<VkSemaphore[]>(s->swapchain_images_count);
s->render_complete_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<vk::Semaphore[]>(s->swapchain_images_count);
for (uint32_t i = 0; i < s->swapchain_images_count; i++) {
auto result = vkCreateSemaphore(ctx->device, &semaphore_info, nullptr,
&s->image_acquired_semaphores[i]);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
auto result =
ctx->device.createSemaphore(&semaphore_info, nullptr, &s->image_acquired_semaphores[i]);
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
result = vkCreateSemaphore(ctx->device, &semaphore_info, nullptr,
&s->render_complete_semaphores[i]);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
result = ctx->device.createSemaphore(&semaphore_info, nullptr,
&s->render_complete_semaphores[i]);
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
}
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) {
for (uint32_t i = 0; i < s->swapchain_images_count; i++) {
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) {
for (uint32_t i = 0; i < s->swapchain_images_count; i++) {
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) {
for (uint32_t i = 0; i < s->swapchain_images_count; i++) {
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) {
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) {
KYTY_PROFILER_FUNCTION();
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));
}
@ -405,8 +406,7 @@ PreparedFrame* WindowPrepareFrame(CommandBuffer* buffer, VideoOutVulkanImage* im
ConfigurePreparedFrame(frame, image->extent, image->format);
const std::array copies {ImageImageCopy {
.src_image = image, .width = image->extent.width, .height = image->extent.height}};
UtilImageToImage(buffer, copies, &frame->image,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL));
UtilImageToImage(buffer, copies, &frame->image, vk::ImageLayout::eTransferSrcOptimal);
return frame;
}
@ -419,7 +419,8 @@ PreparedFrame* WindowPrepareBlankFrame(CommandBuffer* buffer, uint32_t width, ui
auto* frame = pool->Acquire();
Common::LockGuard render_lock(g_render_ctx->GetMutex());
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);
return frame;
}
@ -452,18 +453,20 @@ void WindowPresentFrame(PreparedFrame* frame) {
swapchain->current_index = static_cast<uint32_t>(-1);
auto result = vkAcquireNextImageKHR(
g_window_ctx->graphic_ctx.device, swapchain->swapchain, UINT64_MAX,
swapchain->image_acquired_semaphores[present_frame], nullptr, &swapchain->current_index);
auto result = g_window_ctx->graphic_ctx.device.acquireNextImageKHR(
swapchain->swapchain, UINT64_MAX, swapchain->image_acquired_semaphores[present_frame],
nullptr, &swapchain->current_index);
switch (result) {
case VK_SUCCESS: break;
case VK_SUBOPTIMAL_KHR: LOGF("vkAcquireNextImageKHR returned VK_SUBOPTIMAL_KHR\n"); break;
case VK_ERROR_OUT_OF_DATE_KHR:
LOGF("vkAcquireNextImageKHR returned VK_ERROR_OUT_OF_DATE_KHR\n");
case vk::Result::eSuccess: break;
case vk::Result::eSuboptimalKHR:
LOGF("vkAcquireNextImageKHR returned vk::Result::eSuboptimalKHR\n");
break;
case vk::Result::eErrorOutOfDateKHR:
LOGF("vkAcquireNextImageKHR returned vk::Result::eErrorOutOfDateKHR\n");
VulkanRecreateSwapchain();
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));
if (frame->present_commands == nullptr) {
@ -472,41 +475,41 @@ void WindowPresentFrame(PreparedFrame* frame) {
frame->present_commands->WaitForFenceAndReset();
auto& buffer = *frame->present_commands;
auto* vk_buffer = buffer.GetPool()->buffers[buffer.GetIndex()];
auto vk_buffer = buffer.GetPool()->buffers[buffer.GetIndex()];
buffer.Begin();
UtilBlitPreparedImage(&buffer, &frame->image, swapchain);
VkImageMemoryBarrier pre_present_barrier {};
pre_present_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
vk::ImageMemoryBarrier pre_present_barrier {};
pre_present_barrier.sType = vk::StructureType::eImageMemoryBarrier;
pre_present_barrier.pNext = nullptr;
pre_present_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
pre_present_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
pre_present_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
pre_present_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
pre_present_barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
pre_present_barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead;
pre_present_barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal;
pre_present_barrier.newLayout = vk::ImageLayout::ePresentSrcKHR;
pre_present_barrier.srcQueueFamilyIndex = 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.levelCount = 1;
pre_present_barrier.subresourceRange.baseArrayLayer = 0;
pre_present_barrier.subresourceRange.layerCount = 1;
pre_present_barrier.image = swapchain->swapchain_images[swapchain->current_index];
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1,
&pre_present_barrier);
vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eBottomOfPipe, vk::DependencyFlags {}, 0,
nullptr, 0, nullptr, 1, &pre_present_barrier);
buffer.End();
auto render_complete_semaphore =
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,
render_complete_semaphore);
VkPresentInfoKHR present;
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
vk::PresentInfoKHR present;
present.sType = vk::StructureType::ePresentInfoKHR;
present.pNext = nullptr;
present.swapchainCount = 1;
present.pSwapchains = &swapchain->swapchain;
@ -520,18 +523,20 @@ void WindowPresentFrame(PreparedFrame* frame) {
if (queue.mutex != nullptr) {
queue.mutex->Lock();
}
result = vkQueuePresentKHR(queue.vk_queue, &present);
result = queue.vk_queue.presentKHR(&present);
if (queue.mutex != nullptr) {
queue.mutex->Unlock();
}
switch (result) {
case VK_SUCCESS: break;
case VK_SUBOPTIMAL_KHR: LOGF("vkQueuePresentKHR returned VK_SUBOPTIMAL_KHR\n"); break;
case VK_ERROR_OUT_OF_DATE_KHR:
LOGF("vkQueuePresentKHR returned VK_ERROR_OUT_OF_DATE_KHR\n");
case vk::Result::eSuccess: break;
case vk::Result::eSuboptimalKHR:
LOGF("vkQueuePresentKHR returned vk::Result::eSuboptimalKHR\n");
break;
case vk::Result::eErrorOutOfDateKHR:
LOGF("vkQueuePresentKHR returned vk::Result::eErrorOutOfDateKHR\n");
VulkanRecreateSwapchain();
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;

View File

@ -30,6 +30,7 @@
#include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/renderDoc.h"
#include "graphics/presentation/videoOut.h"
#include "graphics/presentation/window.h"
@ -45,7 +46,6 @@
#include <memory>
#include <string>
#include <vector>
#include <vulkan/vk_enum_string_helper.h>
#include <vulkan/vk_platform.h>
// IWYU pragma: no_include <intrin.h>
@ -58,13 +58,13 @@ namespace Libs::Graphics {
struct VulkanExtensions {
bool enable_validation_layers = false;
std::vector<const char*> required_extensions;
std::vector<VkExtensionProperties> available_extensions;
std::vector<const char*> required_layers;
std::vector<VkLayerProperties> available_layers;
std::vector<const char*> required_extensions;
std::vector<vk::ExtensionProperties> available_extensions;
std::vector<const char*> required_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(),
[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; });
}
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(),
[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) {
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &r->capabilities);
physical_device.getSurfaceCapabilitiesKHR(surface, &r->capabilities);
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);
r->formats = std::vector<VkSurfaceFormatKHR>(formats_count); // @suppress("Ambiguous problem")
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &formats_count,
r->formats.data());
r->formats = std::vector<vk::SurfaceFormatKHR>(formats_count); // @suppress("Ambiguous problem")
physical_device.getSurfaceFormatsKHR(surface, &formats_count, r->formats.data());
uint32_t present_modes_count = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count,
nullptr);
physical_device.getSurfacePresentModesKHR(surface, &present_modes_count, nullptr);
EXIT_NOT_IMPLEMENTED(present_modes_count == 0);
r->present_modes =
std::vector<VkPresentModeKHR>(present_modes_count); // @suppress("Ambiguous problem")
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count,
std::vector<vk::PresentModeKHR>(present_modes_count); // @suppress("Ambiguous problem")
physical_device.getSurfacePresentModesKHR(surface, &present_modes_count,
r->present_modes.data());
r->format_srgb_bgra32 = false;
for (const auto& f: r->formats) {
if (f.format == VK_FORMAT_B8G8R8A8_SRGB &&
f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
if (f.format == vk::Format::eB8G8R8A8Srgb &&
f.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
r->format_srgb_bgra32 = true;
break;
}
if (f.format == VK_FORMAT_B8G8R8A8_UNORM &&
f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
if (f.format == vk::Format::eB8G8R8A8Unorm &&
f.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
r->format_unorm_bgra32 = true;
break;
}
}
}
static bool CheckFormat(VkPhysicalDevice device, VkFormat format, bool tile,
VkFormatFeatureFlags features) {
VkFormatProperties format_props {};
vkGetPhysicalDeviceFormatProperties(device, format, &format_props);
static bool CheckFormat(vk::PhysicalDevice device, vk::Format format, bool tile,
vk::FormatFeatureFlags features) {
vk::FormatProperties format_props {};
device.getFormatProperties(format, &format_props);
const auto supported_features =
(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 transfer_num, uint32_t present_num) {
EXIT_IF(device == nullptr);
@ -184,28 +182,28 @@ static VulkanQueues VulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surfa
VulkanQueues qs;
uint32_t queue_family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, nullptr);
std::vector<VkQueueFamilyProperties> queue_families(queue_family_count);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families.data());
device.getQueueFamilyProperties(&queue_family_count, nullptr);
std::vector<vk::QueueFamilyProperties> queue_families(queue_family_count);
device.getQueueFamilyProperties(&queue_family_count, queue_families.data());
qs.family_count = queue_family_count;
uint32_t family = 0;
for (auto& f: queue_families) {
VkBool32 presentation_supported = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(device, family, surface, &presentation_supported);
vk::Bool32 presentation_supported = VK_FALSE;
device.getSurfaceSupportKHR(family, surface, &presentation_supported);
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"));
for (uint32_t i = 0; i < f.queueCount; i++) {
QueueInfo info;
info.family = family;
info.index = i;
info.graphics = (f.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0;
info.compute = (f.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0;
info.transfer = (f.queueFlags & VK_QUEUE_TRANSFER_BIT) != 0;
info.graphics = static_cast<bool>(f.queueFlags & vk::QueueFlagBits::eGraphics);
info.compute = static_cast<bool>(f.queueFlags & vk::QueueFlagBits::eCompute);
info.transfer = static_cast<bool>(f.queueFlags & vk::QueueFlagBits::eTransfer);
info.present = (presentation_supported == VK_TRUE);
qs.available.push_back(info);
@ -253,10 +251,10 @@ static VulkanQueues VulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surfa
}
// 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,
SurfaceCapabilities* out_capabilities,
VkPhysicalDevice* out_device, VulkanQueues* out_queues) {
vk::PhysicalDevice* out_device, VulkanQueues* out_queues) {
EXIT_IF(instance == nullptr);
EXIT_IF(surface == nullptr);
EXIT_IF(out_capabilities == nullptr);
@ -264,23 +262,23 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
EXIT_IF(out_queues == nullptr);
uint32_t devices_count = 0;
vkEnumeratePhysicalDevices(instance, &devices_count, nullptr);
instance.enumeratePhysicalDevices(&devices_count, nullptr);
EXIT_NOT_IMPLEMENTED(devices_count == 0);
std::vector<VkPhysicalDevice> devices(devices_count);
vkEnumeratePhysicalDevices(instance, &devices_count, devices.data());
std::vector<vk::PhysicalDevice> devices(devices_count);
instance.enumeratePhysicalDevices(&devices_count, devices.data());
VkPhysicalDevice best_device = nullptr;
VulkanQueues best_queues;
vk::PhysicalDevice best_device = nullptr;
VulkanQueues best_queues;
for (const auto& device: devices) {
bool skip_device = false;
VkPhysicalDeviceProperties device_properties {};
vkGetPhysicalDeviceProperties(device, &device_properties);
vk::PhysicalDeviceProperties 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) {
LOGF("Vulkan %u.%u is required, but device supports only %u.%u.%u\n",
VK_VERSION_MAJOR(VULKAN_TARGET_API_VERSION),
@ -291,30 +289,29 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
continue;
}
VkPhysicalDeviceFeatures2 device_features2 {};
vk::PhysicalDeviceFeatures2 device_features2 {};
VkPhysicalDeviceVulkan13Features features13 {};
features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
vk::PhysicalDeviceVulkan13Features features13 {};
features13.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
features13.pNext = nullptr;
VkPhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {};
color_write_ext.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT;
vk::PhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {};
color_write_ext.sType = vk::StructureType::ePhysicalDeviceColorWriteEnableFeaturesEXT;
color_write_ext.pNext = nullptr;
VkPhysicalDeviceDepthClipControlFeaturesEXT depth_clip_control {};
depth_clip_control.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT;
vk::PhysicalDeviceDepthClipControlFeaturesEXT depth_clip_control {};
depth_clip_control.sType = vk::StructureType::ePhysicalDeviceDepthClipControlFeaturesEXT;
depth_clip_control.pNext = &color_write_ext;
VkPhysicalDeviceVulkan12Features features12 {};
features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
vk::PhysicalDeviceVulkan12Features features12 {};
features12.sType = vk::StructureType::ePhysicalDeviceVulkan12Features;
features12.pNext = &depth_clip_control;
features13.pNext = &features12;
device_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
device_features2.sType = vk::StructureType::ePhysicalDeviceFeatures2;
device_features2.pNext = &features13;
vkGetPhysicalDeviceFeatures2(device, &device_features2);
device.getFeatures2(&device_features2);
auto qs = VulkanFindQueues(
device, surface, GraphicContext::QUEUE_GFX_NUM, GraphicContext::QUEUE_COMPUTE_NUM,
@ -391,13 +388,13 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
if (!skip_device) {
uint32_t extensions_count = 0;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensions_count, nullptr);
device.enumerateDeviceExtensionProperties(nullptr, &extensions_count, nullptr);
EXIT_NOT_IMPLEMENTED(extensions_count == 0);
std::vector<VkExtensionProperties> available_extensions(extensions_count);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensions_count,
available_extensions.data());
std::vector<vk::ExtensionProperties> available_extensions(extensions_count);
device.enumerateDeviceExtensionProperties(nullptr, &extensions_count,
available_extensions.data());
for (const char* ext: device_extensions) {
if (!HasExtension(available_extensions, ext)) {
@ -408,7 +405,7 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
if (skip_device) {
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);
}
}
@ -417,87 +414,87 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
if (!skip_device) {
VulkanGetSurfaceCapabilities(device, surface, out_capabilities);
if ((out_capabilities->capabilities.supportedUsageFlags &
VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) {
if (!(out_capabilities->capabilities.supportedUsageFlags &
vk::ImageUsageFlagBits::eTransferDst)) {
LOGF("Surface cannot be destination of blit\n");
skip_device = true;
}
}
if (!skip_device &&
!CheckFormat(device, VK_FORMAT_R8G8B8A8_SRGB, false, VK_FORMAT_FEATURE_BLIT_SRC_BIT)) {
LOGF("Format VK_FORMAT_R8G8B8A8_SRGB cannot be used as transfer source\n");
if (!skip_device && !CheckFormat(device, vk::Format::eR8G8B8A8Srgb, false,
vk::FormatFeatureFlagBits::eBlitSrc)) {
LOGF("Format vk::Format::eR8G8B8A8Srgb cannot be used as transfer source\n");
skip_device = true;
}
if (!skip_device && !CheckFormat(device, VK_FORMAT_D32_SFLOAT, true,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
LOGF("Format VK_FORMAT_D32_SFLOAT cannot be used as depth buffer\n");
if (!skip_device && !CheckFormat(device, vk::Format::eD32Sfloat, true,
vk::FormatFeatureFlagBits::eDepthStencilAttachment)) {
LOGF("Format vk::Format::eD32Sfloat cannot be used as depth buffer\n");
skip_device = true;
}
if (!skip_device && !CheckFormat(device, VK_FORMAT_D32_SFLOAT_S8_UINT, true,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
LOGF("Format VK_FORMAT_D32_SFLOAT_S8_UINT cannot be used as depth buffer\n");
if (!skip_device && !CheckFormat(device, vk::Format::eD32SfloatS8Uint, true,
vk::FormatFeatureFlagBits::eDepthStencilAttachment)) {
LOGF("Format vk::Format::eD32SfloatS8Uint cannot be used as depth buffer\n");
skip_device = true;
}
if (!skip_device && !CheckFormat(device, VK_FORMAT_D16_UNORM, true,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
LOGF("Format VK_FORMAT_D16_UNORM cannot be used as depth buffer\n");
if (!skip_device && !CheckFormat(device, vk::Format::eD16Unorm, true,
vk::FormatFeatureFlagBits::eDepthStencilAttachment)) {
LOGF("Format vk::Format::eD16Unorm cannot be used as depth buffer\n");
skip_device = true;
}
if (!skip_device && !CheckFormat(device, VK_FORMAT_BC3_SRGB_BLOCK, true,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
LOGF("Format VK_FORMAT_BC3_SRGB_BLOCK cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, vk::Format::eBc3SrgbBlock, true,
vk::FormatFeatureFlagBits::eSampledImage |
vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format vk::Format::eBc3SrgbBlock cannot be used as texture\n");
skip_device = true;
}
if (!skip_device && !CheckFormat(device, VK_FORMAT_R8G8B8A8_SRGB, true,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
LOGF("Format VK_FORMAT_R8G8B8A8_SRGB cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, vk::Format::eR8G8B8A8Srgb, true,
vk::FormatFeatureFlagBits::eSampledImage |
vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format vk::Format::eR8G8B8A8Srgb cannot be used as texture\n");
skip_device = true;
}
if (!skip_device && !CheckFormat(device, VK_FORMAT_R8_UNORM, true,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
LOGF("Format VK_FORMAT_R8_UNORM cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, vk::Format::eR8Unorm, true,
vk::FormatFeatureFlagBits::eSampledImage |
vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format vk::Format::eR8Unorm cannot be used as texture\n");
skip_device = true;
}
if (!skip_device && !CheckFormat(device, VK_FORMAT_R8G8_UNORM, true,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
LOGF("Format VK_FORMAT_R8G8_UNORM cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, vk::Format::eR8G8Unorm, true,
vk::FormatFeatureFlagBits::eSampledImage |
vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format vk::Format::eR8G8Unorm cannot be used as texture\n");
skip_device = true;
}
if (!skip_device && !CheckFormat(device, VK_FORMAT_R8G8B8A8_SRGB, true,
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
LOGF("Format VK_FORMAT_R8G8B8A8_SRGB cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, vk::Format::eR8G8B8A8Srgb, true,
vk::FormatFeatureFlagBits::eStorageImage |
vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format vk::Format::eR8G8B8A8Srgb cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, VK_FORMAT_R8G8B8A8_UNORM, true,
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
LOGF("Format VK_FORMAT_R8G8B8A8_UNORM cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, vk::Format::eR8G8B8A8Unorm, true,
vk::FormatFeatureFlagBits::eStorageImage |
vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format vk::Format::eR8G8B8A8Unorm cannot be used as texture\n");
skip_device = true;
}
}
if (!skip_device && !CheckFormat(device, VK_FORMAT_B8G8R8A8_SRGB, true,
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
LOGF("Format VK_FORMAT_B8G8R8A8_SRGB cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, vk::Format::eB8G8R8A8Srgb, true,
vk::FormatFeatureFlagBits::eStorageImage |
vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format vk::Format::eB8G8R8A8Srgb cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, VK_FORMAT_B8G8R8A8_UNORM, true,
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
LOGF("Format VK_FORMAT_B8G8R8A8_UNORM cannot be used as texture\n");
if (!skip_device && !CheckFormat(device, vk::Format::eB8G8R8A8Unorm, true,
vk::FormatFeatureFlagBits::eStorageImage |
vk::FormatFeatureFlagBits::eTransferDst)) {
LOGF("Format vk::Format::eB8G8R8A8Unorm cannot be used as texture\n");
skip_device = true;
}
}
@ -512,7 +509,7 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
}
if (best_device == nullptr ||
device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
device_properties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
best_device = device;
best_queues = qs;
}
@ -522,34 +519,33 @@ static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface,
*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(ctx == nullptr);
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control {};
subgroup_size_control.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES;
vk::PhysicalDeviceSubgroupSizeControlProperties subgroup_size_control {};
subgroup_size_control.sType = vk::StructureType::ePhysicalDeviceSubgroupSizeControlProperties;
subgroup_size_control.pNext = nullptr;
VkPhysicalDeviceVulkan11Properties properties11 {};
properties11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES;
vk::PhysicalDeviceVulkan11Properties properties11 {};
properties11.sType = vk::StructureType::ePhysicalDeviceVulkan11Properties;
properties11.pNext = &subgroup_size_control;
VkPhysicalDeviceProperties2 properties2 {};
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
vk::PhysicalDeviceProperties2 properties2 {};
properties2.sType = vk::StructureType::ePhysicalDeviceProperties2;
properties2.pNext = &properties11;
vkGetPhysicalDeviceProperties2(physical_device, &properties2);
physical_device.getProperties2(&properties2);
VkPhysicalDeviceVulkan13Features features13 {};
features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
vk::PhysicalDeviceVulkan13Features features13 {};
features13.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
features13.pNext = nullptr;
VkPhysicalDeviceFeatures2 features2 {};
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
vk::PhysicalDeviceFeatures2 features2 {};
features2.sType = vk::StructureType::ePhysicalDeviceFeatures2;
features2.pNext = &features13;
vkGetPhysicalDeviceFeatures2(physical_device, &features2);
physical_device.getFeatures2(&features2);
ctx->subgroup_size = properties11.subgroupSize;
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",
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,
const VulkanExtensions* r, const VulkanQueues& queues,
const std::vector<const char*>& device_extensions,
const GraphicContext* ctx) {
static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, vk::SurfaceKHR surface,
const VulkanExtensions* r, const VulkanQueues& queues,
const std::vector<const char*>& device_extensions,
const GraphicContext* ctx) {
EXIT_IF(physical_device == nullptr);
EXIT_IF(r == nullptr);
EXIT_IF(surface == nullptr);
EXIT_IF(ctx == nullptr);
std::vector<VkDeviceQueueCreateInfo> queue_create_info(queues.family_count);
std::vector<std::vector<float>> queue_priority(queues.family_count);
uint32_t queue_create_info_num = 0;
std::vector<vk::DeviceQueueCreateInfo> queue_create_info(queues.family_count);
std::vector<std::vector<float>> queue_priority(queues.family_count);
uint32_t queue_create_info_num = 0;
for (uint32_t i = 0; i < queues.family_count; i++) {
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 =
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].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].queueCount = queues.family_used[i];
queue_create_info[queue_create_info_num].pQueuePriorities =
@ -596,45 +593,45 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
}
}
VkPhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {};
color_write_ext.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT;
vk::PhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {};
color_write_ext.sType = vk::StructureType::ePhysicalDeviceColorWriteEnableFeaturesEXT;
color_write_ext.pNext = nullptr;
color_write_ext.colorWriteEnable = VK_TRUE;
VkPhysicalDeviceDepthClipControlFeaturesEXT depth_clip_control {};
depth_clip_control.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT;
vk::PhysicalDeviceDepthClipControlFeaturesEXT depth_clip_control {};
depth_clip_control.sType = vk::StructureType::ePhysicalDeviceDepthClipControlFeaturesEXT;
depth_clip_control.pNext = &color_write_ext;
depth_clip_control.depthClipControl = VK_TRUE;
VkPhysicalDeviceVulkan12Features features12 {};
features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
vk::PhysicalDeviceVulkan12Features features12 {};
features12.sType = vk::StructureType::ePhysicalDeviceVulkan12Features;
features12.pNext = &depth_clip_control;
features12.samplerMirrorClampToEdge = VK_TRUE;
VkPhysicalDeviceSubgroupSizeControlFeatures subgroup_size_control {};
subgroup_size_control.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES;
vk::PhysicalDeviceSubgroupSizeControlFeatures subgroup_size_control {};
subgroup_size_control.sType = vk::StructureType::ePhysicalDeviceSubgroupSizeControlFeatures;
subgroup_size_control.pNext = &features12;
VkPhysicalDeviceVulkan13Features supported_features13 {};
supported_features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
vk::PhysicalDeviceVulkan13Features supported_features13 {};
supported_features13.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
supported_features13.pNext = nullptr;
const auto robustness2_ext_enabled =
HasExtension(device_extensions, VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
VkPhysicalDeviceRobustness2FeaturesEXT supported_robustness2 {};
supported_robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
vk::PhysicalDeviceRobustness2FeaturesEXT supported_robustness2 {};
supported_robustness2.sType = vk::StructureType::ePhysicalDeviceRobustness2FeaturesEXT;
supported_robustness2.pNext = nullptr;
if (robustness2_ext_enabled) {
supported_features13.pNext = &supported_robustness2;
}
VkPhysicalDeviceFeatures2 supported_features2 {};
supported_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
vk::PhysicalDeviceFeatures2 supported_features2 {};
supported_features2.sType = vk::StructureType::ePhysicalDeviceFeatures2;
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.samplerAnisotropy = 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*>(&features12));
VkPhysicalDeviceRobustness2FeaturesEXT robustness2 {};
robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
vk::PhysicalDeviceRobustness2FeaturesEXT robustness2 {};
robustness2.sType = vk::StructureType::ePhysicalDeviceRobustness2FeaturesEXT;
robustness2.pNext = const_cast<void*>(base_feature_chain);
if (robustness2_ext_enabled) {
robustness2.robustBufferAccess2 = supported_robustness2.robustBufferAccess2;
@ -664,8 +661,8 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
robustness2.nullDescriptor = supported_robustness2.nullDescriptor;
}
VkPhysicalDeviceVulkan13Features features13 {};
features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
vk::PhysicalDeviceVulkan13Features features13 {};
features13.sType = vk::StructureType::ePhysicalDeviceVulkan13Features;
features13.pNext =
robustness2_ext_enabled ? &robustness2 : const_cast<void*>(base_feature_chain);
features13.robustImageAccess = supported_features13.robustImageAccess;
@ -674,10 +671,10 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
features13.robustImageAccess == VK_TRUE ? "true" : "false",
robustness2_ext_enabled && robustness2.robustImageAccess2 == VK_TRUE ? "true" : "false");
VkDeviceCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
vk::DeviceCreateInfo create_info {};
create_info.sType = vk::StructureType::eDeviceCreateInfo;
create_info.pNext = &features13;
create_info.flags = 0;
create_info.flags = {};
create_info.pQueueCreateInfos = queue_create_info.data();
create_info.queueCreateInfoCount = queue_create_info_num;
create_info.enabledLayerCount =
@ -688,11 +685,11 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
create_info.ppEnabledExtensionNames = device_extensions.data();
create_info.pEnabledFeatures = &device_features;
VkDevice device = nullptr;
vk::Device device = nullptr;
auto result = vkCreateDevice(physical_device, &create_info, nullptr, &device);
if (result != VK_SUCCESS) {
LOGF("vkCreateDevice failed: %s\n", string_VkResult(result));
auto result = physical_device.createDevice(&create_info, nullptr, &device);
if (result != vk::Result::eSuccess) {
LOGF("vkCreateDevice failed: %s\n", VulkanToString(result).c_str());
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 != 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")
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,
r->available_extensions.data());
vk::enumerateInstanceExtensionProperties(nullptr, &available_extensions_count,
r->available_extensions.data());
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) {
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 =
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,
sizeof(VkLayerProperties) * r->available_layers.size());
vkEnumerateInstanceLayerProperties(&available_layers_count, r->available_layers.data());
sizeof(vk::LayerProperties) * r->available_layers.size());
vk::enumerateInstanceLayerProperties(&available_layers_count, r->available_layers.data());
EXIT_NOT_IMPLEMENTED(available_layers_count != r->available_layers.size());
for (const auto& l: r->available_layers) {
LOGF("Vulkan available layer: %s, specVersion = %u, implVersion = %u, %s\n", l.layerName,
l.specVersion, l.implementationVersion, l.description);
LOGF("Vulkan available layer: %s, specVersion = %u, implVersion = %u, %s\n",
l.layerName.data(), l.specVersion, l.implementationVersion, l.description.data());
}
r->required_layers = {"VK_LAYER_KHRONOS_validation"};
@ -780,18 +778,18 @@ static void VulkanGetExtensions(SDL_Window* window, VulkanExtensions* r) {
}
if (r->enable_validation_layers) {
vkEnumerateInstanceExtensionProperties("VK_LAYER_KHRONOS_validation",
&available_extensions_count, nullptr);
vk::enumerateInstanceExtensionProperties("VK_LAYER_KHRONOS_validation",
&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",
&available_extensions_count,
available_extensions.data());
vk::enumerateInstanceExtensionProperties("VK_LAYER_KHRONOS_validation",
&available_extensions_count,
available_extensions.data());
for (const auto& ext: available_extensions) {
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)) {
@ -802,10 +800,10 @@ static void VulkanGetExtensions(SDL_Window* window, VulkanExtensions* r) {
}
}
static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugMessengerCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
VkDebugUtilsMessageTypeFlagsEXT message_types,
const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* /*user_data*/) {
static VKAPI_ATTR vk::Bool32 VKAPI_CALL VulkanDebugMessengerCallback(
vk::DebugUtilsMessageSeverityFlagBitsEXT message_severity,
vk::DebugUtilsMessageTypeFlagsEXT message_types,
const vk::DebugUtilsMessengerCallbackDataEXT* callback_data, void* /*user_data*/) {
EXIT_IF(callback_data == nullptr);
EXIT_IF(callback_data->pMessage == nullptr);
@ -815,13 +813,13 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugMessengerCallback(
bool error = false;
bool debug_printf = false;
switch (message_severity) {
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose:
severity_str = "V";
severity_style = Log::Color::BrightWhite;
skip = true;
break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
if ((message_types & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) != 0 &&
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo:
if ((message_types & vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation) &&
Config::SpirvDebugPrintfEnabled() && callback_data->pMessageIdName != nullptr &&
strcmp(callback_data->pMessageIdName, "UNASSIGNED-DEBUG-PRINTF") == 0) {
debug_printf = true;
@ -833,16 +831,17 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugMessengerCallback(
skip = true;
}
break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning:
severity_str = "W";
severity_style = Log::Color::Red;
break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eError:
severity_str = "E";
severity_style = Log::Color::BrightRed;
// Only validation errors are fatal; GENERAL-type errors can come
// 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;
default: severity_str = "?";
}
@ -867,17 +866,15 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugMessengerCallback(
return VK_FALSE;
}
static VKAPI_ATTR VkResult VKAPI_CALL VulkanCreateDebugUtilsMessengerEXT(
VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* create_info,
const VkAllocationCallbacks* allocator, VkDebugUtilsMessengerEXT* messenger) {
static VKAPI_ATTR vk::Result VKAPI_CALL VulkanCreateDebugUtilsMessengerEXT(
vk::Instance instance, const vk::DebugUtilsMessengerCreateInfoEXT* create_info,
const vk::AllocationCallbacks* allocator, vk::DebugUtilsMessengerEXT* messenger) {
EXIT_IF(instance == nullptr);
if (auto func = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(
vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"));
func != nullptr) {
return func(instance, create_info, allocator, messenger);
if (auto func = VULKAN_HPP_DEFAULT_DISPATCHER.vkCreateDebugUtilsMessengerEXT; func != nullptr) {
return instance.createDebugUtilsMessengerEXT(create_info, allocator, messenger);
}
return VK_ERROR_EXTENSION_NOT_PRESENT;
return vk::Result::eErrorExtensionNotPresent;
}
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].index = info.index;
EXIT_IF(ctx->queues[id].vk_queue != nullptr);
vkGetDeviceQueue(ctx->device, ctx->queues[id].family, ctx->queues[id].index,
&ctx->queues[id].vk_queue);
ctx->device.getQueue(ctx->queues[id].family, ctx->queues[id].index,
&ctx->queues[id].vk_queue);
EXIT_NOT_IMPLEMENTED(ctx->queues[id].vk_queue == nullptr);
if (with_mutex) {
ctx->queues[id].mutex = new Common::Mutex;
@ -947,12 +944,10 @@ static void VulkanCreateQueues(GraphicContext* ctx, const VulkanQueues& queues)
static void VulkanCheckInstanceVersion() {
uint32_t version = VK_API_VERSION_1_0;
auto enumerate_instance_version = reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
if (enumerate_instance_version != nullptr) {
auto result = enumerate_instance_version(&version);
if (result != VK_SUCCESS) {
EXIT("Could not query Vulkan loader version: %s\n", string_VkResult(result));
if (VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceVersion != nullptr) {
auto result = vk::enumerateInstanceVersion(&version);
if (result != vk::Result::eSuccess) {
EXIT("Could not query Vulkan loader version: %s\n", VulkanToString(result).c_str());
}
}
@ -973,12 +968,19 @@ void VulkanCreate(WindowContext* ctx) {
EXIT_IF(ctx->graphic_ctx.device != 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;
VulkanGetExtensions(ctx->window, &r);
VulkanCheckInstanceVersion();
VkApplicationInfo app_info {};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
vk::ApplicationInfo app_info {};
app_info.sType = vk::StructureType::eApplicationInfo;
app_info.pNext = nullptr;
app_info.pApplicationName = "Kyty";
app_info.applicationVersion = 1;
@ -986,17 +988,17 @@ void VulkanCreate(WindowContext* ctx) {
app_info.engineVersion = 1;
app_info.apiVersion = VULKAN_TARGET_API_VERSION; // NOLINT
VkValidationFeatureEnableEXT enabled_features[] = {
vk::ValidationFeatureEnableEXT enabled_features[] = {
#ifdef KYTY_ENABLE_BEST_PRACTICES
VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
vk::ValidationFeatureEnableEXT::eBestPractices,
#endif
#ifdef KYTY_ENABLE_DEBUG_PRINTF
VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
vk::ValidationFeatureEnableEXT::eDebugPrintf,
#endif
};
uint32_t enabled_features_count =
sizeof(enabled_features) / sizeof(VkValidationFeatureEnableEXT);
sizeof(enabled_features) / sizeof(vk::ValidationFeatureEnableEXT);
#ifdef KYTY_ENABLE_DEBUG_PRINTF
if (!Config::SpirvDebugPrintfEnabled()) {
@ -1004,34 +1006,32 @@ void VulkanCreate(WindowContext* ctx) {
}
#endif
VkValidationFeaturesEXT validation_features {};
validation_features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
vk::ValidationFeaturesEXT validation_features {};
validation_features.sType = vk::StructureType::eValidationFeaturesEXT;
validation_features.pNext = nullptr;
validation_features.enabledValidationFeatureCount = enabled_features_count;
validation_features.pEnabledValidationFeatures = enabled_features;
validation_features.disabledValidationFeatureCount = 0;
validation_features.pDisabledValidationFeatures = nullptr;
VkDebugUtilsMessengerCreateInfoEXT dbg_create_info {};
dbg_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
dbg_create_info.pNext = &validation_features;
dbg_create_info.flags = 0;
dbg_create_info.messageSeverity =
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) |
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) |
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) |
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT);
dbg_create_info.messageType =
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) |
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) |
static_cast<uint32_t>(VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT);
vk::DebugUtilsMessengerCreateInfoEXT dbg_create_info {};
dbg_create_info.sType = vk::StructureType::eDebugUtilsMessengerCreateInfoEXT;
dbg_create_info.pNext = &validation_features;
dbg_create_info.flags = {};
dbg_create_info.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError;
dbg_create_info.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance;
dbg_create_info.pfnUserCallback = VulkanDebugMessengerCallback;
dbg_create_info.pUserData = nullptr;
VkInstanceCreateInfo inst_info {};
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
vk::InstanceCreateInfo inst_info {};
inst_info.sType = vk::StructureType::eInstanceCreateInfo;
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.enabledExtensionCount = static_cast<uint32_t>(r.required_extensions.size());
inst_info.ppEnabledExtensionNames = r.required_extensions.data();
@ -1040,25 +1040,31 @@ void VulkanCreate(WindowContext* ctx) {
inst_info.ppEnabledLayerNames =
(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) {
case VK_SUCCESS: break;
case VK_ERROR_INCOMPATIBLE_DRIVER: EXIT("Unable to find a compatible Vulkan Driver");
case vk::Result::eSuccess: break;
case vk::Result::eErrorIncompatibleDriver:
EXIT("Unable to find a compatible Vulkan Driver");
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) {
dbg_create_info.pNext = 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");
}
}
if (SDL_Vulkan_CreateSurface(ctx->window, ctx->graphic_ctx.instance, &ctx->surface) ==
SDL_FALSE) {
vk::SurfaceKHR::CType native_surface = VK_NULL_HANDLE;
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");
}
ctx->surface = native_surface;
std::vector<const char*> device_extensions = {
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");
}
vkGetPhysicalDeviceProperties(ctx->graphic_ctx.physical_device,
&ctx->graphic_ctx.physical_device_properties);
vkGetPhysicalDeviceMemoryProperties(ctx->graphic_ctx.physical_device,
&ctx->graphic_ctx.physical_device_memory_properties);
ctx->graphic_ctx.physical_device.getProperties(&ctx->graphic_ctx.physical_device_properties);
ctx->graphic_ctx.physical_device.getMemoryProperties(
&ctx->graphic_ctx.physical_device_memory_properties);
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;
vkEnumerateDeviceExtensionProperties(ctx->graphic_ctx.physical_device, nullptr,
&extensions_count, nullptr);
ctx->graphic_ctx.physical_device.enumerateDeviceExtensionProperties(
nullptr, &extensions_count, nullptr);
std::vector<VkExtensionProperties> available_extensions(extensions_count);
vkEnumerateDeviceExtensionProperties(ctx->graphic_ctx.physical_device, nullptr,
&extensions_count, available_extensions.data());
std::vector<vk::ExtensionProperties> available_extensions(extensions_count);
ctx->graphic_ctx.physical_device.enumerateDeviceExtensionProperties(
nullptr, &extensions_count, available_extensions.data());
if (HasExtension(available_extensions, 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) {
EXIT("Could not create device");
}
VULKAN_HPP_DEFAULT_DISPATCHER.init(ctx->graphic_ctx.device);
if (!VulkanCreateAllocator(&ctx->graphic_ctx)) {
EXIT("Could not create Vulkan memory allocator");

View File

@ -32,6 +32,7 @@
#include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "graphics/presentation/renderDoc.h"
#include "graphics/presentation/videoOut.h"
#include "graphics/presentation/window/windowInternal.h"
@ -45,7 +46,6 @@
#include <memory>
#include <string>
#include <vector>
#include <vulkan/vk_enum_string_helper.h>
#include <vulkan/vk_platform.h>
#define STB_IMAGE_IMPLEMENTATION
@ -1035,7 +1035,7 @@ void WindowRun() {
std::_Exit(0);
}
VkSurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities() {
vk::SurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities() {
EXIT_IF(g_window_ctx == nullptr);
Common::LockGuard lock(g_window_ctx->mutex);

View File

@ -4,21 +4,21 @@
#include "SDL_video.h"
#include "common/threads.h"
#include "graphics/host_gpu/graphicContext.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include <cstdint>
#include <vector>
#include <vulkan/vulkan_core.h>
namespace Libs::Graphics {
struct WindowGame;
struct SurfaceCapabilities {
VkSurfaceCapabilitiesKHR capabilities {};
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> present_modes;
bool format_srgb_bgra32 = false;
bool format_unorm_bgra32 = false;
vk::SurfaceCapabilitiesKHR capabilities {};
std::vector<vk::SurfaceFormatKHR> formats;
std::vector<vk::PresentModeKHR> present_modes;
bool format_srgb_bgra32 = false;
bool format_unorm_bgra32 = false;
};
struct WindowContext {
@ -26,7 +26,7 @@ struct WindowContext {
VulkanSwapchain* swapchain = nullptr;
SDL_Window* window = nullptr;
bool window_hidden = true;
VkSurfaceKHR surface = nullptr;
vk::SurfaceKHR surface = nullptr;
SurfaceCapabilities* surface_capabilities = nullptr;
WindowGame* game = nullptr;
@ -40,7 +40,7 @@ struct WindowContext {
extern WindowContext* g_window_ctx;
void VulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
void VulkanGetSurfaceCapabilities(vk::PhysicalDevice physical_device, vk::SurfaceKHR surface,
SurfaceCapabilities* capabilities);
VulkanSwapchain* VulkanCreateSwapchain(GraphicContext* ctx, uint32_t image_count);
void VulkanCreate(WindowContext* ctx);

View File

@ -9,7 +9,7 @@
namespace Libs::Graphics::Rt {
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::strcmp(extension.extensionName, name) == 0;
});
@ -26,7 +26,7 @@ void AppendExtensionIfMissing(std::vector<const char*>& extensions, const char*
} // namespace
void AppendHardwareRayTracingDeviceExtensions(
const std::vector<VkExtensionProperties>& available_extensions,
const std::vector<vk::ExtensionProperties>& available_extensions,
std::vector<const char*>* device_extensions, GraphicContext* ctx) {
EXIT_IF(device_extensions == nullptr || ctx == nullptr);
@ -64,33 +64,13 @@ void LoadHardwareRayTracingFunctions(GraphicContext* ctx) {
return;
}
ctx->vkGetBufferDeviceAddressKHR = reinterpret_cast<PFN_vkGetBufferDeviceAddressKHR>(
vkGetDeviceProcAddr(ctx->device, "vkGetBufferDeviceAddressKHR"));
if (ctx->vkGetBufferDeviceAddressKHR == nullptr) {
ctx->vkGetBufferDeviceAddressKHR = reinterpret_cast<PFN_vkGetBufferDeviceAddressKHR>(
vkGetDeviceProcAddr(ctx->device, "vkGetBufferDeviceAddress"));
}
ctx->vkCreateAccelerationStructureKHR = reinterpret_cast<PFN_vkCreateAccelerationStructureKHR>(
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) {
const auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER;
if (dispatcher.vkGetBufferDeviceAddressKHR == nullptr ||
dispatcher.vkCreateAccelerationStructureKHR == nullptr ||
dispatcher.vkDestroyAccelerationStructureKHR == nullptr ||
dispatcher.vkGetAccelerationStructureBuildSizesKHR == nullptr ||
dispatcher.vkCmdBuildAccelerationStructuresKHR == nullptr ||
dispatcher.vkGetAccelerationStructureDeviceAddressKHR == nullptr) {
EXIT("Vulkan RT: failed to load required device functions\n");
}
}

View File

@ -10,7 +10,7 @@ namespace Libs::Graphics {
namespace Rt {
void AppendHardwareRayTracingDeviceExtensions(
const std::vector<VkExtensionProperties>& available_extensions,
const std::vector<vk::ExtensionProperties>& available_extensions,
std::vector<const char*>* device_extensions, GraphicContext* ctx);
void LoadHardwareRayTracingFunctions(GraphicContext* ctx);

File diff suppressed because it is too large Load Diff

View File

@ -411,14 +411,16 @@ constexpr uint32_t EncodeSopp(uint32_t opcode, uint32_t simm = 0) {
void TestNativeShaderResourceDependencies() {
const auto stages = ShaderPipelineStages(
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT);
Check(stages == (VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT),
vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment |
vk::ShaderStageFlagBits::eCompute);
Check(stages == (vk::PipelineStageFlagBits::eVertexShader |
vk::PipelineStageFlagBits::eFragmentShader |
vk::PipelineStageFlagBits::eComputeShader),
"shader-stage dependency mapping was not exact");
const auto shader_barrier = MakeShaderWriteDependency();
Check(shader_barrier.srcAccessMask == VK_ACCESS_SHADER_WRITE_BIT &&
(shader_barrier.dstAccessMask & VK_ACCESS_SHADER_READ_BIT) != 0 &&
(shader_barrier.dstAccessMask & VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT) != 0,
Check(shader_barrier.srcAccessMask == vk::AccessFlagBits::eShaderWrite &&
(shader_barrier.dstAccessMask & vk::AccessFlagBits::eShaderRead) &&
(shader_barrier.dstAccessMask & vk::AccessFlagBits::eVertexAttributeRead),
"shader-write dependency does not expose draw/dispatch buffer writes");
ShaderRecompiler::IR::Program program;
@ -445,27 +447,27 @@ void TestNativeShaderResourceDependencies() {
"graphics/compute write collector lost or invented a storage-buffer range");
VulkanImage image {VulkanImageType::StorageTexture};
image.image = reinterpret_cast<VkImage>(uintptr_t {1});
image.layout = VK_IMAGE_LAYOUT_GENERAL;
image.image = reinterpret_cast<vk::Image::CType>(uintptr_t {1});
image.layout = vk::ImageLayout::eGeneral;
image.layers = 3;
const auto image_barrier = MakeStorageImageDependency(image, true, true);
Check(image_barrier.oldLayout == VK_IMAGE_LAYOUT_GENERAL &&
image_barrier.newLayout == VK_IMAGE_LAYOUT_GENERAL &&
(image_barrier.srcAccessMask & VK_ACCESS_MEMORY_WRITE_BIT) != 0 &&
(image_barrier.dstAccessMask & VK_ACCESS_SHADER_READ_BIT) != 0 &&
(image_barrier.dstAccessMask & VK_ACCESS_SHADER_WRITE_BIT) != 0 &&
Check(image_barrier.oldLayout == vk::ImageLayout::eGeneral &&
image_barrier.newLayout == vk::ImageLayout::eGeneral &&
(image_barrier.srcAccessMask & vk::AccessFlagBits::eMemoryWrite) &&
(image_barrier.dstAccessMask & vk::AccessFlagBits::eShaderRead) &&
(image_barrier.dstAccessMask & vk::AccessFlagBits::eShaderWrite) &&
image_barrier.subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS &&
image_barrier.subresourceRange.layerCount == image.layers,
"GENERAL storage-image dependency lacks a complete memory barrier");
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);
Check((gds_barrier.srcAccessMask & VK_ACCESS_HOST_WRITE_BIT) != 0 &&
(gds_barrier.srcAccessMask & VK_ACCESS_TRANSFER_WRITE_BIT) != 0 &&
(gds_barrier.srcAccessMask & VK_ACCESS_SHADER_WRITE_BIT) != 0 &&
Check((gds_barrier.srcAccessMask & vk::AccessFlagBits::eHostWrite) &&
(gds_barrier.srcAccessMask & vk::AccessFlagBits::eTransferWrite) &&
(gds_barrier.srcAccessMask & vk::AccessFlagBits::eShaderWrite) &&
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 dependency does not order host/transfer/shader writes");
}
@ -476,21 +478,21 @@ void TestNativeSubgroupPolicy() {
context.min_subgroup_size = 32;
context.max_subgroup_size = 32;
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;
safe.wave_size = 32;
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,
"native wave32 policy changed");
safe.wave_size = 64;
Check(SelectGraphicsLaneMaskMode(context, safe.wave_size) ==
ShaderLaneMaskMode::PerInvocation &&
ConfigureShaderSubgroup(context, VK_SHADER_STAGE_VERTEX_BIT, safe).mode ==
ConfigureShaderSubgroup(context, vk::ShaderStageFlagBits::eVertex, safe).mode ==
ShaderSubgroupMode::Unsupported,
"wave64 graphics mismatch accepted native-wave mask lowering");
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,
"wave64 graphics mismatch did not select per-invocation masks");
@ -498,12 +500,12 @@ void TestNativeSubgroupPolicy() {
cross_lane.blocks.emplace_back().instructions.emplace_back().op =
ShaderRecompiler::IR::Opcode::ReadLaneU32;
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,
"graphics mismatch did not select per-invocation masks");
auto cross_lane_compute = cross_lane;
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,
"cross-lane compute mismatch bypassed the exact subgroup requirement");
@ -519,7 +521,7 @@ void TestNativeSubgroupPolicy() {
zero_bfm.src_count = 2;
zero_bfm.scalar_sources[0] = 2;
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,
"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.blocks.emplace_back().instructions.emplace_back().op =
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,
"partial wave64 DS append bypassed the exact subgroup requirement");
context.max_subgroup_size = 64;
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,
"supported controlled wave64 was not preferred over splitting");
context.subgroup_size = 64;
context.subgroup_size_control_enabled = false;
cross_lane.wave_size = 32;
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,
"inverse graphics mismatch was accepted as one guest wave");
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,
"inverse cross-lane compute mismatch was accepted");
}
@ -5720,7 +5722,7 @@ void TestRenderTargetReverseFloat16ExportMapping() {
TextureGetRenderTargetFormat(Prospero::GpuEnumValue(Prospero::ChannelLayout::k16_16_16_16),
Prospero::GpuEnumValue(Prospero::ChannelType::kFloat),
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 "
"and size");
Check(format.export_mapping == Prospero::ColorMappingAbgr &&
@ -5735,7 +5737,7 @@ void TestRenderTargetReverseFloat16ExportMapping() {
Prospero::GpuEnumValue(Prospero::ChannelLayout::k8_8_8_8),
Prospero::GpuEnumValue(Prospero::ChannelType::kUNorm),
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");
const uint32_t shader[] = {