graphics: migrate Vulkan backend to Vulkan-Hpp
This commit is contained in:
parent
587cb238f0
commit
7905f2d12f
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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, ©);
|
||||
vk_buffer.copyBuffer(old.buffer->buffer, cached->buffer->buffer, 1, ©);
|
||||
}
|
||||
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, ©);
|
||||
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, ©);
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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_
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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[] = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue