aboutsummaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/CMakeLists.txt6
-rw-r--r--src/video_core/cdma_pusher.cpp4
-rw-r--r--src/video_core/cdma_pusher.h2
-rw-r--r--src/video_core/command_classes/codecs/h264.cpp4
-rw-r--r--src/video_core/engines/fermi_2d.h30
-rw-r--r--src/video_core/engines/kepler_compute.h16
-rw-r--r--src/video_core/engines/kepler_memory.h4
-rw-r--r--src/video_core/engines/maxwell_3d.h150
-rw-r--r--src/video_core/engines/shader_header.h38
-rw-r--r--src/video_core/gpu.h8
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp10
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp22
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.h10
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp44
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h22
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp32
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.h15
-rw-r--r--src/video_core/renderer_vulkan/vk_fence_manager.cpp54
-rw-r--r--src/video_core/renderer_vulkan/vk_fence_manager.h15
-rw-r--r--src/video_core/renderer_vulkan/vk_memory_manager.cpp230
-rw-r--r--src/video_core/renderer_vulkan/vk_memory_manager.h132
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp17
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h10
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp126
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.h62
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp22
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h22
-rw-r--r--src/video_core/texture_cache/accelerated_swizzle.cpp4
-rw-r--r--src/video_core/texture_cache/util.cpp10
-rw-r--r--src/video_core/textures/astc.cpp41
-rw-r--r--src/video_core/textures/decoders.cpp8
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp11
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h35
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.cpp268
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.h118
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h284
37 files changed, 955 insertions, 935 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index f7b9d7f86..7a20d3a79 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -135,8 +135,6 @@ add_library(video_core STATIC
renderer_vulkan/vk_graphics_pipeline.h
renderer_vulkan/vk_master_semaphore.cpp
renderer_vulkan/vk_master_semaphore.h
- renderer_vulkan/vk_memory_manager.cpp
- renderer_vulkan/vk_memory_manager.h
renderer_vulkan/vk_pipeline_cache.cpp
renderer_vulkan/vk_pipeline_cache.h
renderer_vulkan/vk_query_cache.cpp
@@ -259,6 +257,8 @@ add_library(video_core STATIC
vulkan_common/vulkan_instance.h
vulkan_common/vulkan_library.cpp
vulkan_common/vulkan_library.h
+ vulkan_common/vulkan_memory_allocator.cpp
+ vulkan_common/vulkan_memory_allocator.h
vulkan_common/vulkan_surface.cpp
vulkan_common/vulkan_surface.h
vulkan_common/vulkan_wrapper.cpp
@@ -312,9 +312,7 @@ else()
-Werror=pessimizing-move
-Werror=redundant-move
-Werror=shadow
- -Werror=switch
-Werror=type-limits
- -Werror=unused-variable
$<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess>
$<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
diff --git a/src/video_core/cdma_pusher.cpp b/src/video_core/cdma_pusher.cpp
index 94679d5d1..33b3c060b 100644
--- a/src/video_core/cdma_pusher.cpp
+++ b/src/video_core/cdma_pusher.cpp
@@ -18,10 +18,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+#include <bit>
#include "command_classes/host1x.h"
#include "command_classes/nvdec.h"
#include "command_classes/vic.h"
-#include "common/bit_util.h"
#include "video_core/cdma_pusher.h"
#include "video_core/command_classes/nvdec_common.h"
#include "video_core/engines/maxwell_3d.h"
@@ -56,7 +56,7 @@ void CDmaPusher::Step() {
for (const u32 value : values) {
if (mask != 0) {
- const u32 lbs = Common::CountTrailingZeroes32(mask);
+ const auto lbs = static_cast<u32>(std::countr_zero(mask));
mask &= ~(1U << lbs);
ExecuteCommand(static_cast<u32>(offset + lbs), value);
continue;
diff --git a/src/video_core/cdma_pusher.h b/src/video_core/cdma_pusher.h
index 8ca70b6dd..e5f212c1a 100644
--- a/src/video_core/cdma_pusher.h
+++ b/src/video_core/cdma_pusher.h
@@ -126,7 +126,7 @@ private:
s32 count{};
s32 offset{};
- s32 mask{};
+ u32 mask{};
bool incrementing{};
// Queue of command lists to be processed
diff --git a/src/video_core/command_classes/codecs/h264.cpp b/src/video_core/command_classes/codecs/h264.cpp
index 65bbeac78..fea6aed98 100644
--- a/src/video_core/command_classes/codecs/h264.cpp
+++ b/src/video_core/command_classes/codecs/h264.cpp
@@ -19,7 +19,7 @@
//
#include <array>
-#include "common/bit_util.h"
+#include <bit>
#include "video_core/command_classes/codecs/h264.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
@@ -266,7 +266,7 @@ void H264BitWriter::WriteExpGolombCodedInt(s32 value) {
}
void H264BitWriter::WriteExpGolombCodedUInt(u32 value) {
- const s32 size = 32 - Common::CountLeadingZeroes32(static_cast<s32>(value + 1));
+ const s32 size = 32 - std::countl_zero(value + 1);
WriteBits(1, size);
value -= (1U << (size - 1)) - 1;
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index 81522988e..0de3280a2 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -171,30 +171,30 @@ public:
static constexpr std::size_t NUM_REGS = 0x258;
struct {
u32 object;
- INSERT_UNION_PADDING_WORDS(0x3F);
+ INSERT_PADDING_WORDS_NOINIT(0x3F);
u32 no_operation;
NotifyType notify;
- INSERT_UNION_PADDING_WORDS(0x2);
+ INSERT_PADDING_WORDS_NOINIT(0x2);
u32 wait_for_idle;
- INSERT_UNION_PADDING_WORDS(0xB);
+ INSERT_PADDING_WORDS_NOINIT(0xB);
u32 pm_trigger;
- INSERT_UNION_PADDING_WORDS(0xF);
+ INSERT_PADDING_WORDS_NOINIT(0xF);
u32 context_dma_notify;
u32 dst_context_dma;
u32 src_context_dma;
u32 semaphore_context_dma;
- INSERT_UNION_PADDING_WORDS(0x1C);
+ INSERT_PADDING_WORDS_NOINIT(0x1C);
Surface dst;
CpuIndexWrap pixels_from_cpu_index_wrap;
u32 kind2d_check_enable;
Surface src;
SectorPromotion pixels_from_memory_sector_promotion;
- INSERT_UNION_PADDING_WORDS(0x1);
+ INSERT_PADDING_WORDS_NOINIT(0x1);
NumTpcs num_tpcs;
u32 render_enable_addr_upper;
u32 render_enable_addr_lower;
RenderEnableMode render_enable_mode;
- INSERT_UNION_PADDING_WORDS(0x4);
+ INSERT_PADDING_WORDS_NOINIT(0x4);
u32 clip_x0;
u32 clip_y0;
u32 clip_width;
@@ -212,7 +212,7 @@ public:
BitField<8, 6, u32> y;
} pattern_offset;
BitField<0, 2, PatternSelect> pattern_select;
- INSERT_UNION_PADDING_WORDS(0xC);
+ INSERT_PADDING_WORDS_NOINIT(0xC);
struct {
BitField<0, 3, MonochromePatternColorFormat> color_format;
BitField<0, 1, MonochromePatternFormat> format;
@@ -227,15 +227,15 @@ public:
std::array<u32, 0x20> X1R5G5B5;
std::array<u32, 0x10> Y8;
} color_pattern;
- INSERT_UNION_PADDING_WORDS(0x10);
+ INSERT_PADDING_WORDS_NOINIT(0x10);
struct {
u32 prim_mode;
u32 prim_color_format;
u32 prim_color;
u32 line_tie_break_bits;
- INSERT_UNION_PADDING_WORDS(0x14);
+ INSERT_PADDING_WORDS_NOINIT(0x14);
u32 prim_point_xy;
- INSERT_UNION_PADDING_WORDS(0x7);
+ INSERT_PADDING_WORDS_NOINIT(0x7);
std::array<Point, 0x40> prim_point;
} render_solid;
struct {
@@ -247,7 +247,7 @@ public:
u32 color0;
u32 color1;
u32 mono_opacity;
- INSERT_UNION_PADDING_WORDS(0x6);
+ INSERT_PADDING_WORDS_NOINIT(0x6);
u32 src_width;
u32 src_height;
u32 dx_du_frac;
@@ -260,9 +260,9 @@ public:
u32 dst_y0_int;
u32 data;
} pixels_from_cpu;
- INSERT_UNION_PADDING_WORDS(0x3);
+ INSERT_PADDING_WORDS_NOINIT(0x3);
u32 big_endian_control;
- INSERT_UNION_PADDING_WORDS(0x3);
+ INSERT_PADDING_WORDS_NOINIT(0x3);
struct {
BitField<0, 3, u32> block_shape;
BitField<0, 5, u32> corral_size;
@@ -271,7 +271,7 @@ public:
BitField<0, 1, Origin> origin;
BitField<4, 1, Filter> filter;
} sample_mode;
- INSERT_UNION_PADDING_WORDS(0x8);
+ INSERT_PADDING_WORDS_NOINIT(0x8);
s32 dst_x0;
s32 dst_y0;
s32 dst_width;
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h
index 51a041202..9f0a7b76d 100644
--- a/src/video_core/engines/kepler_compute.h
+++ b/src/video_core/engines/kepler_compute.h
@@ -55,7 +55,7 @@ public:
union {
struct {
- INSERT_UNION_PADDING_WORDS(0x60);
+ INSERT_PADDING_WORDS_NOINIT(0x60);
Upload::Registers upload;
@@ -67,7 +67,7 @@ public:
u32 data_upload;
- INSERT_UNION_PADDING_WORDS(0x3F);
+ INSERT_PADDING_WORDS_NOINIT(0x3F);
struct {
u32 address;
@@ -76,11 +76,11 @@ public:
}
} launch_desc_loc;
- INSERT_UNION_PADDING_WORDS(0x1);
+ INSERT_PADDING_WORDS_NOINIT(0x1);
u32 launch;
- INSERT_UNION_PADDING_WORDS(0x4A7);
+ INSERT_PADDING_WORDS_NOINIT(0x4A7);
struct {
u32 address_high;
@@ -92,7 +92,7 @@ public:
}
} tsc;
- INSERT_UNION_PADDING_WORDS(0x3);
+ INSERT_PADDING_WORDS_NOINIT(0x3);
struct {
u32 address_high;
@@ -104,7 +104,7 @@ public:
}
} tic;
- INSERT_UNION_PADDING_WORDS(0x22);
+ INSERT_PADDING_WORDS_NOINIT(0x22);
struct {
u32 address_high;
@@ -115,11 +115,11 @@ public:
}
} code_loc;
- INSERT_UNION_PADDING_WORDS(0x3FE);
+ INSERT_PADDING_WORDS_NOINIT(0x3FE);
u32 tex_cb_index;
- INSERT_UNION_PADDING_WORDS(0x374);
+ INSERT_PADDING_WORDS_NOINIT(0x374);
};
std::array<u32, NUM_REGS> reg_array;
};
diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h
index 62483589e..19808a5c6 100644
--- a/src/video_core/engines/kepler_memory.h
+++ b/src/video_core/engines/kepler_memory.h
@@ -50,7 +50,7 @@ public:
union {
struct {
- INSERT_UNION_PADDING_WORDS(0x60);
+ INSERT_PADDING_WORDS_NOINIT(0x60);
Upload::Registers upload;
@@ -62,7 +62,7 @@ public:
u32 data;
- INSERT_UNION_PADDING_WORDS(0x11);
+ INSERT_PADDING_WORDS_NOINIT(0x11);
};
std::array<u32, NUM_REGS> reg_array;
};
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index bf9e07c9b..326b32228 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -536,7 +536,7 @@ public:
Equation equation_a;
Factor factor_source_a;
Factor factor_dest_a;
- INSERT_UNION_PADDING_WORDS(1);
+ INSERT_PADDING_WORDS_NOINIT(1);
};
enum class TessellationPrimitive : u32 {
@@ -608,7 +608,7 @@ public:
};
u32 layer_stride;
u32 base_layer;
- INSERT_UNION_PADDING_WORDS(7);
+ INSERT_PADDING_WORDS_NOINIT(7);
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
@@ -640,7 +640,7 @@ public:
BitField<8, 3, ViewportSwizzle> z;
BitField<12, 3, ViewportSwizzle> w;
} swizzle;
- INSERT_UNION_PADDING_WORDS(1);
+ INSERT_PADDING_WORDS_NOINIT(1);
Common::Rectangle<f32> GetRect() const {
return {
@@ -700,7 +700,7 @@ public:
u32 address_low;
s32 buffer_size;
s32 buffer_offset;
- INSERT_UNION_PADDING_WORDS(3);
+ INSERT_PADDING_WORDS_NOINIT(3);
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
@@ -713,7 +713,7 @@ public:
u32 stream;
u32 varying_count;
u32 stride;
- INSERT_UNION_PADDING_WORDS(1);
+ INSERT_PADDING_WORDS_NOINIT(1);
};
static_assert(sizeof(TransformFeedbackLayout) == 16);
@@ -731,7 +731,7 @@ public:
union {
struct {
- INSERT_UNION_PADDING_WORDS(0x44);
+ INSERT_PADDING_WORDS_NOINIT(0x44);
u32 wait_for_idle;
@@ -744,7 +744,7 @@ public:
ShadowRamControl shadow_ram_control;
- INSERT_UNION_PADDING_WORDS(0x16);
+ INSERT_PADDING_WORDS_NOINIT(0x16);
Upload::Registers upload;
struct {
@@ -755,11 +755,11 @@ public:
u32 data_upload;
- INSERT_UNION_PADDING_WORDS(0x16);
+ INSERT_PADDING_WORDS_NOINIT(0x16);
u32 force_early_fragment_tests;
- INSERT_UNION_PADDING_WORDS(0x2D);
+ INSERT_PADDING_WORDS_NOINIT(0x2D);
struct {
union {
@@ -769,7 +769,7 @@ public:
};
} sync_info;
- INSERT_UNION_PADDING_WORDS(0x15);
+ INSERT_PADDING_WORDS_NOINIT(0x15);
union {
BitField<0, 2, TessellationPrimitive> prim;
@@ -781,21 +781,21 @@ public:
std::array<f32, 4> tess_level_outer;
std::array<f32, 2> tess_level_inner;
- INSERT_UNION_PADDING_WORDS(0x10);
+ INSERT_PADDING_WORDS_NOINIT(0x10);
u32 rasterize_enable;
std::array<TransformFeedbackBinding, NumTransformFeedbackBuffers> tfb_bindings;
- INSERT_UNION_PADDING_WORDS(0xC0);
+ INSERT_PADDING_WORDS_NOINIT(0xC0);
std::array<TransformFeedbackLayout, NumTransformFeedbackBuffers> tfb_layouts;
- INSERT_UNION_PADDING_WORDS(0x1);
+ INSERT_PADDING_WORDS_NOINIT(0x1);
u32 tfb_enabled;
- INSERT_UNION_PADDING_WORDS(0x2E);
+ INSERT_PADDING_WORDS_NOINIT(0x2E);
std::array<RenderTargetConfig, NumRenderTargets> rt;
@@ -803,7 +803,7 @@ public:
std::array<ViewPort, NumViewports> viewports;
- INSERT_UNION_PADDING_WORDS(0x1D);
+ INSERT_PADDING_WORDS_NOINIT(0x1D);
struct {
u32 first;
@@ -815,16 +815,16 @@ public:
float clear_color[4];
float clear_depth;
- INSERT_UNION_PADDING_WORDS(0x3);
+ INSERT_PADDING_WORDS_NOINIT(0x3);
s32 clear_stencil;
- INSERT_UNION_PADDING_WORDS(0x2);
+ INSERT_PADDING_WORDS_NOINIT(0x2);
PolygonMode polygon_mode_front;
PolygonMode polygon_mode_back;
- INSERT_UNION_PADDING_WORDS(0x3);
+ INSERT_PADDING_WORDS_NOINIT(0x3);
u32 polygon_offset_point_enable;
u32 polygon_offset_line_enable;
@@ -832,47 +832,47 @@ public:
u32 patch_vertices;
- INSERT_UNION_PADDING_WORDS(0x4);
+ INSERT_PADDING_WORDS_NOINIT(0x4);
u32 fragment_barrier;
- INSERT_UNION_PADDING_WORDS(0x7);
+ INSERT_PADDING_WORDS_NOINIT(0x7);
std::array<ScissorTest, NumViewports> scissor_test;
- INSERT_UNION_PADDING_WORDS(0x15);
+ INSERT_PADDING_WORDS_NOINIT(0x15);
s32 stencil_back_func_ref;
u32 stencil_back_mask;
u32 stencil_back_func_mask;
- INSERT_UNION_PADDING_WORDS(0x5);
+ INSERT_PADDING_WORDS_NOINIT(0x5);
u32 invalidate_texture_data_cache;
- INSERT_UNION_PADDING_WORDS(0x1);
+ INSERT_PADDING_WORDS_NOINIT(0x1);
u32 tiled_cache_barrier;
- INSERT_UNION_PADDING_WORDS(0x4);
+ INSERT_PADDING_WORDS_NOINIT(0x4);
u32 color_mask_common;
- INSERT_UNION_PADDING_WORDS(0x2);
+ INSERT_PADDING_WORDS_NOINIT(0x2);
f32 depth_bounds[2];
- INSERT_UNION_PADDING_WORDS(0x2);
+ INSERT_PADDING_WORDS_NOINIT(0x2);
u32 rt_separate_frag_data;
- INSERT_UNION_PADDING_WORDS(0x1);
+ INSERT_PADDING_WORDS_NOINIT(0x1);
u32 multisample_raster_enable;
u32 multisample_raster_samples;
std::array<u32, 4> multisample_sample_mask;
- INSERT_UNION_PADDING_WORDS(0x5);
+ INSERT_PADDING_WORDS_NOINIT(0x5);
struct {
u32 address_high;
@@ -898,7 +898,7 @@ public:
};
} render_area;
- INSERT_UNION_PADDING_WORDS(0x3F);
+ INSERT_PADDING_WORDS_NOINIT(0x3F);
union {
BitField<0, 4, u32> stencil;
@@ -907,24 +907,24 @@ public:
BitField<12, 4, u32> viewport;
} clear_flags;
- INSERT_UNION_PADDING_WORDS(0x10);
+ INSERT_PADDING_WORDS_NOINIT(0x10);
u32 fill_rectangle;
- INSERT_UNION_PADDING_WORDS(0x8);
+ INSERT_PADDING_WORDS_NOINIT(0x8);
std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format;
std::array<MsaaSampleLocation, 4> multisample_sample_locations;
- INSERT_UNION_PADDING_WORDS(0x2);
+ INSERT_PADDING_WORDS_NOINIT(0x2);
union {
BitField<0, 1, u32> enable;
BitField<4, 3, u32> target;
} multisample_coverage_to_color;
- INSERT_UNION_PADDING_WORDS(0x8);
+ INSERT_PADDING_WORDS_NOINIT(0x8);
struct {
union {
@@ -947,7 +947,7 @@ public:
}
} rt_control;
- INSERT_UNION_PADDING_WORDS(0x2);
+ INSERT_PADDING_WORDS_NOINIT(0x2);
u32 zeta_width;
u32 zeta_height;
@@ -958,11 +958,11 @@ public:
SamplerIndex sampler_index;
- INSERT_UNION_PADDING_WORDS(0x25);
+ INSERT_PADDING_WORDS_NOINIT(0x25);
u32 depth_test_enable;
- INSERT_UNION_PADDING_WORDS(0x5);
+ INSERT_PADDING_WORDS_NOINIT(0x5);
u32 independent_blend_enable;
@@ -970,7 +970,7 @@ public:
u32 alpha_test_enabled;
- INSERT_UNION_PADDING_WORDS(0x6);
+ INSERT_PADDING_WORDS_NOINIT(0x6);
u32 d3d_cull_mode;
@@ -985,7 +985,7 @@ public:
float a;
} blend_color;
- INSERT_UNION_PADDING_WORDS(0x4);
+ INSERT_PADDING_WORDS_NOINIT(0x4);
struct {
u32 separate_alpha;
@@ -994,7 +994,7 @@ public:
Blend::Factor factor_dest_rgb;
Blend::Equation equation_a;
Blend::Factor factor_source_a;
- INSERT_UNION_PADDING_WORDS(1);
+ INSERT_PADDING_WORDS_NOINIT(1);
Blend::Factor factor_dest_a;
u32 enable_common;
@@ -1010,7 +1010,7 @@ public:
u32 stencil_front_func_mask;
u32 stencil_front_mask;
- INSERT_UNION_PADDING_WORDS(0x2);
+ INSERT_PADDING_WORDS_NOINIT(0x2);
u32 frag_color_clamp;
@@ -1022,17 +1022,17 @@ public:
float line_width_smooth;
float line_width_aliased;
- INSERT_UNION_PADDING_WORDS(0x1B);
+ INSERT_PADDING_WORDS_NOINIT(0x1B);
u32 invalidate_sampler_cache_no_wfi;
u32 invalidate_texture_header_cache_no_wfi;
- INSERT_UNION_PADDING_WORDS(0x2);
+ INSERT_PADDING_WORDS_NOINIT(0x2);
u32 vb_element_base;
u32 vb_base_instance;
- INSERT_UNION_PADDING_WORDS(0x35);
+ INSERT_PADDING_WORDS_NOINIT(0x35);
u32 clip_distance_enabled;
@@ -1040,11 +1040,11 @@ public:
float point_size;
- INSERT_UNION_PADDING_WORDS(0x1);
+ INSERT_PADDING_WORDS_NOINIT(0x1);
u32 point_sprite_enable;
- INSERT_UNION_PADDING_WORDS(0x3);
+ INSERT_PADDING_WORDS_NOINIT(0x3);
CounterReset counter_reset;
@@ -1057,7 +1057,7 @@ public:
BitField<4, 1, u32> alpha_to_one;
} multisample_control;
- INSERT_UNION_PADDING_WORDS(0x4);
+ INSERT_PADDING_WORDS_NOINIT(0x4);
struct {
u32 address_high;
@@ -1081,7 +1081,7 @@ public:
}
} tsc;
- INSERT_UNION_PADDING_WORDS(0x1);
+ INSERT_PADDING_WORDS_NOINIT(0x1);
float polygon_offset_factor;
@@ -1098,7 +1098,7 @@ public:
}
} tic;
- INSERT_UNION_PADDING_WORDS(0x5);
+ INSERT_PADDING_WORDS_NOINIT(0x5);
u32 stencil_two_side_enable;
StencilOp stencil_back_op_fail;
@@ -1106,17 +1106,17 @@ public:
StencilOp stencil_back_op_zpass;
ComparisonOp stencil_back_func_func;
- INSERT_UNION_PADDING_WORDS(0x4);
+ INSERT_PADDING_WORDS_NOINIT(0x4);
u32 framebuffer_srgb;
float polygon_offset_units;
- INSERT_UNION_PADDING_WORDS(0x4);
+ INSERT_PADDING_WORDS_NOINIT(0x4);
Tegra::Texture::MsaaMode multisample_mode;
- INSERT_UNION_PADDING_WORDS(0xC);
+ INSERT_PADDING_WORDS_NOINIT(0xC);
union {
BitField<2, 1, u32> coord_origin;
@@ -1132,7 +1132,7 @@ public:
(static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low);
}
} code_address;
- INSERT_UNION_PADDING_WORDS(1);
+ INSERT_PADDING_WORDS_NOINIT(1);
struct {
u32 vertex_end_gl;
@@ -1144,14 +1144,14 @@ public:
};
} draw;
- INSERT_UNION_PADDING_WORDS(0xA);
+ INSERT_PADDING_WORDS_NOINIT(0xA);
struct {
u32 enabled;
u32 index;
} primitive_restart;
- INSERT_UNION_PADDING_WORDS(0x5F);
+ INSERT_PADDING_WORDS_NOINIT(0x5F);
struct {
u32 start_addr_high;
@@ -1192,9 +1192,9 @@ public:
}
} index_array;
- INSERT_UNION_PADDING_WORDS(0x7);
+ INSERT_PADDING_WORDS_NOINIT(0x7);
- INSERT_UNION_PADDING_WORDS(0x1F);
+ INSERT_PADDING_WORDS_NOINIT(0x1F);
float polygon_offset_clamp;
@@ -1208,14 +1208,14 @@ public:
}
} instanced_arrays;
- INSERT_UNION_PADDING_WORDS(0x4);
+ INSERT_PADDING_WORDS_NOINIT(0x4);
union {
BitField<0, 1, u32> enable;
BitField<4, 8, u32> unk4;
} vp_point_size;
- INSERT_UNION_PADDING_WORDS(1);
+ INSERT_PADDING_WORDS_NOINIT(1);
u32 cull_test_enabled;
FrontFace front_face;
@@ -1223,11 +1223,11 @@ public:
u32 pixel_center_integer;
- INSERT_UNION_PADDING_WORDS(0x1);
+ INSERT_PADDING_WORDS_NOINIT(0x1);
u32 viewport_transform_enabled;
- INSERT_UNION_PADDING_WORDS(0x3);
+ INSERT_PADDING_WORDS_NOINIT(0x3);
union {
BitField<0, 1, u32> depth_range_0_1;
@@ -1236,18 +1236,18 @@ public:
BitField<11, 1, u32> depth_clamp_disabled;
} view_volume_clip_control;
- INSERT_UNION_PADDING_WORDS(0x1F);
+ INSERT_PADDING_WORDS_NOINIT(0x1F);
u32 depth_bounds_enable;
- INSERT_UNION_PADDING_WORDS(1);
+ INSERT_PADDING_WORDS_NOINIT(1);
struct {
u32 enable;
LogicOperation operation;
} logic_op;
- INSERT_UNION_PADDING_WORDS(0x1);
+ INSERT_PADDING_WORDS_NOINIT(0x1);
union {
u32 raw;
@@ -1260,9 +1260,9 @@ public:
BitField<6, 4, u32> RT;
BitField<10, 11, u32> layer;
} clear_buffers;
- INSERT_UNION_PADDING_WORDS(0xB);
+ INSERT_PADDING_WORDS_NOINIT(0xB);
std::array<ColorMask, NumRenderTargets> color_mask;
- INSERT_UNION_PADDING_WORDS(0x38);
+ INSERT_PADDING_WORDS_NOINIT(0x38);
struct {
u32 query_address_high;
@@ -1284,7 +1284,7 @@ public:
}
} query;
- INSERT_UNION_PADDING_WORDS(0x3C);
+ INSERT_PADDING_WORDS_NOINIT(0x3C);
struct {
union {
@@ -1325,10 +1325,10 @@ public:
BitField<4, 4, ShaderProgram> program;
};
u32 offset;
- INSERT_UNION_PADDING_WORDS(14);
+ INSERT_PADDING_WORDS_NOINIT(14);
} shader_config[MaxShaderProgram];
- INSERT_UNION_PADDING_WORDS(0x60);
+ INSERT_PADDING_WORDS_NOINIT(0x60);
u32 firmware[0x20];
@@ -1345,7 +1345,7 @@ public:
}
} const_buffer;
- INSERT_UNION_PADDING_WORDS(0x10);
+ INSERT_PADDING_WORDS_NOINIT(0x10);
struct {
union {
@@ -1353,18 +1353,18 @@ public:
BitField<0, 1, u32> valid;
BitField<4, 5, u32> index;
};
- INSERT_UNION_PADDING_WORDS(7);
+ INSERT_PADDING_WORDS_NOINIT(7);
} cb_bind[MaxShaderStage];
- INSERT_UNION_PADDING_WORDS(0x56);
+ INSERT_PADDING_WORDS_NOINIT(0x56);
u32 tex_cb_index;
- INSERT_UNION_PADDING_WORDS(0x7D);
+ INSERT_PADDING_WORDS_NOINIT(0x7D);
std::array<std::array<u8, 128>, NumTransformFeedbackBuffers> tfb_varying_locs;
- INSERT_UNION_PADDING_WORDS(0x298);
+ INSERT_PADDING_WORDS_NOINIT(0x298);
struct {
/// Compressed address of a buffer that holds information about bound SSBOs.
@@ -1376,14 +1376,14 @@ public:
}
} ssbo_info;
- INSERT_UNION_PADDING_WORDS(0x11);
+ INSERT_PADDING_WORDS_NOINIT(0x11);
struct {
u32 address[MaxShaderStage];
u32 size[MaxShaderStage];
} tex_info_buffers;
- INSERT_UNION_PADDING_WORDS(0xCC);
+ INSERT_PADDING_WORDS_NOINIT(0xCC);
};
std::array<u32, NUM_REGS> reg_array;
};
diff --git a/src/video_core/engines/shader_header.h b/src/video_core/engines/shader_header.h
index ceec05459..e0d7b89c5 100644
--- a/src/video_core/engines/shader_header.h
+++ b/src/video_core/engines/shader_header.h
@@ -68,10 +68,10 @@ struct Header {
union {
struct {
- INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA
- INSERT_UNION_PADDING_BYTES(1); // ImapSystemValuesB
- INSERT_UNION_PADDING_BYTES(16); // ImapGenericVector[32]
- INSERT_UNION_PADDING_BYTES(2); // ImapColor
+ INSERT_PADDING_BYTES_NOINIT(3); // ImapSystemValuesA
+ INSERT_PADDING_BYTES_NOINIT(1); // ImapSystemValuesB
+ INSERT_PADDING_BYTES_NOINIT(16); // ImapGenericVector[32]
+ INSERT_PADDING_BYTES_NOINIT(2); // ImapColor
union {
BitField<0, 8, u16> clip_distances;
BitField<8, 1, u16> point_sprite_s;
@@ -82,20 +82,20 @@ struct Header {
BitField<14, 1, u16> instance_id;
BitField<15, 1, u16> vertex_id;
};
- INSERT_UNION_PADDING_BYTES(5); // ImapFixedFncTexture[10]
- INSERT_UNION_PADDING_BYTES(1); // ImapReserved
- INSERT_UNION_PADDING_BYTES(3); // OmapSystemValuesA
- INSERT_UNION_PADDING_BYTES(1); // OmapSystemValuesB
- INSERT_UNION_PADDING_BYTES(16); // OmapGenericVector[32]
- INSERT_UNION_PADDING_BYTES(2); // OmapColor
- INSERT_UNION_PADDING_BYTES(2); // OmapSystemValuesC
- INSERT_UNION_PADDING_BYTES(5); // OmapFixedFncTexture[10]
- INSERT_UNION_PADDING_BYTES(1); // OmapReserved
+ INSERT_PADDING_BYTES_NOINIT(5); // ImapFixedFncTexture[10]
+ INSERT_PADDING_BYTES_NOINIT(1); // ImapReserved
+ INSERT_PADDING_BYTES_NOINIT(3); // OmapSystemValuesA
+ INSERT_PADDING_BYTES_NOINIT(1); // OmapSystemValuesB
+ INSERT_PADDING_BYTES_NOINIT(16); // OmapGenericVector[32]
+ INSERT_PADDING_BYTES_NOINIT(2); // OmapColor
+ INSERT_PADDING_BYTES_NOINIT(2); // OmapSystemValuesC
+ INSERT_PADDING_BYTES_NOINIT(5); // OmapFixedFncTexture[10]
+ INSERT_PADDING_BYTES_NOINIT(1); // OmapReserved
} vtg;
struct {
- INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA
- INSERT_UNION_PADDING_BYTES(1); // ImapSystemValuesB
+ INSERT_PADDING_BYTES_NOINIT(3); // ImapSystemValuesA
+ INSERT_PADDING_BYTES_NOINIT(1); // ImapSystemValuesB
union {
BitField<0, 2, PixelImap> x;
@@ -105,10 +105,10 @@ struct Header {
u8 raw;
} imap_generic_vector[32];
- INSERT_UNION_PADDING_BYTES(2); // ImapColor
- INSERT_UNION_PADDING_BYTES(2); // ImapSystemValuesC
- INSERT_UNION_PADDING_BYTES(10); // ImapFixedFncTexture[10]
- INSERT_UNION_PADDING_BYTES(2); // ImapReserved
+ INSERT_PADDING_BYTES_NOINIT(2); // ImapColor
+ INSERT_PADDING_BYTES_NOINIT(2); // ImapSystemValuesC
+ INSERT_PADDING_BYTES_NOINIT(10); // ImapFixedFncTexture[10]
+ INSERT_PADDING_BYTES_NOINIT(2); // ImapReserved
struct {
u32 target;
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index d81e38680..b4ce6b154 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -270,7 +270,7 @@ public:
union {
struct {
- INSERT_UNION_PADDING_WORDS(0x4);
+ INSERT_PADDING_WORDS_NOINIT(0x4);
struct {
u32 address_high;
u32 address_low;
@@ -283,18 +283,18 @@ public:
u32 semaphore_sequence;
u32 semaphore_trigger;
- INSERT_UNION_PADDING_WORDS(0xC);
+ INSERT_PADDING_WORDS_NOINIT(0xC);
// The pusher and the puller share the reference counter, the pusher only has read
// access
u32 reference_count;
- INSERT_UNION_PADDING_WORDS(0x5);
+ INSERT_PADDING_WORDS_NOINIT(0x5);
u32 semaphore_acquire;
u32 semaphore_release;
u32 fence_value;
FenceAction fence_action;
- INSERT_UNION_PADDING_WORDS(0xE2);
+ INSERT_PADDING_WORDS_NOINIT(0xE2);
// Puller state
u32 acquire_mode;
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index d7437e185..61796e33a 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -23,7 +23,6 @@
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "video_core/renderer_vulkan/vk_blit_screen.h"
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
-#include "video_core/renderer_vulkan/vk_memory_manager.h"
#include "video_core/renderer_vulkan/vk_rasterizer.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_state_tracker.h"
@@ -32,6 +31,7 @@
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_instance.h"
#include "video_core/vulkan_common/vulkan_library.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_surface.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -137,7 +137,7 @@ bool RendererVulkan::Init() try {
InitializeDevice();
Report();
- memory_manager = std::make_unique<VKMemoryManager>(*device);
+ memory_allocator = std::make_unique<MemoryAllocator>(*device);
state_tracker = std::make_unique<StateTracker>(gpu);
@@ -149,11 +149,11 @@ bool RendererVulkan::Init() try {
rasterizer = std::make_unique<RasterizerVulkan>(render_window, gpu, gpu.MemoryManager(),
cpu_memory, screen_info, *device,
- *memory_manager, *state_tracker, *scheduler);
+ *memory_allocator, *state_tracker, *scheduler);
blit_screen =
std::make_unique<VKBlitScreen>(cpu_memory, render_window, *rasterizer, *device,
- *memory_manager, *swapchain, *scheduler, screen_info);
+ *memory_allocator, *swapchain, *scheduler, screen_info);
return true;
} catch (const vk::Exception& exception) {
@@ -172,7 +172,7 @@ void RendererVulkan::ShutDown() {
blit_screen.reset();
scheduler.reset();
swapchain.reset();
- memory_manager.reset();
+ memory_allocator.reset();
device.reset();
}
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index 5575ffc54..daf55b9b4 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -29,8 +29,8 @@ namespace Vulkan {
class Device;
class StateTracker;
+class MemoryAllocator;
class VKBlitScreen;
-class VKMemoryManager;
class VKSwapchain;
class VKScheduler;
@@ -75,7 +75,7 @@ private:
vk::DebugUtilsMessenger debug_callback;
std::unique_ptr<Device> device;
- std::unique_ptr<VKMemoryManager> memory_manager;
+ std::unique_ptr<MemoryAllocator> memory_allocator;
std::unique_ptr<StateTracker> state_tracker;
std::unique_ptr<VKScheduler> scheduler;
std::unique_ptr<VKSwapchain> swapchain;
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 5e184eb42..3e3b895e0 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -22,13 +22,13 @@
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "video_core/renderer_vulkan/vk_blit_screen.h"
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
-#include "video_core/renderer_vulkan/vk_memory_manager.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_shader_util.h"
#include "video_core/renderer_vulkan/vk_swapchain.h"
#include "video_core/surface.h"
#include "video_core/textures/decoders.h"
#include "video_core/vulkan_common/vulkan_device.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan {
@@ -115,10 +115,10 @@ struct VKBlitScreen::BufferData {
VKBlitScreen::VKBlitScreen(Core::Memory::Memory& cpu_memory_,
Core::Frontend::EmuWindow& render_window_,
VideoCore::RasterizerInterface& rasterizer_, const Device& device_,
- VKMemoryManager& memory_manager_, VKSwapchain& swapchain_,
+ MemoryAllocator& memory_allocator_, VKSwapchain& swapchain_,
VKScheduler& scheduler_, const VKScreenInfo& screen_info_)
: cpu_memory{cpu_memory_}, render_window{render_window_}, rasterizer{rasterizer_},
- device{device_}, memory_manager{memory_manager_}, swapchain{swapchain_},
+ device{device_}, memory_allocator{memory_allocator_}, swapchain{swapchain_},
scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
resource_ticks.resize(image_count);
@@ -150,8 +150,8 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, bool
SetUniformData(data, framebuffer);
SetVertexData(data, framebuffer);
- auto map = buffer_commit->Map();
- std::memcpy(map.Address(), &data, sizeof(data));
+ const std::span<u8> map = buffer_commit.Map();
+ std::memcpy(map.data(), &data, sizeof(data));
if (!use_accelerated) {
const u64 image_offset = GetRawImageOffset(framebuffer, image_index);
@@ -165,8 +165,8 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, bool
constexpr u32 block_height_log2 = 4;
const u32 bytes_per_pixel = GetBytesPerPixel(framebuffer);
Tegra::Texture::UnswizzleTexture(
- std::span(map.Address() + image_offset, size_bytes), std::span(host_ptr, size_bytes),
- bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0);
+ map.subspan(image_offset, size_bytes), std::span(host_ptr, size_bytes), bytes_per_pixel,
+ framebuffer.width, framebuffer.height, 1, block_height_log2, 0);
const VkBufferImageCopy copy{
.bufferOffset = image_offset,
@@ -224,8 +224,6 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, bool
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, write_barrier);
});
}
- map.Release();
-
scheduler.Record([renderpass = *renderpass, framebuffer = *framebuffers[image_index],
descriptor_set = descriptor_sets[image_index], buffer = *buffer,
size = swapchain.GetSize(), pipeline = *pipeline,
@@ -642,7 +640,7 @@ void VKBlitScreen::ReleaseRawImages() {
raw_images.clear();
raw_buffer_commits.clear();
buffer.reset();
- buffer_commit.reset();
+ buffer_commit = MemoryCommit{};
}
void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) {
@@ -659,7 +657,7 @@ void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuff
};
buffer = device.GetLogical().CreateBuffer(ci);
- buffer_commit = memory_manager.Commit(buffer, true);
+ buffer_commit = memory_allocator.Commit(buffer, MemoryUsage::Upload);
}
void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
@@ -690,7 +688,7 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer)
.pQueueFamilyIndices = nullptr,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
});
- raw_buffer_commits[i] = memory_manager.Commit(raw_images[i], false);
+ raw_buffer_commits[i] = memory_allocator.Commit(raw_images[i], MemoryUsage::DeviceLocal);
raw_image_views[i] = device.GetLogical().CreateImageView(VkImageViewCreateInfo{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = nullptr,
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h
index 69ed61770..b52576957 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.h
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.h
@@ -6,7 +6,7 @@
#include <memory>
-#include "video_core/renderer_vulkan/vk_memory_manager.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Core {
@@ -43,7 +43,7 @@ public:
explicit VKBlitScreen(Core::Memory::Memory& cpu_memory,
Core::Frontend::EmuWindow& render_window,
VideoCore::RasterizerInterface& rasterizer, const Device& device,
- VKMemoryManager& memory_manager, VKSwapchain& swapchain,
+ MemoryAllocator& memory_allocator, VKSwapchain& swapchain,
VKScheduler& scheduler, const VKScreenInfo& screen_info);
~VKBlitScreen();
@@ -86,7 +86,7 @@ private:
Core::Frontend::EmuWindow& render_window;
VideoCore::RasterizerInterface& rasterizer;
const Device& device;
- VKMemoryManager& memory_manager;
+ MemoryAllocator& memory_allocator;
VKSwapchain& swapchain;
VKScheduler& scheduler;
const std::size_t image_count;
@@ -104,14 +104,14 @@ private:
vk::Sampler sampler;
vk::Buffer buffer;
- VKMemoryCommit buffer_commit;
+ MemoryCommit buffer_commit;
std::vector<u64> resource_ticks;
std::vector<vk::Semaphore> semaphores;
std::vector<vk::Image> raw_images;
std::vector<vk::ImageView> raw_image_views;
- std::vector<VKMemoryCommit> raw_buffer_commits;
+ std::vector<MemoryCommit> raw_buffer_commits;
u32 raw_width = 0;
u32 raw_height = 0;
};
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 4d517c547..d8ad40a0f 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -34,17 +34,13 @@ constexpr VkAccessFlags UPLOAD_ACCESS_BARRIERS =
constexpr VkAccessFlags TRANSFORM_FEEDBACK_WRITE_ACCESS =
VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
-std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const Device& device, VKScheduler& scheduler) {
- return std::make_unique<VKStreamBuffer>(device, scheduler);
-}
-
} // Anonymous namespace
-Buffer::Buffer(const Device& device_, VKMemoryManager& memory_manager, VKScheduler& scheduler_,
- VKStagingBufferPool& staging_pool_, VAddr cpu_addr_, std::size_t size_)
+Buffer::Buffer(const Device& device_, MemoryAllocator& memory_allocator, VKScheduler& scheduler_,
+ StagingBufferPool& staging_pool_, VAddr cpu_addr_, std::size_t size_)
: BufferBlock{cpu_addr_, size_}, device{device_}, scheduler{scheduler_}, staging_pool{
staging_pool_} {
- const VkBufferCreateInfo ci{
+ buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
@@ -53,22 +49,20 @@ Buffer::Buffer(const Device& device_, VKMemoryManager& memory_manager, VKSchedul
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
- };
-
- buffer.handle = device.GetLogical().CreateBuffer(ci);
- buffer.commit = memory_manager.Commit(buffer.handle, false);
+ });
+ commit = memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
}
Buffer::~Buffer() = default;
void Buffer::Upload(std::size_t offset, std::size_t data_size, const u8* data) {
- const auto& staging = staging_pool.GetUnusedBuffer(data_size, true);
- std::memcpy(staging.commit->Map(data_size), data, data_size);
+ const auto& staging = staging_pool.Request(data_size, MemoryUsage::Upload);
+ std::memcpy(staging.mapped_span.data(), data, data_size);
scheduler.RequestOutsideRenderPassOperationContext();
const VkBuffer handle = Handle();
- scheduler.Record([staging = *staging.handle, handle, offset, data_size,
+ scheduler.Record([staging = staging.buffer, handle, offset, data_size,
&device = device](vk::CommandBuffer cmdbuf) {
const VkBufferMemoryBarrier read_barrier{
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
@@ -104,12 +98,12 @@ void Buffer::Upload(std::size_t offset, std::size_t data_size, const u8* data) {
}
void Buffer::Download(std::size_t offset, std::size_t data_size, u8* data) {
- const auto& staging = staging_pool.GetUnusedBuffer(data_size, true);
+ auto staging = staging_pool.Request(data_size, MemoryUsage::Download);
scheduler.RequestOutsideRenderPassOperationContext();
const VkBuffer handle = Handle();
scheduler.Record(
- [staging = *staging.handle, handle, offset, data_size](vk::CommandBuffer cmdbuf) {
+ [staging = staging.buffer, handle, offset, data_size](vk::CommandBuffer cmdbuf) {
const VkBufferMemoryBarrier barrier{
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
@@ -130,7 +124,7 @@ void Buffer::Download(std::size_t offset, std::size_t data_size, u8* data) {
});
scheduler.Finish();
- std::memcpy(data, staging.commit->Map(data_size), data_size);
+ std::memcpy(data, staging.mapped_span.data(), data_size);
}
void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset,
@@ -168,29 +162,29 @@ void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst
VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer_,
Tegra::MemoryManager& gpu_memory_, Core::Memory::Memory& cpu_memory_,
- const Device& device_, VKMemoryManager& memory_manager_,
+ const Device& device_, MemoryAllocator& memory_allocator_,
VKScheduler& scheduler_, VKStreamBuffer& stream_buffer_,
- VKStagingBufferPool& staging_pool_)
+ StagingBufferPool& staging_pool_)
: VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer>{rasterizer_, gpu_memory_,
cpu_memory_, stream_buffer_},
- device{device_}, memory_manager{memory_manager_}, scheduler{scheduler_}, staging_pool{
- staging_pool_} {}
+ device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
+ staging_pool{staging_pool_} {}
VKBufferCache::~VKBufferCache() = default;
std::shared_ptr<Buffer> VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) {
- return std::make_shared<Buffer>(device, memory_manager, scheduler, staging_pool, cpu_addr,
+ return std::make_shared<Buffer>(device, memory_allocator, scheduler, staging_pool, cpu_addr,
size);
}
VKBufferCache::BufferInfo VKBufferCache::GetEmptyBuffer(std::size_t size) {
size = std::max(size, std::size_t(4));
- const auto& empty = staging_pool.GetUnusedBuffer(size, false);
+ const auto& empty = staging_pool.Request(size, MemoryUsage::DeviceLocal);
scheduler.RequestOutsideRenderPassOperationContext();
- scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) {
+ scheduler.Record([size, buffer = empty.buffer](vk::CommandBuffer cmdbuf) {
cmdbuf.FillBuffer(buffer, 0, size, 0);
});
- return {*empty.handle, 0, 0};
+ return {empty.buffer, 0, 0};
}
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 1c39aed34..41d577510 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -8,21 +8,20 @@
#include "common/common_types.h"
#include "video_core/buffer_cache/buffer_cache.h"
-#include "video_core/renderer_vulkan/vk_memory_manager.h"
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
#include "video_core/renderer_vulkan/vk_stream_buffer.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan {
class Device;
-class VKMemoryManager;
class VKScheduler;
class Buffer final : public VideoCommon::BufferBlock {
public:
- explicit Buffer(const Device& device, VKMemoryManager& memory_manager, VKScheduler& scheduler,
- VKStagingBufferPool& staging_pool, VAddr cpu_addr_, std::size_t size_);
+ explicit Buffer(const Device& device, MemoryAllocator& memory_allocator, VKScheduler& scheduler,
+ StagingBufferPool& staging_pool, VAddr cpu_addr_, std::size_t size_);
~Buffer();
void Upload(std::size_t offset, std::size_t data_size, const u8* data);
@@ -33,7 +32,7 @@ public:
std::size_t copy_size);
VkBuffer Handle() const {
- return *buffer.handle;
+ return *buffer;
}
u64 Address() const {
@@ -43,18 +42,19 @@ public:
private:
const Device& device;
VKScheduler& scheduler;
- VKStagingBufferPool& staging_pool;
+ StagingBufferPool& staging_pool;
- VKBuffer buffer;
+ vk::Buffer buffer;
+ MemoryCommit commit;
};
class VKBufferCache final : public VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer> {
public:
explicit VKBufferCache(VideoCore::RasterizerInterface& rasterizer,
Tegra::MemoryManager& gpu_memory, Core::Memory::Memory& cpu_memory,
- const Device& device, VKMemoryManager& memory_manager,
+ const Device& device, MemoryAllocator& memory_allocator,
VKScheduler& scheduler, VKStreamBuffer& stream_buffer,
- VKStagingBufferPool& staging_pool);
+ StagingBufferPool& staging_pool);
~VKBufferCache();
BufferInfo GetEmptyBuffer(std::size_t size) override;
@@ -64,9 +64,9 @@ protected:
private:
const Device& device;
- VKMemoryManager& memory_manager;
+ MemoryAllocator& memory_allocator;
VKScheduler& scheduler;
- VKStagingBufferPool& staging_pool;
+ StagingBufferPool& staging_pool;
};
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index 02a6d54b7..5eb6a54be 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -164,7 +164,7 @@ VkDescriptorSet VKComputePass::CommitDescriptorSet(
QuadArrayPass::QuadArrayPass(const Device& device_, VKScheduler& scheduler_,
VKDescriptorPool& descriptor_pool_,
- VKStagingBufferPool& staging_buffer_pool_,
+ StagingBufferPool& staging_buffer_pool_,
VKUpdateDescriptorQueue& update_descriptor_queue_)
: VKComputePass(device_, descriptor_pool_, BuildQuadArrayPassDescriptorSetLayoutBinding(),
BuildQuadArrayPassDescriptorUpdateTemplateEntry(),
@@ -177,18 +177,18 @@ QuadArrayPass::~QuadArrayPass() = default;
std::pair<VkBuffer, VkDeviceSize> QuadArrayPass::Assemble(u32 num_vertices, u32 first) {
const u32 num_triangle_vertices = (num_vertices / 4) * 6;
const std::size_t staging_size = num_triangle_vertices * sizeof(u32);
- auto& buffer = staging_buffer_pool.GetUnusedBuffer(staging_size, false);
+ const auto staging_ref = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
update_descriptor_queue.Acquire();
- update_descriptor_queue.AddBuffer(*buffer.handle, 0, staging_size);
+ update_descriptor_queue.AddBuffer(staging_ref.buffer, 0, staging_size);
const VkDescriptorSet set = CommitDescriptorSet(update_descriptor_queue);
scheduler.RequestOutsideRenderPassOperationContext();
ASSERT(num_vertices % 4 == 0);
const u32 num_quads = num_vertices / 4;
- scheduler.Record([layout = *layout, pipeline = *pipeline, buffer = *buffer.handle, num_quads,
- first, set](vk::CommandBuffer cmdbuf) {
+ scheduler.Record([layout = *layout, pipeline = *pipeline, buffer = staging_ref.buffer,
+ num_quads, first, set](vk::CommandBuffer cmdbuf) {
constexpr u32 dispatch_size = 1024;
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, set, {});
@@ -208,11 +208,11 @@ std::pair<VkBuffer, VkDeviceSize> QuadArrayPass::Assemble(u32 num_vertices, u32
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, {}, {barrier}, {});
});
- return {*buffer.handle, 0};
+ return {staging_ref.buffer, 0};
}
Uint8Pass::Uint8Pass(const Device& device, VKScheduler& scheduler_,
- VKDescriptorPool& descriptor_pool, VKStagingBufferPool& staging_buffer_pool_,
+ VKDescriptorPool& descriptor_pool, StagingBufferPool& staging_buffer_pool_,
VKUpdateDescriptorQueue& update_descriptor_queue_)
: VKComputePass(device, descriptor_pool, BuildInputOutputDescriptorSetBindings(),
BuildInputOutputDescriptorUpdateTemplate(), {}, VULKAN_UINT8_COMP_SPV),
@@ -224,15 +224,15 @@ Uint8Pass::~Uint8Pass() = default;
std::pair<VkBuffer, u64> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buffer,
u64 src_offset) {
const u32 staging_size = static_cast<u32>(num_vertices * sizeof(u16));
- auto& buffer = staging_buffer_pool.GetUnusedBuffer(staging_size, false);
+ const auto staging_ref = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
update_descriptor_queue.Acquire();
update_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices);
- update_descriptor_queue.AddBuffer(*buffer.handle, 0, staging_size);
+ update_descriptor_queue.AddBuffer(staging_ref.buffer, 0, staging_size);
const VkDescriptorSet set = CommitDescriptorSet(update_descriptor_queue);
scheduler.RequestOutsideRenderPassOperationContext();
- scheduler.Record([layout = *layout, pipeline = *pipeline, buffer = *buffer.handle, set,
+ scheduler.Record([layout = *layout, pipeline = *pipeline, buffer = staging_ref.buffer, set,
num_vertices](vk::CommandBuffer cmdbuf) {
constexpr u32 dispatch_size = 1024;
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
@@ -252,12 +252,12 @@ std::pair<VkBuffer, u64> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buff
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, {}, barrier, {});
});
- return {*buffer.handle, 0};
+ return {staging_ref.buffer, 0};
}
QuadIndexedPass::QuadIndexedPass(const Device& device_, VKScheduler& scheduler_,
VKDescriptorPool& descriptor_pool_,
- VKStagingBufferPool& staging_buffer_pool_,
+ StagingBufferPool& staging_buffer_pool_,
VKUpdateDescriptorQueue& update_descriptor_queue_)
: VKComputePass(device_, descriptor_pool_, BuildInputOutputDescriptorSetBindings(),
BuildInputOutputDescriptorUpdateTemplate(),
@@ -286,15 +286,15 @@ std::pair<VkBuffer, u64> QuadIndexedPass::Assemble(
const u32 num_tri_vertices = (num_vertices / 4) * 6;
const std::size_t staging_size = num_tri_vertices * sizeof(u32);
- auto& buffer = staging_buffer_pool.GetUnusedBuffer(staging_size, false);
+ const auto staging_ref = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
update_descriptor_queue.Acquire();
update_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size);
- update_descriptor_queue.AddBuffer(*buffer.handle, 0, staging_size);
+ update_descriptor_queue.AddBuffer(staging_ref.buffer, 0, staging_size);
const VkDescriptorSet set = CommitDescriptorSet(update_descriptor_queue);
scheduler.RequestOutsideRenderPassOperationContext();
- scheduler.Record([layout = *layout, pipeline = *pipeline, buffer = *buffer.handle, set,
+ scheduler.Record([layout = *layout, pipeline = *pipeline, buffer = staging_ref.buffer, set,
num_tri_vertices, base_vertex, index_shift](vk::CommandBuffer cmdbuf) {
static constexpr u32 dispatch_size = 1024;
const std::array push_constants = {base_vertex, index_shift};
@@ -317,7 +317,7 @@ std::pair<VkBuffer, u64> QuadIndexedPass::Assemble(
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, {}, barrier, {});
});
- return {*buffer.handle, 0};
+ return {staging_ref.buffer, 0};
}
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h
index 7ddb09afb..f5c6f5f17 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.h
@@ -16,8 +16,8 @@
namespace Vulkan {
class Device;
+class StagingBufferPool;
class VKScheduler;
-class VKStagingBufferPool;
class VKUpdateDescriptorQueue;
class VKComputePass {
@@ -45,7 +45,7 @@ class QuadArrayPass final : public VKComputePass {
public:
explicit QuadArrayPass(const Device& device_, VKScheduler& scheduler_,
VKDescriptorPool& descriptor_pool_,
- VKStagingBufferPool& staging_buffer_pool_,
+ StagingBufferPool& staging_buffer_pool_,
VKUpdateDescriptorQueue& update_descriptor_queue_);
~QuadArrayPass();
@@ -53,15 +53,14 @@ public:
private:
VKScheduler& scheduler;
- VKStagingBufferPool& staging_buffer_pool;
+ StagingBufferPool& staging_buffer_pool;
VKUpdateDescriptorQueue& update_descriptor_queue;
};
class Uint8Pass final : public VKComputePass {
public:
explicit Uint8Pass(const Device& device_, VKScheduler& scheduler_,
- VKDescriptorPool& descriptor_pool_,
- VKStagingBufferPool& staging_buffer_pool_,
+ VKDescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_,
VKUpdateDescriptorQueue& update_descriptor_queue_);
~Uint8Pass();
@@ -69,7 +68,7 @@ public:
private:
VKScheduler& scheduler;
- VKStagingBufferPool& staging_buffer_pool;
+ StagingBufferPool& staging_buffer_pool;
VKUpdateDescriptorQueue& update_descriptor_queue;
};
@@ -77,7 +76,7 @@ class QuadIndexedPass final : public VKComputePass {
public:
explicit QuadIndexedPass(const Device& device_, VKScheduler& scheduler_,
VKDescriptorPool& descriptor_pool_,
- VKStagingBufferPool& staging_buffer_pool_,
+ StagingBufferPool& staging_buffer_pool_,
VKUpdateDescriptorQueue& update_descriptor_queue_);
~QuadIndexedPass();
@@ -87,7 +86,7 @@ public:
private:
VKScheduler& scheduler;
- VKStagingBufferPool& staging_buffer_pool;
+ StagingBufferPool& staging_buffer_pool;
VKUpdateDescriptorQueue& update_descriptor_queue;
};
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.cpp b/src/video_core/renderer_vulkan/vk_fence_manager.cpp
index 4c5bc0aa1..6cd00884d 100644
--- a/src/video_core/renderer_vulkan/vk_fence_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_fence_manager.cpp
@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include <memory>
-#include <thread>
#include "video_core/renderer_vulkan/vk_buffer_cache.h"
#include "video_core/renderer_vulkan/vk_fence_manager.h"
@@ -14,13 +13,11 @@
namespace Vulkan {
-InnerFence::InnerFence(const Device& device_, VKScheduler& scheduler_, u32 payload_,
- bool is_stubbed_)
- : FenceBase{payload_, is_stubbed_}, device{device_}, scheduler{scheduler_} {}
+InnerFence::InnerFence(VKScheduler& scheduler_, u32 payload_, bool is_stubbed_)
+ : FenceBase{payload_, is_stubbed_}, scheduler{scheduler_} {}
-InnerFence::InnerFence(const Device& device_, VKScheduler& scheduler_, GPUVAddr address_,
- u32 payload_, bool is_stubbed_)
- : FenceBase{address_, payload_, is_stubbed_}, device{device_}, scheduler{scheduler_} {}
+InnerFence::InnerFence(VKScheduler& scheduler_, GPUVAddr address_, u32 payload_, bool is_stubbed_)
+ : FenceBase{address_, payload_, is_stubbed_}, scheduler{scheduler_} {}
InnerFence::~InnerFence() = default;
@@ -28,63 +25,38 @@ void InnerFence::Queue() {
if (is_stubbed) {
return;
}
- ASSERT(!event);
-
- event = device.GetLogical().CreateEvent();
- ticks = scheduler.CurrentTick();
-
- scheduler.RequestOutsideRenderPassOperationContext();
- scheduler.Record([event = *event](vk::CommandBuffer cmdbuf) {
- cmdbuf.SetEvent(event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
- });
+ // Get the current tick so we can wait for it
+ wait_tick = scheduler.CurrentTick();
+ scheduler.Flush();
}
bool InnerFence::IsSignaled() const {
if (is_stubbed) {
return true;
}
- ASSERT(event);
- return IsEventSignalled();
+ return scheduler.IsFree(wait_tick);
}
void InnerFence::Wait() {
if (is_stubbed) {
return;
}
- ASSERT(event);
-
- if (ticks >= scheduler.CurrentTick()) {
- scheduler.Flush();
- }
- while (!IsEventSignalled()) {
- std::this_thread::yield();
- }
-}
-
-bool InnerFence::IsEventSignalled() const {
- switch (const VkResult result = event.GetStatus()) {
- case VK_EVENT_SET:
- return true;
- case VK_EVENT_RESET:
- return false;
- default:
- throw vk::Exception(result);
- }
+ scheduler.Wait(wait_tick);
}
VKFenceManager::VKFenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::GPU& gpu_,
Tegra::MemoryManager& memory_manager_, TextureCache& texture_cache_,
VKBufferCache& buffer_cache_, VKQueryCache& query_cache_,
- const Device& device_, VKScheduler& scheduler_)
+ VKScheduler& scheduler_)
: GenericFenceManager{rasterizer_, gpu_, texture_cache_, buffer_cache_, query_cache_},
- device{device_}, scheduler{scheduler_} {}
+ scheduler{scheduler_} {}
Fence VKFenceManager::CreateFence(u32 value, bool is_stubbed) {
- return std::make_shared<InnerFence>(device, scheduler, value, is_stubbed);
+ return std::make_shared<InnerFence>(scheduler, value, is_stubbed);
}
Fence VKFenceManager::CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) {
- return std::make_shared<InnerFence>(device, scheduler, addr, value, is_stubbed);
+ return std::make_shared<InnerFence>(scheduler, addr, value, is_stubbed);
}
void VKFenceManager::QueueFence(Fence& fence) {
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.h b/src/video_core/renderer_vulkan/vk_fence_manager.h
index 6b51e4587..9c5e5aa8f 100644
--- a/src/video_core/renderer_vulkan/vk_fence_manager.h
+++ b/src/video_core/renderer_vulkan/vk_fence_manager.h
@@ -28,10 +28,8 @@ class VKScheduler;
class InnerFence : public VideoCommon::FenceBase {
public:
- explicit InnerFence(const Device& device_, VKScheduler& scheduler_, u32 payload_,
- bool is_stubbed_);
- explicit InnerFence(const Device& device_, VKScheduler& scheduler_, GPUVAddr address_,
- u32 payload_, bool is_stubbed_);
+ explicit InnerFence(VKScheduler& scheduler_, u32 payload_, bool is_stubbed_);
+ explicit InnerFence(VKScheduler& scheduler_, GPUVAddr address_, u32 payload_, bool is_stubbed_);
~InnerFence();
void Queue();
@@ -41,12 +39,8 @@ public:
void Wait();
private:
- bool IsEventSignalled() const;
-
- const Device& device;
VKScheduler& scheduler;
- vk::Event event;
- u64 ticks = 0;
+ u64 wait_tick = 0;
};
using Fence = std::shared_ptr<InnerFence>;
@@ -58,7 +52,7 @@ public:
explicit VKFenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::GPU& gpu_,
Tegra::MemoryManager& memory_manager_, TextureCache& texture_cache_,
VKBufferCache& buffer_cache_, VKQueryCache& query_cache_,
- const Device& device_, VKScheduler& scheduler_);
+ VKScheduler& scheduler_);
protected:
Fence CreateFence(u32 value, bool is_stubbed) override;
@@ -68,7 +62,6 @@ protected:
void WaitFence(Fence& fence) override;
private:
- const Device& device;
VKScheduler& scheduler;
};
diff --git a/src/video_core/renderer_vulkan/vk_memory_manager.cpp b/src/video_core/renderer_vulkan/vk_memory_manager.cpp
deleted file mode 100644
index a6abd0eee..000000000
--- a/src/video_core/renderer_vulkan/vk_memory_manager.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright 2018 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <optional>
-#include <tuple>
-#include <vector>
-
-#include "common/alignment.h"
-#include "common/assert.h"
-#include "common/common_types.h"
-#include "common/logging/log.h"
-#include "video_core/renderer_vulkan/vk_memory_manager.h"
-#include "video_core/vulkan_common/vulkan_device.h"
-#include "video_core/vulkan_common/vulkan_wrapper.h"
-
-namespace Vulkan {
-
-namespace {
-
-u64 GetAllocationChunkSize(u64 required_size) {
- static constexpr u64 sizes[] = {16ULL << 20, 32ULL << 20, 64ULL << 20, 128ULL << 20};
- auto it = std::lower_bound(std::begin(sizes), std::end(sizes), required_size);
- return it != std::end(sizes) ? *it : Common::AlignUp(required_size, 256ULL << 20);
-}
-
-} // Anonymous namespace
-
-class VKMemoryAllocation final {
-public:
- explicit VKMemoryAllocation(const Device& device_, vk::DeviceMemory memory_,
- VkMemoryPropertyFlags properties_, u64 allocation_size_, u32 type_)
- : device{device_}, memory{std::move(memory_)}, properties{properties_},
- allocation_size{allocation_size_}, shifted_type{ShiftType(type_)} {}
-
- VKMemoryCommit Commit(VkDeviceSize commit_size, VkDeviceSize alignment) {
- auto found = TryFindFreeSection(free_iterator, allocation_size,
- static_cast<u64>(commit_size), static_cast<u64>(alignment));
- if (!found) {
- found = TryFindFreeSection(0, free_iterator, static_cast<u64>(commit_size),
- static_cast<u64>(alignment));
- if (!found) {
- // Signal out of memory, it'll try to do more allocations.
- return nullptr;
- }
- }
- auto commit = std::make_unique<VKMemoryCommitImpl>(device, this, memory, *found,
- *found + commit_size);
- commits.push_back(commit.get());
-
- // Last commit's address is highly probable to be free.
- free_iterator = *found + commit_size;
-
- return commit;
- }
-
- void Free(const VKMemoryCommitImpl* commit) {
- ASSERT(commit);
-
- const auto it = std::find(std::begin(commits), std::end(commits), commit);
- if (it == commits.end()) {
- UNREACHABLE_MSG("Freeing unallocated commit!");
- return;
- }
- commits.erase(it);
- }
-
- /// Returns whether this allocation is compatible with the arguments.
- bool IsCompatible(VkMemoryPropertyFlags wanted_properties, u32 type_mask) const {
- return (wanted_properties & properties) && (type_mask & shifted_type) != 0;
- }
-
-private:
- static constexpr u32 ShiftType(u32 type) {
- return 1U << type;
- }
-
- /// A memory allocator, it may return a free region between "start" and "end" with the solicited
- /// requirements.
- std::optional<u64> TryFindFreeSection(u64 start, u64 end, u64 size, u64 alignment) const {
- u64 iterator = Common::AlignUp(start, alignment);
- while (iterator + size <= end) {
- const u64 try_left = iterator;
- const u64 try_right = try_left + size;
-
- bool overlap = false;
- for (const auto& commit : commits) {
- const auto [commit_left, commit_right] = commit->interval;
- if (try_left < commit_right && commit_left < try_right) {
- // There's an overlap, continue the search where the overlapping commit ends.
- iterator = Common::AlignUp(commit_right, alignment);
- overlap = true;
- break;
- }
- }
- if (!overlap) {
- // A free address has been found.
- return try_left;
- }
- }
-
- // No free regions where found, return an empty optional.
- return std::nullopt;
- }
-
- const Device& device; ///< Vulkan device.
- const vk::DeviceMemory memory; ///< Vulkan memory allocation handler.
- const VkMemoryPropertyFlags properties; ///< Vulkan properties.
- const u64 allocation_size; ///< Size of this allocation.
- const u32 shifted_type; ///< Stored Vulkan type of this allocation, shifted.
-
- /// Hints where the next free region is likely going to be.
- u64 free_iterator{};
-
- /// Stores all commits done from this allocation.
- std::vector<const VKMemoryCommitImpl*> commits;
-};
-
-VKMemoryManager::VKMemoryManager(const Device& device_)
- : device{device_}, properties{device_.GetPhysical().GetMemoryProperties()} {}
-
-VKMemoryManager::~VKMemoryManager() = default;
-
-VKMemoryCommit VKMemoryManager::Commit(const VkMemoryRequirements& requirements,
- bool host_visible) {
- const u64 chunk_size = GetAllocationChunkSize(requirements.size);
-
- // When a host visible commit is asked, search for host visible and coherent, otherwise search
- // for a fast device local type.
- const VkMemoryPropertyFlags wanted_properties =
- host_visible ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
- : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
-
- if (auto commit = TryAllocCommit(requirements, wanted_properties)) {
- return commit;
- }
-
- // Commit has failed, allocate more memory.
- if (!AllocMemory(wanted_properties, requirements.memoryTypeBits, chunk_size)) {
- // TODO(Rodrigo): Handle these situations in some way like flushing to guest memory.
- // Allocation has failed, panic.
- UNREACHABLE_MSG("Ran out of VRAM!");
- return {};
- }
-
- // Commit again, this time it won't fail since there's a fresh allocation above. If it does,
- // there's a bug.
- auto commit = TryAllocCommit(requirements, wanted_properties);
- ASSERT(commit);
- return commit;
-}
-
-VKMemoryCommit VKMemoryManager::Commit(const vk::Buffer& buffer, bool host_visible) {
- auto commit = Commit(device.GetLogical().GetBufferMemoryRequirements(*buffer), host_visible);
- buffer.BindMemory(commit->GetMemory(), commit->GetOffset());
- return commit;
-}
-
-VKMemoryCommit VKMemoryManager::Commit(const vk::Image& image, bool host_visible) {
- auto commit = Commit(device.GetLogical().GetImageMemoryRequirements(*image), host_visible);
- image.BindMemory(commit->GetMemory(), commit->GetOffset());
- return commit;
-}
-
-bool VKMemoryManager::AllocMemory(VkMemoryPropertyFlags wanted_properties, u32 type_mask,
- u64 size) {
- const u32 type = [&] {
- for (u32 type_index = 0; type_index < properties.memoryTypeCount; ++type_index) {
- const auto flags = properties.memoryTypes[type_index].propertyFlags;
- if ((type_mask & (1U << type_index)) && (flags & wanted_properties)) {
- // The type matches in type and in the wanted properties.
- return type_index;
- }
- }
- UNREACHABLE_MSG("Couldn't find a compatible memory type!");
- return 0U;
- }();
-
- // Try to allocate found type.
- vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- .pNext = nullptr,
- .allocationSize = size,
- .memoryTypeIndex = type,
- });
- if (!memory) {
- LOG_CRITICAL(Render_Vulkan, "Device allocation failed!");
- return false;
- }
-
- allocations.push_back(std::make_unique<VKMemoryAllocation>(device, std::move(memory),
- wanted_properties, size, type));
- return true;
-}
-
-VKMemoryCommit VKMemoryManager::TryAllocCommit(const VkMemoryRequirements& requirements,
- VkMemoryPropertyFlags wanted_properties) {
- for (auto& allocation : allocations) {
- if (!allocation->IsCompatible(wanted_properties, requirements.memoryTypeBits)) {
- continue;
- }
- if (auto commit = allocation->Commit(requirements.size, requirements.alignment)) {
- return commit;
- }
- }
- return {};
-}
-
-VKMemoryCommitImpl::VKMemoryCommitImpl(const Device& device_, VKMemoryAllocation* allocation_,
- const vk::DeviceMemory& memory_, u64 begin_, u64 end_)
- : device{device_}, memory{memory_}, interval{begin_, end_}, allocation{allocation_} {}
-
-VKMemoryCommitImpl::~VKMemoryCommitImpl() {
- allocation->Free(this);
-}
-
-MemoryMap VKMemoryCommitImpl::Map(u64 size, u64 offset_) const {
- return MemoryMap(this, std::span<u8>(memory.Map(interval.first + offset_, size), size));
-}
-
-void VKMemoryCommitImpl::Unmap() const {
- memory.Unmap();
-}
-
-MemoryMap VKMemoryCommitImpl::Map() const {
- return Map(interval.second - interval.first);
-}
-
-} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_memory_manager.h b/src/video_core/renderer_vulkan/vk_memory_manager.h
deleted file mode 100644
index 2452bca4e..000000000
--- a/src/video_core/renderer_vulkan/vk_memory_manager.h
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2019 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include <span>
-#include <utility>
-#include <vector>
-#include "common/common_types.h"
-#include "video_core/vulkan_common/vulkan_wrapper.h"
-
-namespace Vulkan {
-
-class Device;
-class MemoryMap;
-class VKMemoryAllocation;
-class VKMemoryCommitImpl;
-
-using VKMemoryCommit = std::unique_ptr<VKMemoryCommitImpl>;
-
-class VKMemoryManager final {
-public:
- explicit VKMemoryManager(const Device& device_);
- VKMemoryManager(const VKMemoryManager&) = delete;
- ~VKMemoryManager();
-
- /**
- * Commits a memory with the specified requeriments.
- * @param requirements Requirements returned from a Vulkan call.
- * @param host_visible Signals the allocator that it *must* use host visible and coherent
- * memory. When passing false, it will try to allocate device local memory.
- * @returns A memory commit.
- */
- VKMemoryCommit Commit(const VkMemoryRequirements& requirements, bool host_visible);
-
- /// Commits memory required by the buffer and binds it.
- VKMemoryCommit Commit(const vk::Buffer& buffer, bool host_visible);
-
- /// Commits memory required by the image and binds it.
- VKMemoryCommit Commit(const vk::Image& image, bool host_visible);
-
-private:
- /// Allocates a chunk of memory.
- bool AllocMemory(VkMemoryPropertyFlags wanted_properties, u32 type_mask, u64 size);
-
- /// Tries to allocate a memory commit.
- VKMemoryCommit TryAllocCommit(const VkMemoryRequirements& requirements,
- VkMemoryPropertyFlags wanted_properties);
-
- const Device& device; ///< Device handler.
- const VkPhysicalDeviceMemoryProperties properties; ///< Physical device properties.
- std::vector<std::unique_ptr<VKMemoryAllocation>> allocations; ///< Current allocations.
-};
-
-class VKMemoryCommitImpl final {
- friend VKMemoryAllocation;
- friend MemoryMap;
-
-public:
- explicit VKMemoryCommitImpl(const Device& device_, VKMemoryAllocation* allocation_,
- const vk::DeviceMemory& memory_, u64 begin_, u64 end_);
- ~VKMemoryCommitImpl();
-
- /// Maps a memory region and returns a pointer to it.
- /// It's illegal to have more than one memory map at the same time.
- MemoryMap Map(u64 size, u64 offset = 0) const;
-
- /// Maps the whole commit and returns a pointer to it.
- /// It's illegal to have more than one memory map at the same time.
- MemoryMap Map() const;
-
- /// Returns the Vulkan memory handler.
- VkDeviceMemory GetMemory() const {
- return *memory;
- }
-
- /// Returns the start position of the commit relative to the allocation.
- VkDeviceSize GetOffset() const {
- return static_cast<VkDeviceSize>(interval.first);
- }
-
-private:
- /// Unmaps memory.
- void Unmap() const;
-
- const Device& device; ///< Vulkan device.
- const vk::DeviceMemory& memory; ///< Vulkan device memory handler.
- std::pair<u64, u64> interval{}; ///< Interval where the commit exists.
- VKMemoryAllocation* allocation{}; ///< Pointer to the large memory allocation.
-};
-
-/// Holds ownership of a memory map.
-class MemoryMap final {
-public:
- explicit MemoryMap(const VKMemoryCommitImpl* commit_, std::span<u8> span_)
- : commit{commit_}, span{span_} {}
-
- ~MemoryMap() {
- if (commit) {
- commit->Unmap();
- }
- }
-
- /// Prematurely releases the memory map.
- void Release() {
- commit->Unmap();
- commit = nullptr;
- }
-
- /// Returns a span to the memory map.
- [[nodiscard]] std::span<u8> Span() const noexcept {
- return span;
- }
-
- /// Returns the address of the memory map.
- [[nodiscard]] u8* Address() const noexcept {
- return span.data();
- }
-
- /// Returns the address of the memory map;
- [[nodiscard]] operator u8*() const noexcept {
- return span.data();
- }
-
-private:
- const VKMemoryCommitImpl* commit{}; ///< Mapped memory commit.
- std::span<u8> span; ///< Address to the mapped memory.
-};
-
-} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 93fbea510..f0a111829 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -409,27 +409,26 @@ void RasterizerVulkan::DrawParameters::Draw(vk::CommandBuffer cmdbuf) const {
RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
Tegra::MemoryManager& gpu_memory_,
Core::Memory::Memory& cpu_memory_, VKScreenInfo& screen_info_,
- const Device& device_, VKMemoryManager& memory_manager_,
+ const Device& device_, MemoryAllocator& memory_allocator_,
StateTracker& state_tracker_, VKScheduler& scheduler_)
: RasterizerAccelerated{cpu_memory_}, gpu{gpu_},
gpu_memory{gpu_memory_}, maxwell3d{gpu.Maxwell3D()}, kepler_compute{gpu.KeplerCompute()},
- screen_info{screen_info_}, device{device_}, memory_manager{memory_manager_},
+ screen_info{screen_info_}, device{device_}, memory_allocator{memory_allocator_},
state_tracker{state_tracker_}, scheduler{scheduler_}, stream_buffer(device, scheduler),
- staging_pool(device, memory_manager, scheduler), descriptor_pool(device, scheduler),
+ staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler),
update_descriptor_queue(device, scheduler),
blit_image(device, scheduler, state_tracker, descriptor_pool),
quad_array_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
quad_indexed_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
- texture_cache_runtime{device, scheduler, memory_manager, staging_pool, blit_image},
+ texture_cache_runtime{device, scheduler, memory_allocator, staging_pool, blit_image},
texture_cache(texture_cache_runtime, *this, maxwell3d, kepler_compute, gpu_memory),
pipeline_cache(*this, gpu, maxwell3d, kepler_compute, gpu_memory, device, scheduler,
descriptor_pool, update_descriptor_queue),
- buffer_cache(*this, gpu_memory, cpu_memory_, device, memory_manager, scheduler, stream_buffer,
- staging_pool),
+ buffer_cache(*this, gpu_memory, cpu_memory_, device, memory_allocator, scheduler,
+ stream_buffer, staging_pool),
query_cache{*this, maxwell3d, gpu_memory, device, scheduler},
- fence_manager(*this, gpu, gpu_memory, texture_cache, buffer_cache, query_cache, device,
- scheduler),
+ fence_manager(*this, gpu, gpu_memory, texture_cache, buffer_cache, query_cache, scheduler),
wfi_event(device.GetLogical().CreateEvent()), async_shaders(emu_window_) {
scheduler.SetQueryCache(query_cache);
if (device.UseAsynchronousShaders()) {
@@ -1446,7 +1445,7 @@ VkBuffer RasterizerVulkan::DefaultBuffer() {
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
});
- default_buffer_commit = memory_manager.Commit(default_buffer, false);
+ default_buffer_commit = memory_allocator.Commit(default_buffer, MemoryUsage::DeviceLocal);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([buffer = *default_buffer](vk::CommandBuffer cmdbuf) {
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index 4695718e9..8e261b9bd 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -21,7 +21,6 @@
#include "video_core/renderer_vulkan/vk_compute_pass.h"
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
#include "video_core/renderer_vulkan/vk_fence_manager.h"
-#include "video_core/renderer_vulkan/vk_memory_manager.h"
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
#include "video_core/renderer_vulkan/vk_query_cache.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
@@ -30,6 +29,7 @@
#include "video_core/renderer_vulkan/vk_texture_cache.h"
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
#include "video_core/shader/async_shaders.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Core {
@@ -56,7 +56,7 @@ public:
explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
Tegra::MemoryManager& gpu_memory_, Core::Memory::Memory& cpu_memory_,
VKScreenInfo& screen_info_, const Device& device_,
- VKMemoryManager& memory_manager_, StateTracker& state_tracker_,
+ MemoryAllocator& memory_allocator_, StateTracker& state_tracker_,
VKScheduler& scheduler_);
~RasterizerVulkan() override;
@@ -213,12 +213,12 @@ private:
VKScreenInfo& screen_info;
const Device& device;
- VKMemoryManager& memory_manager;
+ MemoryAllocator& memory_allocator;
StateTracker& state_tracker;
VKScheduler& scheduler;
VKStreamBuffer stream_buffer;
- VKStagingBufferPool staging_pool;
+ StagingBufferPool staging_pool;
VKDescriptorPool descriptor_pool;
VKUpdateDescriptorQueue update_descriptor_queue;
BlitImageHelper blit_image;
@@ -234,7 +234,7 @@ private:
VKFenceManager fence_manager;
vk::Buffer default_buffer;
- VKMemoryCommit default_buffer_commit;
+ MemoryCommit default_buffer_commit;
vk::Event wfi_event;
VideoCommon::Shader::AsyncShaders async_shaders;
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
index 1e0b8b922..97fd41cc1 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
@@ -3,10 +3,12 @@
// Refer to the license.txt file included.
#include <algorithm>
-#include <unordered_map>
#include <utility>
#include <vector>
+#include <fmt/format.h>
+
+#include "common/assert.h"
#include "common/bit_util.h"
#include "common/common_types.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
@@ -16,45 +18,51 @@
namespace Vulkan {
-VKStagingBufferPool::StagingBuffer::StagingBuffer(std::unique_ptr<VKBuffer> buffer_)
- : buffer{std::move(buffer_)} {}
-
-VKStagingBufferPool::VKStagingBufferPool(const Device& device_, VKMemoryManager& memory_manager_,
- VKScheduler& scheduler_)
- : device{device_}, memory_manager{memory_manager_}, scheduler{scheduler_} {}
+StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_,
+ VKScheduler& scheduler_)
+ : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} {}
-VKStagingBufferPool::~VKStagingBufferPool() = default;
+StagingBufferPool::~StagingBufferPool() = default;
-VKBuffer& VKStagingBufferPool::GetUnusedBuffer(std::size_t size, bool host_visible) {
- if (const auto buffer = TryGetReservedBuffer(size, host_visible)) {
- return *buffer;
+StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage) {
+ if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage)) {
+ return *ref;
}
- return CreateStagingBuffer(size, host_visible);
+ return CreateStagingBuffer(size, usage);
}
-void VKStagingBufferPool::TickFrame() {
- current_delete_level = (current_delete_level + 1) % NumLevels;
+void StagingBufferPool::TickFrame() {
+ current_delete_level = (current_delete_level + 1) % NUM_LEVELS;
- ReleaseCache(true);
- ReleaseCache(false);
+ ReleaseCache(MemoryUsage::DeviceLocal);
+ ReleaseCache(MemoryUsage::Upload);
+ ReleaseCache(MemoryUsage::Download);
}
-VKBuffer* VKStagingBufferPool::TryGetReservedBuffer(std::size_t size, bool host_visible) {
- for (StagingBuffer& entry : GetCache(host_visible)[Common::Log2Ceil64(size)].entries) {
- if (!scheduler.IsFree(entry.tick)) {
- continue;
+std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size,
+ MemoryUsage usage) {
+ StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil64(size)];
+
+ const auto is_free = [this](const StagingBuffer& entry) {
+ return scheduler.IsFree(entry.tick);
+ };
+ auto& entries = cache_level.entries;
+ const auto hint_it = entries.begin() + cache_level.iterate_index;
+ auto it = std::find_if(entries.begin() + cache_level.iterate_index, entries.end(), is_free);
+ if (it == entries.end()) {
+ it = std::find_if(entries.begin(), hint_it, is_free);
+ if (it == hint_it) {
+ return std::nullopt;
}
- entry.tick = scheduler.CurrentTick();
- return &*entry.buffer;
}
- return nullptr;
+ cache_level.iterate_index = std::distance(entries.begin(), it) + 1;
+ it->tick = scheduler.CurrentTick();
+ return it->Ref();
}
-VKBuffer& VKStagingBufferPool::CreateStagingBuffer(std::size_t size, bool host_visible) {
+StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage) {
const u32 log2 = Common::Log2Ceil64(size);
-
- auto buffer = std::make_unique<VKBuffer>();
- buffer->handle = device.GetLogical().CreateBuffer({
+ vk::Buffer buffer = device.GetLogical().CreateBuffer({
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
@@ -66,49 +74,63 @@ VKBuffer& VKStagingBufferPool::CreateStagingBuffer(std::size_t size, bool host_v
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
});
- buffer->commit = memory_manager.Commit(buffer->handle, host_visible);
-
- std::vector<StagingBuffer>& entries = GetCache(host_visible)[log2].entries;
- StagingBuffer& entry = entries.emplace_back(std::move(buffer));
- entry.tick = scheduler.CurrentTick();
- return *entry.buffer;
-}
-
-VKStagingBufferPool::StagingBuffersCache& VKStagingBufferPool::GetCache(bool host_visible) {
- return host_visible ? host_staging_buffers : device_staging_buffers;
+ if (device.HasDebuggingToolAttached()) {
+ ++buffer_index;
+ buffer.SetObjectNameEXT(fmt::format("Staging Buffer {}", buffer_index).c_str());
+ }
+ MemoryCommit commit = memory_allocator.Commit(buffer, usage);
+ const std::span<u8> mapped_span = IsHostVisible(usage) ? commit.Map() : std::span<u8>{};
+
+ StagingBuffer& entry = GetCache(usage)[log2].entries.emplace_back(StagingBuffer{
+ .buffer = std::move(buffer),
+ .commit = std::move(commit),
+ .mapped_span = mapped_span,
+ .tick = scheduler.CurrentTick(),
+ });
+ return entry.Ref();
}
-void VKStagingBufferPool::ReleaseCache(bool host_visible) {
- auto& cache = GetCache(host_visible);
- const u64 size = ReleaseLevel(cache, current_delete_level);
- if (size == 0) {
- return;
+StagingBufferPool::StagingBuffersCache& StagingBufferPool::GetCache(MemoryUsage usage) {
+ switch (usage) {
+ case MemoryUsage::DeviceLocal:
+ return device_local_cache;
+ case MemoryUsage::Upload:
+ return upload_cache;
+ case MemoryUsage::Download:
+ return download_cache;
+ default:
+ UNREACHABLE_MSG("Invalid memory usage={}", usage);
+ return upload_cache;
}
}
-u64 VKStagingBufferPool::ReleaseLevel(StagingBuffersCache& cache, std::size_t log2) {
- static constexpr std::size_t deletions_per_tick = 16;
+void StagingBufferPool::ReleaseCache(MemoryUsage usage) {
+ ReleaseLevel(GetCache(usage), current_delete_level);
+}
+void StagingBufferPool::ReleaseLevel(StagingBuffersCache& cache, size_t log2) {
+ constexpr size_t deletions_per_tick = 16;
auto& staging = cache[log2];
auto& entries = staging.entries;
- const std::size_t old_size = entries.size();
+ const size_t old_size = entries.size();
const auto is_deleteable = [this](const StagingBuffer& entry) {
return scheduler.IsFree(entry.tick);
};
- const std::size_t begin_offset = staging.delete_index;
- const std::size_t end_offset = std::min(begin_offset + deletions_per_tick, old_size);
- const auto begin = std::begin(entries) + begin_offset;
- const auto end = std::begin(entries) + end_offset;
+ const size_t begin_offset = staging.delete_index;
+ const size_t end_offset = std::min(begin_offset + deletions_per_tick, old_size);
+ const auto begin = entries.begin() + begin_offset;
+ const auto end = entries.begin() + end_offset;
entries.erase(std::remove_if(begin, end, is_deleteable), end);
- const std::size_t new_size = entries.size();
+ const size_t new_size = entries.size();
staging.delete_index += deletions_per_tick;
if (staging.delete_index >= new_size) {
staging.delete_index = 0;
}
-
- return (1ULL << log2) * (old_size - new_size);
+ if (staging.iterate_index > new_size) {
+ staging.iterate_index = 0;
+ }
}
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
index 90dadcbbe..d42918a47 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
@@ -9,7 +9,7 @@
#include "common/common_types.h"
-#include "video_core/renderer_vulkan/vk_memory_manager.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan {
@@ -17,55 +17,65 @@ namespace Vulkan {
class Device;
class VKScheduler;
-struct VKBuffer final {
- vk::Buffer handle;
- VKMemoryCommit commit;
+struct StagingBufferRef {
+ VkBuffer buffer;
+ std::span<u8> mapped_span;
};
-class VKStagingBufferPool final {
+class StagingBufferPool {
public:
- explicit VKStagingBufferPool(const Device& device, VKMemoryManager& memory_manager,
- VKScheduler& scheduler);
- ~VKStagingBufferPool();
+ explicit StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator,
+ VKScheduler& scheduler);
+ ~StagingBufferPool();
- VKBuffer& GetUnusedBuffer(std::size_t size, bool host_visible);
+ StagingBufferRef Request(size_t size, MemoryUsage usage);
void TickFrame();
private:
- struct StagingBuffer final {
- explicit StagingBuffer(std::unique_ptr<VKBuffer> buffer);
-
- std::unique_ptr<VKBuffer> buffer;
+ struct StagingBuffer {
+ vk::Buffer buffer;
+ MemoryCommit commit;
+ std::span<u8> mapped_span;
u64 tick = 0;
+
+ StagingBufferRef Ref() const noexcept {
+ return {
+ .buffer = *buffer,
+ .mapped_span = mapped_span,
+ };
+ }
};
- struct StagingBuffers final {
+ struct StagingBuffers {
std::vector<StagingBuffer> entries;
- std::size_t delete_index = 0;
+ size_t delete_index = 0;
+ size_t iterate_index = 0;
};
- static constexpr std::size_t NumLevels = sizeof(std::size_t) * CHAR_BIT;
- using StagingBuffersCache = std::array<StagingBuffers, NumLevels>;
+ static constexpr size_t NUM_LEVELS = sizeof(size_t) * CHAR_BIT;
+ using StagingBuffersCache = std::array<StagingBuffers, NUM_LEVELS>;
- VKBuffer* TryGetReservedBuffer(std::size_t size, bool host_visible);
+ std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage);
- VKBuffer& CreateStagingBuffer(std::size_t size, bool host_visible);
+ StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage);
- StagingBuffersCache& GetCache(bool host_visible);
+ StagingBuffersCache& GetCache(MemoryUsage usage);
- void ReleaseCache(bool host_visible);
+ void ReleaseCache(MemoryUsage usage);
- u64 ReleaseLevel(StagingBuffersCache& cache, std::size_t log2);
+ void ReleaseLevel(StagingBuffersCache& cache, size_t log2);
const Device& device;
- VKMemoryManager& memory_manager;
+ MemoryAllocator& memory_allocator;
VKScheduler& scheduler;
- StagingBuffersCache host_staging_buffers;
- StagingBuffersCache device_staging_buffers;
+ StagingBuffersCache device_local_cache;
+ StagingBuffersCache upload_cache;
+ StagingBuffersCache download_cache;
- std::size_t current_delete_level = 0;
+ size_t current_delete_level = 0;
+ u64 buffer_index = 0;
};
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index bd11de012..ab14922d7 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -10,12 +10,12 @@
#include "video_core/engines/fermi_2d.h"
#include "video_core/renderer_vulkan/blit_image.h"
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
-#include "video_core/renderer_vulkan/vk_memory_manager.h"
#include "video_core/renderer_vulkan/vk_rasterizer.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
#include "video_core/renderer_vulkan/vk_texture_cache.h"
#include "video_core/vulkan_common/vulkan_device.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan {
@@ -554,10 +554,18 @@ void TextureCacheRuntime::Finish() {
}
ImageBufferMap TextureCacheRuntime::MapUploadBuffer(size_t size) {
- const auto& buffer = staging_buffer_pool.GetUnusedBuffer(size, true);
- return ImageBufferMap{
- .handle = *buffer.handle,
- .map = buffer.commit->Map(size),
+ const auto staging_ref = staging_buffer_pool.Request(size, MemoryUsage::Upload);
+ return {
+ .handle = staging_ref.buffer,
+ .span = staging_ref.mapped_span,
+ };
+}
+
+ImageBufferMap TextureCacheRuntime::MapDownloadBuffer(size_t size) {
+ const auto staging_ref = staging_buffer_pool.Request(size, MemoryUsage::Download);
+ return {
+ .handle = staging_ref.buffer,
+ .span = staging_ref.mapped_span,
};
}
@@ -788,9 +796,9 @@ Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_
image(MakeImage(runtime.device, info)), buffer(MakeBuffer(runtime.device, info)),
aspect_mask(ImageAspectMask(info.format)) {
if (image) {
- commit = runtime.memory_manager.Commit(image, false);
+ commit = runtime.memory_allocator.Commit(image, MemoryUsage::DeviceLocal);
} else {
- commit = runtime.memory_manager.Commit(buffer, false);
+ commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
}
if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) {
flags |= VideoCommon::ImageFlagBits::Converted;
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 92a7aad8b..a55d405d1 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -7,8 +7,8 @@
#include <compare>
#include <span>
-#include "video_core/renderer_vulkan/vk_memory_manager.h"
#include "video_core/texture_cache/texture_cache.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan {
@@ -19,14 +19,13 @@ using VideoCommon::Offset2D;
using VideoCommon::RenderTargets;
using VideoCore::Surface::PixelFormat;
-class VKScheduler;
-class VKStagingBufferPool;
-
class BlitImageHelper;
class Device;
class Image;
class ImageView;
class Framebuffer;
+class StagingBufferPool;
+class VKScheduler;
struct RenderPassKey {
constexpr auto operator<=>(const RenderPassKey&) const noexcept = default;
@@ -60,18 +59,18 @@ struct ImageBufferMap {
}
[[nodiscard]] std::span<u8> Span() const noexcept {
- return map.Span();
+ return span;
}
VkBuffer handle;
- MemoryMap map;
+ std::span<u8> span;
};
struct TextureCacheRuntime {
const Device& device;
VKScheduler& scheduler;
- VKMemoryManager& memory_manager;
- VKStagingBufferPool& staging_buffer_pool;
+ MemoryAllocator& memory_allocator;
+ StagingBufferPool& staging_buffer_pool;
BlitImageHelper& blit_image_helper;
std::unordered_map<RenderPassKey, vk::RenderPass> renderpass_cache;
@@ -79,10 +78,7 @@ struct TextureCacheRuntime {
[[nodiscard]] ImageBufferMap MapUploadBuffer(size_t size);
- [[nodiscard]] ImageBufferMap MapDownloadBuffer(size_t size) {
- // TODO: Have a special function for this
- return MapUploadBuffer(size);
- }
+ [[nodiscard]] ImageBufferMap MapDownloadBuffer(size_t size);
void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
const std::array<Offset2D, 2>& dst_region,
@@ -141,7 +137,7 @@ private:
VKScheduler* scheduler;
vk::Image image;
vk::Buffer buffer;
- VKMemoryCommit commit;
+ MemoryCommit commit;
VkImageAspectFlags aspect_mask = 0;
bool initialized = false;
};
diff --git a/src/video_core/texture_cache/accelerated_swizzle.cpp b/src/video_core/texture_cache/accelerated_swizzle.cpp
index a4fc1184b..15585caeb 100644
--- a/src/video_core/texture_cache/accelerated_swizzle.cpp
+++ b/src/video_core/texture_cache/accelerated_swizzle.cpp
@@ -27,7 +27,7 @@ BlockLinearSwizzle2DParams MakeBlockLinearSwizzle2DParams(const SwizzleParameter
const Extent3D num_tiles = swizzle.num_tiles;
const u32 bytes_per_block = BytesPerBlock(info.format);
const u32 stride_alignment = CalculateLevelStrideAlignment(info, swizzle.level);
- const u32 stride = Common::AlignBits(num_tiles.width, stride_alignment) * bytes_per_block;
+ const u32 stride = Common::AlignUpLog2(num_tiles.width, stride_alignment) * bytes_per_block;
const u32 gobs_in_x = Common::DivCeilLog2(stride, GOB_SIZE_X_SHIFT);
return BlockLinearSwizzle2DParams{
.origin{0, 0, 0},
@@ -47,7 +47,7 @@ BlockLinearSwizzle3DParams MakeBlockLinearSwizzle3DParams(const SwizzleParameter
const Extent3D num_tiles = swizzle.num_tiles;
const u32 bytes_per_block = BytesPerBlock(info.format);
const u32 stride_alignment = CalculateLevelStrideAlignment(info, swizzle.level);
- const u32 stride = Common::AlignBits(num_tiles.width, stride_alignment) * bytes_per_block;
+ const u32 stride = Common::AlignUpLog2(num_tiles.width, stride_alignment) * bytes_per_block;
const u32 gobs_in_x = (stride + GOB_SIZE_X - 1) >> GOB_SIZE_X_SHIFT;
const u32 block_size = gobs_in_x << (GOB_SIZE_SHIFT + block.height + block.depth);
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index 279932778..ce8fcfe0a 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -279,7 +279,7 @@ template <u32 GOB_EXTENT>
const bool is_small = IsSmallerThanGobSize(blocks, gob, info.block.depth);
const u32 alignment = is_small ? 0 : info.tile_width_spacing;
return Extent2D{
- .width = Common::AlignBits(gobs.width, alignment),
+ .width = Common::AlignUpLog2(gobs.width, alignment),
.height = gobs.height,
};
}
@@ -352,7 +352,7 @@ template <u32 GOB_EXTENT>
// https://github.com/Ryujinx/Ryujinx/blob/1c9aba6de1520aea5480c032e0ff5664ac1bb36f/Ryujinx.Graphics.Texture/SizeCalculator.cs#L134
if (tile_width_spacing > 0) {
const u32 alignment_log2 = GOB_SIZE_SHIFT + tile_width_spacing + block.height + block.depth;
- return Common::AlignBits(size_bytes, alignment_log2);
+ return Common::AlignUpLog2(size_bytes, alignment_log2);
}
const u32 aligned_height = Common::AlignUp(size.height, tile_size_y);
while (block.height != 0 && aligned_height <= (1U << (block.height - 1)) * GOB_SIZE_Y) {
@@ -528,9 +528,9 @@ template <u32 GOB_EXTENT>
const u32 alignment = StrideAlignment(num_tiles, info.block, bpp_log2, info.tile_width_spacing);
const Extent3D mip_block = AdjustMipBlockSize(num_tiles, info.block, 0);
return Extent3D{
- .width = Common::AlignBits(num_tiles.width, alignment),
- .height = Common::AlignBits(num_tiles.height, GOB_SIZE_Y_SHIFT + mip_block.height),
- .depth = Common::AlignBits(num_tiles.depth, GOB_SIZE_Z_SHIFT + mip_block.depth),
+ .width = Common::AlignUpLog2(num_tiles.width, alignment),
+ .height = Common::AlignUpLog2(num_tiles.height, GOB_SIZE_Y_SHIFT + mip_block.height),
+ .depth = Common::AlignUpLog2(num_tiles.depth, GOB_SIZE_Z_SHIFT + mip_block.depth),
};
}
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
index acd5bdd78..3625b666c 100644
--- a/src/video_core/textures/astc.cpp
+++ b/src/video_core/textures/astc.cpp
@@ -42,21 +42,24 @@ constexpr u32 Popcnt(u32 n) {
class InputBitStream {
public:
- constexpr explicit InputBitStream(const u8* ptr, std::size_t start_offset = 0)
- : cur_byte{ptr}, next_bit{start_offset % 8} {}
+ constexpr explicit InputBitStream(std::span<const u8> data, size_t start_offset = 0)
+ : cur_byte{data.data()}, total_bits{data.size()}, next_bit{start_offset % 8} {}
- constexpr std::size_t GetBitsRead() const {
+ constexpr size_t GetBitsRead() const {
return bits_read;
}
constexpr bool ReadBit() {
- const bool bit = (*cur_byte >> next_bit++) & 1;
+ if (bits_read >= total_bits * 8) {
+ return 0;
+ }
+ const bool bit = ((*cur_byte >> next_bit) & 1) != 0;
+ ++next_bit;
while (next_bit >= 8) {
next_bit -= 8;
- cur_byte++;
+ ++cur_byte;
}
-
- bits_read++;
+ ++bits_read;
return bit;
}
@@ -79,8 +82,9 @@ public:
private:
const u8* cur_byte;
- std::size_t next_bit = 0;
- std::size_t bits_read = 0;
+ size_t total_bits = 0;
+ size_t next_bit = 0;
+ size_t bits_read = 0;
};
class OutputBitStream {
@@ -193,15 +197,15 @@ struct IntegerEncodedValue {
};
};
using IntegerEncodedVector = boost::container::static_vector<
- IntegerEncodedValue, 64,
+ IntegerEncodedValue, 256,
boost::container::static_vector_options<
boost::container::inplace_alignment<alignof(IntegerEncodedValue)>,
boost::container::throw_on_overflow<false>>::type>;
static void DecodeTritBlock(InputBitStream& bits, IntegerEncodedVector& result, u32 nBitsPerValue) {
// Implement the algorithm in section C.2.12
- u32 m[5];
- u32 t[5];
+ std::array<u32, 5> m;
+ std::array<u32, 5> t;
u32 T;
// Read the trit encoded block according to
@@ -866,7 +870,7 @@ public:
}
};
-static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nPartitions,
+static void DecodeColorValues(u32* out, std::span<u8> data, const u32* modes, const u32 nPartitions,
const u32 nBitsForColorData) {
// First figure out how many color values we have
u32 nValues = 0;
@@ -898,7 +902,7 @@ static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nP
// We now have enough to decode our integer sequence.
IntegerEncodedVector decodedColorValues;
- InputBitStream colorStream(data);
+ InputBitStream colorStream(data, 0);
DecodeIntegerSequence(decodedColorValues, colorStream, range, nValues);
// Once we have the decoded values, we need to dequantize them to the 0-255 range
@@ -1441,7 +1445,7 @@ static void ComputeEndpos32s(Pixel& ep1, Pixel& ep2, const u32*& colorValues,
static void DecompressBlock(std::span<const u8, 16> inBuf, const u32 blockWidth,
const u32 blockHeight, std::span<u32, 12 * 12> outBuf) {
- InputBitStream strm(inBuf.data());
+ InputBitStream strm(inBuf);
TexelWeightParams weightParams = DecodeBlockInfo(strm);
// Was there an error?
@@ -1619,15 +1623,16 @@ static void DecompressBlock(std::span<const u8, 16> inBuf, const u32 blockWidth,
// Make sure that higher non-texel bits are set to zero
const u32 clearByteStart = (weightParams.GetPackedBitSize() >> 3) + 1;
- if (clearByteStart > 0) {
+ if (clearByteStart > 0 && clearByteStart <= texelWeightData.size()) {
texelWeightData[clearByteStart - 1] &=
static_cast<u8>((1 << (weightParams.GetPackedBitSize() % 8)) - 1);
+ std::memset(texelWeightData.data() + clearByteStart, 0,
+ std::min(16U - clearByteStart, 16U));
}
- std::memset(texelWeightData.data() + clearByteStart, 0, std::min(16U - clearByteStart, 16U));
IntegerEncodedVector texelWeightValues;
- InputBitStream weightStream(texelWeightData.data());
+ InputBitStream weightStream(texelWeightData);
DecodeIntegerSequence(texelWeightValues, weightStream, weightParams.m_MaxWeight,
weightParams.GetNumWeightValues());
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 9f5181318..62685a183 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -49,7 +49,7 @@ void Swizzle(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixe
// We can configure here a custom pitch
// As it's not exposed 'width * bpp' will be the expected pitch.
const u32 pitch = width * bytes_per_pixel;
- const u32 stride = Common::AlignBits(width, stride_alignment) * bytes_per_pixel;
+ const u32 stride = Common::AlignUpLog2(width, stride_alignment) * bytes_per_pixel;
const u32 gobs_in_x = Common::DivCeilLog2(stride, GOB_SIZE_X_SHIFT);
const u32 block_size = gobs_in_x << (GOB_SIZE_SHIFT + block_height + block_depth);
@@ -217,9 +217,9 @@ void SwizzleKepler(const u32 width, const u32 height, const u32 dst_x, const u32
std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
u32 block_height, u32 block_depth) {
if (tiled) {
- const u32 aligned_width = Common::AlignBits(width * bytes_per_pixel, GOB_SIZE_X_SHIFT);
- const u32 aligned_height = Common::AlignBits(height, GOB_SIZE_Y_SHIFT + block_height);
- const u32 aligned_depth = Common::AlignBits(depth, GOB_SIZE_Z_SHIFT + block_depth);
+ const u32 aligned_width = Common::AlignUpLog2(width * bytes_per_pixel, GOB_SIZE_X_SHIFT);
+ const u32 aligned_height = Common::AlignUpLog2(height, GOB_SIZE_Y_SHIFT + block_height);
+ const u32 aligned_depth = Common::AlignUpLog2(depth, GOB_SIZE_Z_SHIFT + block_depth);
return aligned_width * aligned_height * aligned_depth;
} else {
return width * height * depth * bytes_per_pixel;
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 75173324e..37d7b45a3 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -99,8 +99,7 @@ VkFormatFeatureFlags GetFormatFeatures(VkFormatProperties properties, FormatType
});
}
-std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
- vk::PhysicalDevice physical, const vk::InstanceDispatch& dld) {
+std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::PhysicalDevice physical) {
static constexpr std::array formats{
VK_FORMAT_A8B8G8R8_UNORM_PACK32,
VK_FORMAT_A8B8G8R8_UINT_PACK32,
@@ -210,7 +209,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface,
const vk::InstanceDispatch& dld_)
: instance{instance_}, dld{dld_}, physical{physical_}, properties{physical.GetProperties()},
- format_properties{GetFormatProperties(physical, dld)} {
+ format_properties{GetFormatProperties(physical)} {
CheckSuitability();
SetupFamilies(surface);
SetupFeatures();
@@ -221,6 +220,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
VkPhysicalDeviceFeatures2 features2{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
.pNext = nullptr,
+ .features{},
};
const void* first_next = &features2;
void** next = &features2.pNext;
@@ -256,7 +256,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
.shaderTessellationAndGeometryPointSize = false,
.shaderImageGatherExtended = true,
.shaderStorageImageExtendedFormats = false,
- .shaderStorageImageMultisample = true,
+ .shaderStorageImageMultisample = is_shader_storage_image_multisample,
.shaderStorageImageReadWithoutFormat = is_formatless_image_load_supported,
.shaderStorageImageWriteWithoutFormat = true,
.shaderUniformBufferArrayDynamicIndexing = false,
@@ -310,6 +310,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT,
+ .pNext = nullptr,
.hostQueryReset = true,
};
SetNext(next, host_query_reset);
@@ -604,7 +605,6 @@ void Device::CheckSuitability() const {
std::make_pair(features.occlusionQueryPrecise, "occlusionQueryPrecise"),
std::make_pair(features.fragmentStoresAndAtomics, "fragmentStoresAndAtomics"),
std::make_pair(features.shaderImageGatherExtended, "shaderImageGatherExtended"),
- std::make_pair(features.shaderStorageImageMultisample, "shaderStorageImageMultisample"),
std::make_pair(features.shaderStorageImageWriteWithoutFormat,
"shaderStorageImageWriteWithoutFormat"),
};
@@ -804,6 +804,7 @@ void Device::SetupFamilies(VkSurfaceKHR surface) {
void Device::SetupFeatures() {
const auto supported_features{physical.GetFeatures()};
is_formatless_image_load_supported = supported_features.shaderStorageImageReadWithoutFormat;
+ is_shader_storage_image_multisample = supported_features.shaderStorageImageMultisample;
is_blit_depth_stencil_supported = TestDepthStencilBlits();
is_optimal_astc_supported = IsOptimalAstcSupported(supported_features);
}
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index a973c3ce4..4b66dba7a 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -272,23 +272,24 @@ private:
bool is_optimal_astc_supported{}; ///< Support for native ASTC.
bool is_float16_supported{}; ///< Support for float16 arithmetics.
bool is_warp_potentially_bigger{}; ///< Host warp size can be bigger than guest.
- bool is_formatless_image_load_supported{}; ///< Support for shader image read without format.
- bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil.
- bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle.
- bool khr_uniform_buffer_standard_layout{}; ///< Support for std430 on UBOs.
- bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8.
- bool ext_sampler_filter_minmax{}; ///< Support for VK_EXT_sampler_filter_minmax.
- bool ext_depth_range_unrestricted{}; ///< Support for VK_EXT_depth_range_unrestricted.
- bool ext_shader_viewport_index_layer{}; ///< Support for VK_EXT_shader_viewport_index_layer.
- bool ext_tooling_info{}; ///< Support for VK_EXT_tooling_info.
- bool ext_transform_feedback{}; ///< Support for VK_EXT_transform_feedback.
- bool ext_custom_border_color{}; ///< Support for VK_EXT_custom_border_color.
- bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state.
- bool ext_robustness2{}; ///< Support for VK_EXT_robustness2.
- bool ext_shader_stencil_export{}; ///< Support for VK_EXT_shader_stencil_export.
- bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config.
- bool has_renderdoc{}; ///< Has RenderDoc attached
- bool has_nsight_graphics{}; ///< Has Nsight Graphics attached
+ bool is_formatless_image_load_supported{}; ///< Support for shader image read without format.
+ bool is_shader_storage_image_multisample{}; ///< Support for image operations on MSAA images.
+ bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil.
+ bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle.
+ bool khr_uniform_buffer_standard_layout{}; ///< Support for std430 on UBOs.
+ bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8.
+ bool ext_sampler_filter_minmax{}; ///< Support for VK_EXT_sampler_filter_minmax.
+ bool ext_depth_range_unrestricted{}; ///< Support for VK_EXT_depth_range_unrestricted.
+ bool ext_shader_viewport_index_layer{}; ///< Support for VK_EXT_shader_viewport_index_layer.
+ bool ext_tooling_info{}; ///< Support for VK_EXT_tooling_info.
+ bool ext_transform_feedback{}; ///< Support for VK_EXT_transform_feedback.
+ bool ext_custom_border_color{}; ///< Support for VK_EXT_custom_border_color.
+ bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state.
+ bool ext_robustness2{}; ///< Support for VK_EXT_robustness2.
+ bool ext_shader_stencil_export{}; ///< Support for VK_EXT_shader_stencil_export.
+ bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config.
+ bool has_renderdoc{}; ///< Has RenderDoc attached
+ bool has_nsight_graphics{}; ///< Has Nsight Graphics attached
// Asynchronous Graphics Pipeline setting
bool use_asynchronous_shaders{}; ///< Setting to use asynchronous shaders/graphics pipeline
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
new file mode 100644
index 000000000..d6eb3af31
--- /dev/null
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
@@ -0,0 +1,268 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include <bit>
+#include <optional>
+#include <vector>
+
+#include "common/alignment.h"
+#include "common/assert.h"
+#include "common/common_types.h"
+#include "common/logging/log.h"
+#include "video_core/vulkan_common/vulkan_device.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
+#include "video_core/vulkan_common/vulkan_wrapper.h"
+
+namespace Vulkan {
+namespace {
+struct Range {
+ u64 begin;
+ u64 end;
+
+ [[nodiscard]] bool Contains(u64 iterator, u64 size) const noexcept {
+ return iterator < end && begin < iterator + size;
+ }
+};
+
+[[nodiscard]] u64 AllocationChunkSize(u64 required_size) {
+ static constexpr std::array sizes{
+ 0x1000ULL << 10, 0x1400ULL << 10, 0x1800ULL << 10, 0x1c00ULL << 10, 0x2000ULL << 10,
+ 0x3200ULL << 10, 0x4000ULL << 10, 0x6000ULL << 10, 0x8000ULL << 10, 0xA000ULL << 10,
+ 0x10000ULL << 10, 0x18000ULL << 10, 0x20000ULL << 10,
+ };
+ static_assert(std::is_sorted(sizes.begin(), sizes.end()));
+
+ const auto it = std::ranges::lower_bound(sizes, required_size);
+ return it != sizes.end() ? *it : Common::AlignUp(required_size, 4ULL << 20);
+}
+
+[[nodiscard]] VkMemoryPropertyFlags MemoryUsagePropertyFlags(MemoryUsage usage) {
+ switch (usage) {
+ case MemoryUsage::DeviceLocal:
+ return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ case MemoryUsage::Upload:
+ return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ case MemoryUsage::Download:
+ return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
+ VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ }
+ UNREACHABLE_MSG("Invalid memory usage={}", usage);
+ return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+}
+} // Anonymous namespace
+
+class MemoryAllocation {
+public:
+ explicit MemoryAllocation(const Device& device_, vk::DeviceMemory memory_,
+ VkMemoryPropertyFlags properties, u64 allocation_size_, u32 type)
+ : device{device_}, memory{std::move(memory_)}, allocation_size{allocation_size_},
+ property_flags{properties}, shifted_memory_type{1U << type} {}
+
+ [[nodiscard]] std::optional<MemoryCommit> Commit(VkDeviceSize size, VkDeviceSize alignment) {
+ const std::optional<u64> alloc = FindFreeRegion(size, alignment);
+ if (!alloc) {
+ // Signal out of memory, it'll try to do more allocations.
+ return std::nullopt;
+ }
+ const Range range{
+ .begin = *alloc,
+ .end = *alloc + size,
+ };
+ commits.insert(std::ranges::upper_bound(commits, *alloc, {}, &Range::begin), range);
+ return std::make_optional<MemoryCommit>(this, *memory, *alloc, *alloc + size);
+ }
+
+ void Free(u64 begin) {
+ const auto it = std::ranges::find(commits, begin, &Range::begin);
+ ASSERT_MSG(it != commits.end(), "Invalid commit");
+ commits.erase(it);
+ }
+
+ [[nodiscard]] std::span<u8> Map() {
+ if (memory_mapped_span.empty()) {
+ u8* const raw_pointer = memory.Map(0, allocation_size);
+ memory_mapped_span = std::span<u8>(raw_pointer, allocation_size);
+ }
+ return memory_mapped_span;
+ }
+
+ /// Returns whether this allocation is compatible with the arguments.
+ [[nodiscard]] bool IsCompatible(VkMemoryPropertyFlags flags, u32 type_mask) const {
+ return (flags & property_flags) && (type_mask & shifted_memory_type) != 0;
+ }
+
+private:
+ [[nodiscard]] static constexpr u32 ShiftType(u32 type) {
+ return 1U << type;
+ }
+
+ [[nodiscard]] std::optional<u64> FindFreeRegion(u64 size, u64 alignment) noexcept {
+ ASSERT(std::has_single_bit(alignment));
+ const u64 alignment_log2 = std::countr_zero(alignment);
+ std::optional<u64> candidate;
+ u64 iterator = 0;
+ auto commit = commits.begin();
+ while (iterator + size <= allocation_size) {
+ candidate = candidate.value_or(iterator);
+ if (commit == commits.end()) {
+ break;
+ }
+ if (commit->Contains(*candidate, size)) {
+ candidate = std::nullopt;
+ }
+ iterator = Common::AlignUpLog2(commit->end, alignment_log2);
+ ++commit;
+ }
+ return candidate;
+ }
+
+ const Device& device; ///< Vulkan device.
+ const vk::DeviceMemory memory; ///< Vulkan memory allocation handler.
+ const u64 allocation_size; ///< Size of this allocation.
+ const VkMemoryPropertyFlags property_flags; ///< Vulkan memory property flags.
+ const u32 shifted_memory_type; ///< Shifted Vulkan memory type.
+ std::vector<Range> commits; ///< All commit ranges done from this allocation.
+ std::span<u8> memory_mapped_span; ///< Memory mapped span. Empty if not queried before.
+};
+
+MemoryCommit::MemoryCommit(MemoryAllocation* allocation_, VkDeviceMemory memory_, u64 begin_,
+ u64 end_) noexcept
+ : allocation{allocation_}, memory{memory_}, begin{begin_}, end{end_} {}
+
+MemoryCommit::~MemoryCommit() {
+ Release();
+}
+
+MemoryCommit& MemoryCommit::operator=(MemoryCommit&& rhs) noexcept {
+ Release();
+ allocation = std::exchange(rhs.allocation, nullptr);
+ memory = rhs.memory;
+ begin = rhs.begin;
+ end = rhs.end;
+ span = std::exchange(rhs.span, std::span<u8>{});
+ return *this;
+}
+
+MemoryCommit::MemoryCommit(MemoryCommit&& rhs) noexcept
+ : allocation{std::exchange(rhs.allocation, nullptr)}, memory{rhs.memory}, begin{rhs.begin},
+ end{rhs.end}, span{std::exchange(rhs.span, std::span<u8>{})} {}
+
+std::span<u8> MemoryCommit::Map() {
+ if (span.empty()) {
+ span = allocation->Map().subspan(begin, end - begin);
+ }
+ return span;
+}
+
+void MemoryCommit::Release() {
+ if (allocation) {
+ allocation->Free(begin);
+ }
+}
+
+MemoryAllocator::MemoryAllocator(const Device& device_)
+ : device{device_}, properties{device_.GetPhysical().GetMemoryProperties()} {}
+
+MemoryAllocator::~MemoryAllocator() = default;
+
+MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) {
+ // Find the fastest memory flags we can afford with the current requirements
+ const VkMemoryPropertyFlags flags = MemoryPropertyFlags(requirements.memoryTypeBits, usage);
+ if (std::optional<MemoryCommit> commit = TryCommit(requirements, flags)) {
+ return std::move(*commit);
+ }
+ // Commit has failed, allocate more memory.
+ // TODO(Rodrigo): Handle out of memory situations in some way like flushing to guest memory.
+ AllocMemory(flags, requirements.memoryTypeBits, AllocationChunkSize(requirements.size));
+
+ // Commit again, this time it won't fail since there's a fresh allocation above.
+ // If it does, there's a bug.
+ return TryCommit(requirements, flags).value();
+}
+
+MemoryCommit MemoryAllocator::Commit(const vk::Buffer& buffer, MemoryUsage usage) {
+ auto commit = Commit(device.GetLogical().GetBufferMemoryRequirements(*buffer), usage);
+ buffer.BindMemory(commit.Memory(), commit.Offset());
+ return commit;
+}
+
+MemoryCommit MemoryAllocator::Commit(const vk::Image& image, MemoryUsage usage) {
+ auto commit = Commit(device.GetLogical().GetImageMemoryRequirements(*image), usage);
+ image.BindMemory(commit.Memory(), commit.Offset());
+ return commit;
+}
+
+void MemoryAllocator::AllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) {
+ const u32 type = FindType(flags, type_mask).value();
+ vk::DeviceMemory memory = device.GetLogical().AllocateMemory({
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = nullptr,
+ .allocationSize = size,
+ .memoryTypeIndex = type,
+ });
+ allocations.push_back(
+ std::make_unique<MemoryAllocation>(device, std::move(memory), flags, size, type));
+}
+
+std::optional<MemoryCommit> MemoryAllocator::TryCommit(const VkMemoryRequirements& requirements,
+ VkMemoryPropertyFlags flags) {
+ for (auto& allocation : allocations) {
+ if (!allocation->IsCompatible(flags, requirements.memoryTypeBits)) {
+ continue;
+ }
+ if (auto commit = allocation->Commit(requirements.size, requirements.alignment)) {
+ return commit;
+ }
+ }
+ return std::nullopt;
+}
+
+VkMemoryPropertyFlags MemoryAllocator::MemoryPropertyFlags(u32 type_mask, MemoryUsage usage) const {
+ return MemoryPropertyFlags(type_mask, MemoryUsagePropertyFlags(usage));
+}
+
+VkMemoryPropertyFlags MemoryAllocator::MemoryPropertyFlags(u32 type_mask,
+ VkMemoryPropertyFlags flags) const {
+ if (FindType(flags, type_mask)) {
+ // Found a memory type with those requirements
+ return flags;
+ }
+ if (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
+ // Remove host cached bit in case it's not supported
+ return MemoryPropertyFlags(type_mask, flags & ~VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
+ }
+ if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
+ // Remove device local, if it's not supported by the requested resource
+ return MemoryPropertyFlags(type_mask, flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+ }
+ UNREACHABLE_MSG("No compatible memory types found");
+ return 0;
+}
+
+std::optional<u32> MemoryAllocator::FindType(VkMemoryPropertyFlags flags, u32 type_mask) const {
+ for (u32 type_index = 0; type_index < properties.memoryTypeCount; ++type_index) {
+ const VkMemoryPropertyFlags type_flags = properties.memoryTypes[type_index].propertyFlags;
+ if ((type_mask & (1U << type_index)) && (type_flags & flags)) {
+ // The type matches in type and in the wanted properties.
+ return type_index;
+ }
+ }
+ // Failed to find index
+ return std::nullopt;
+}
+
+bool IsHostVisible(MemoryUsage usage) noexcept {
+ switch (usage) {
+ case MemoryUsage::DeviceLocal:
+ return false;
+ case MemoryUsage::Upload:
+ case MemoryUsage::Download:
+ return true;
+ }
+ UNREACHABLE_MSG("Invalid memory usage={}", usage);
+ return false;
+}
+
+} // namespace Vulkan
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.h b/src/video_core/vulkan_common/vulkan_memory_allocator.h
new file mode 100644
index 000000000..53b3b275a
--- /dev/null
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.h
@@ -0,0 +1,118 @@
+// Copyright 2019 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <span>
+#include <utility>
+#include <vector>
+#include "common/common_types.h"
+#include "video_core/vulkan_common/vulkan_wrapper.h"
+
+namespace Vulkan {
+
+class Device;
+class MemoryMap;
+class MemoryAllocation;
+
+/// Hints and requirements for the backing memory type of a commit
+enum class MemoryUsage {
+ DeviceLocal, ///< Hints device local usages, fastest memory type to read and write from the GPU
+ Upload, ///< Requires a host visible memory type optimized for CPU to GPU uploads
+ Download, ///< Requires a host visible memory type optimized for GPU to CPU readbacks
+};
+
+/// Ownership handle of a memory commitment.
+/// Points to a subregion of a memory allocation.
+class MemoryCommit {
+public:
+ explicit MemoryCommit() noexcept = default;
+ explicit MemoryCommit(MemoryAllocation* allocation_, VkDeviceMemory memory_, u64 begin_,
+ u64 end_) noexcept;
+ ~MemoryCommit();
+
+ MemoryCommit& operator=(MemoryCommit&&) noexcept;
+ MemoryCommit(MemoryCommit&&) noexcept;
+
+ MemoryCommit& operator=(const MemoryCommit&) = delete;
+ MemoryCommit(const MemoryCommit&) = delete;
+
+ /// Returns a host visible memory map.
+ /// It will map the backing allocation if it hasn't been mapped before.
+ std::span<u8> Map();
+
+ /// Returns the Vulkan memory handler.
+ VkDeviceMemory Memory() const {
+ return memory;
+ }
+
+ /// Returns the start position of the commit relative to the allocation.
+ VkDeviceSize Offset() const {
+ return static_cast<VkDeviceSize>(begin);
+ }
+
+private:
+ void Release();
+
+ MemoryAllocation* allocation{}; ///< Pointer to the large memory allocation.
+ VkDeviceMemory memory{}; ///< Vulkan device memory handler.
+ u64 begin{}; ///< Beginning offset in bytes to where the commit exists.
+ u64 end{}; ///< Offset in bytes where the commit ends.
+ std::span<u8> span; ///< Host visible memory span. Empty if not queried before.
+};
+
+/// Memory allocator container.
+/// Allocates and releases memory allocations on demand.
+class MemoryAllocator {
+public:
+ explicit MemoryAllocator(const Device& device_);
+ ~MemoryAllocator();
+
+ MemoryAllocator& operator=(const MemoryAllocator&) = delete;
+ MemoryAllocator(const MemoryAllocator&) = delete;
+
+ /**
+ * Commits a memory with the specified requeriments.
+ *
+ * @param requirements Requirements returned from a Vulkan call.
+ * @param host_visible Signals the allocator that it *must* use host visible and coherent
+ * memory. When passing false, it will try to allocate device local memory.
+ *
+ * @returns A memory commit.
+ */
+ MemoryCommit Commit(const VkMemoryRequirements& requirements, MemoryUsage usage);
+
+ /// Commits memory required by the buffer and binds it.
+ MemoryCommit Commit(const vk::Buffer& buffer, MemoryUsage usage);
+
+ /// Commits memory required by the image and binds it.
+ MemoryCommit Commit(const vk::Image& image, MemoryUsage usage);
+
+private:
+ /// Allocates a chunk of memory.
+ void AllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size);
+
+ /// Tries to allocate a memory commit.
+ std::optional<MemoryCommit> TryCommit(const VkMemoryRequirements& requirements,
+ VkMemoryPropertyFlags flags);
+
+ /// Returns the fastest compatible memory property flags from a wanted usage.
+ VkMemoryPropertyFlags MemoryPropertyFlags(u32 type_mask, MemoryUsage usage) const;
+
+ /// Returns the fastest compatible memory property flags from the wanted flags.
+ VkMemoryPropertyFlags MemoryPropertyFlags(u32 type_mask, VkMemoryPropertyFlags flags) const;
+
+ /// Returns index to the fastest memory type compatible with the passed requirements.
+ std::optional<u32> FindType(VkMemoryPropertyFlags flags, u32 type_mask) const;
+
+ const Device& device; ///< Device handle.
+ const VkPhysicalDeviceMemoryProperties properties; ///< Physical device properties.
+ std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations.
+};
+
+/// Returns true when a memory usage is guaranteed to be host visible.
+bool IsHostVisible(MemoryUsage usage) noexcept;
+
+} // namespace Vulkan
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index 912cab46c..9689de0cb 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -144,152 +144,152 @@ inline VkResult Filter(VkResult result) {
/// Table holding Vulkan instance function pointers.
struct InstanceDispatch {
- PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
-
- PFN_vkCreateInstance vkCreateInstance;
- PFN_vkDestroyInstance vkDestroyInstance;
- PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
- PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties;
-
- PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;
- PFN_vkCreateDevice vkCreateDevice;
- PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
- PFN_vkDestroyDevice vkDestroyDevice;
- PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
- PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties;
- PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
- PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
- PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
- PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties;
- PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
- PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
- PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
- PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties;
- PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
- PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
- PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
- PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
- PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
- PFN_vkQueuePresentKHR vkQueuePresentKHR;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr{};
+
+ PFN_vkCreateInstance vkCreateInstance{};
+ PFN_vkDestroyInstance vkDestroyInstance{};
+ PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties{};
+ PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties{};
+
+ PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT{};
+ PFN_vkCreateDevice vkCreateDevice{};
+ PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT{};
+ PFN_vkDestroyDevice vkDestroyDevice{};
+ PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR{};
+ PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties{};
+ PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices{};
+ PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr{};
+ PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR{};
+ PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties{};
+ PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties{};
+ PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties{};
+ PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR{};
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties{};
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR{};
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR{};
+ PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR{};
+ PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR{};
+ PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR{};
+ PFN_vkQueuePresentKHR vkQueuePresentKHR{};
};
/// Table holding Vulkan device function pointers.
struct DeviceDispatch : public InstanceDispatch {
- PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
- PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers;
- PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets;
- PFN_vkAllocateMemory vkAllocateMemory;
- PFN_vkBeginCommandBuffer vkBeginCommandBuffer;
- PFN_vkBindBufferMemory vkBindBufferMemory;
- PFN_vkBindImageMemory vkBindImageMemory;
- PFN_vkCmdBeginQuery vkCmdBeginQuery;
- PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass;
- PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT;
- PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT;
- PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets;
- PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer;
- PFN_vkCmdBindPipeline vkCmdBindPipeline;
- PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT;
- PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers;
- PFN_vkCmdBlitImage vkCmdBlitImage;
- PFN_vkCmdClearAttachments vkCmdClearAttachments;
- PFN_vkCmdCopyBuffer vkCmdCopyBuffer;
- PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage;
- PFN_vkCmdCopyImage vkCmdCopyImage;
- PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer;
- PFN_vkCmdDispatch vkCmdDispatch;
- PFN_vkCmdDraw vkCmdDraw;
- PFN_vkCmdDrawIndexed vkCmdDrawIndexed;
- PFN_vkCmdEndQuery vkCmdEndQuery;
- PFN_vkCmdEndRenderPass vkCmdEndRenderPass;
- PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT;
- PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT;
- PFN_vkCmdFillBuffer vkCmdFillBuffer;
- PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier;
- PFN_vkCmdPushConstants vkCmdPushConstants;
- PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants;
- PFN_vkCmdSetDepthBias vkCmdSetDepthBias;
- PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds;
- PFN_vkCmdSetEvent vkCmdSetEvent;
- PFN_vkCmdSetScissor vkCmdSetScissor;
- PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask;
- PFN_vkCmdSetStencilReference vkCmdSetStencilReference;
- PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask;
- PFN_vkCmdSetViewport vkCmdSetViewport;
- PFN_vkCmdWaitEvents vkCmdWaitEvents;
- PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT;
- PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT;
- PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT;
- PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT;
- PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT;
- PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT;
- PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT;
- PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT;
- PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT;
- PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT;
- PFN_vkCmdResolveImage vkCmdResolveImage;
- PFN_vkCreateBuffer vkCreateBuffer;
- PFN_vkCreateBufferView vkCreateBufferView;
- PFN_vkCreateCommandPool vkCreateCommandPool;
- PFN_vkCreateComputePipelines vkCreateComputePipelines;
- PFN_vkCreateDescriptorPool vkCreateDescriptorPool;
- PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout;
- PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR;
- PFN_vkCreateEvent vkCreateEvent;
- PFN_vkCreateFence vkCreateFence;
- PFN_vkCreateFramebuffer vkCreateFramebuffer;
- PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines;
- PFN_vkCreateImage vkCreateImage;
- PFN_vkCreateImageView vkCreateImageView;
- PFN_vkCreatePipelineLayout vkCreatePipelineLayout;
- PFN_vkCreateQueryPool vkCreateQueryPool;
- PFN_vkCreateRenderPass vkCreateRenderPass;
- PFN_vkCreateSampler vkCreateSampler;
- PFN_vkCreateSemaphore vkCreateSemaphore;
- PFN_vkCreateShaderModule vkCreateShaderModule;
- PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR;
- PFN_vkDestroyBuffer vkDestroyBuffer;
- PFN_vkDestroyBufferView vkDestroyBufferView;
- PFN_vkDestroyCommandPool vkDestroyCommandPool;
- PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool;
- PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout;
- PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR;
- PFN_vkDestroyEvent vkDestroyEvent;
- PFN_vkDestroyFence vkDestroyFence;
- PFN_vkDestroyFramebuffer vkDestroyFramebuffer;
- PFN_vkDestroyImage vkDestroyImage;
- PFN_vkDestroyImageView vkDestroyImageView;
- PFN_vkDestroyPipeline vkDestroyPipeline;
- PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout;
- PFN_vkDestroyQueryPool vkDestroyQueryPool;
- PFN_vkDestroyRenderPass vkDestroyRenderPass;
- PFN_vkDestroySampler vkDestroySampler;
- PFN_vkDestroySemaphore vkDestroySemaphore;
- PFN_vkDestroyShaderModule vkDestroyShaderModule;
- PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
- PFN_vkDeviceWaitIdle vkDeviceWaitIdle;
- PFN_vkEndCommandBuffer vkEndCommandBuffer;
- PFN_vkFreeCommandBuffers vkFreeCommandBuffers;
- PFN_vkFreeDescriptorSets vkFreeDescriptorSets;
- PFN_vkFreeMemory vkFreeMemory;
- PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
- PFN_vkGetDeviceQueue vkGetDeviceQueue;
- PFN_vkGetEventStatus vkGetEventStatus;
- PFN_vkGetFenceStatus vkGetFenceStatus;
- PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
- PFN_vkGetQueryPoolResults vkGetQueryPoolResults;
- PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR;
- PFN_vkMapMemory vkMapMemory;
- PFN_vkQueueSubmit vkQueueSubmit;
- PFN_vkResetFences vkResetFences;
- PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT;
- PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT;
- PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT;
- PFN_vkUnmapMemory vkUnmapMemory;
- PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR;
- PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets;
- PFN_vkWaitForFences vkWaitForFences;
- PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR;
+ PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR{};
+ PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers{};
+ PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets{};
+ PFN_vkAllocateMemory vkAllocateMemory{};
+ PFN_vkBeginCommandBuffer vkBeginCommandBuffer{};
+ PFN_vkBindBufferMemory vkBindBufferMemory{};
+ PFN_vkBindImageMemory vkBindImageMemory{};
+ PFN_vkCmdBeginQuery vkCmdBeginQuery{};
+ PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass{};
+ PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT{};
+ PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT{};
+ PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets{};
+ PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer{};
+ PFN_vkCmdBindPipeline vkCmdBindPipeline{};
+ PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT{};
+ PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers{};
+ PFN_vkCmdBlitImage vkCmdBlitImage{};
+ PFN_vkCmdClearAttachments vkCmdClearAttachments{};
+ PFN_vkCmdCopyBuffer vkCmdCopyBuffer{};
+ PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage{};
+ PFN_vkCmdCopyImage vkCmdCopyImage{};
+ PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer{};
+ PFN_vkCmdDispatch vkCmdDispatch{};
+ PFN_vkCmdDraw vkCmdDraw{};
+ PFN_vkCmdDrawIndexed vkCmdDrawIndexed{};
+ PFN_vkCmdEndQuery vkCmdEndQuery{};
+ PFN_vkCmdEndRenderPass vkCmdEndRenderPass{};
+ PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{};
+ PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT{};
+ PFN_vkCmdFillBuffer vkCmdFillBuffer{};
+ PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier{};
+ PFN_vkCmdPushConstants vkCmdPushConstants{};
+ PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants{};
+ PFN_vkCmdSetDepthBias vkCmdSetDepthBias{};
+ PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds{};
+ PFN_vkCmdSetEvent vkCmdSetEvent{};
+ PFN_vkCmdSetScissor vkCmdSetScissor{};
+ PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask{};
+ PFN_vkCmdSetStencilReference vkCmdSetStencilReference{};
+ PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask{};
+ PFN_vkCmdSetViewport vkCmdSetViewport{};
+ PFN_vkCmdWaitEvents vkCmdWaitEvents{};
+ PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT{};
+ PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{};
+ PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT{};
+ PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT{};
+ PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT{};
+ PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT{};
+ PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT{};
+ PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT{};
+ PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT{};
+ PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT{};
+ PFN_vkCmdResolveImage vkCmdResolveImage{};
+ PFN_vkCreateBuffer vkCreateBuffer{};
+ PFN_vkCreateBufferView vkCreateBufferView{};
+ PFN_vkCreateCommandPool vkCreateCommandPool{};
+ PFN_vkCreateComputePipelines vkCreateComputePipelines{};
+ PFN_vkCreateDescriptorPool vkCreateDescriptorPool{};
+ PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout{};
+ PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR{};
+ PFN_vkCreateEvent vkCreateEvent{};
+ PFN_vkCreateFence vkCreateFence{};
+ PFN_vkCreateFramebuffer vkCreateFramebuffer{};
+ PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines{};
+ PFN_vkCreateImage vkCreateImage{};
+ PFN_vkCreateImageView vkCreateImageView{};
+ PFN_vkCreatePipelineLayout vkCreatePipelineLayout{};
+ PFN_vkCreateQueryPool vkCreateQueryPool{};
+ PFN_vkCreateRenderPass vkCreateRenderPass{};
+ PFN_vkCreateSampler vkCreateSampler{};
+ PFN_vkCreateSemaphore vkCreateSemaphore{};
+ PFN_vkCreateShaderModule vkCreateShaderModule{};
+ PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR{};
+ PFN_vkDestroyBuffer vkDestroyBuffer{};
+ PFN_vkDestroyBufferView vkDestroyBufferView{};
+ PFN_vkDestroyCommandPool vkDestroyCommandPool{};
+ PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool{};
+ PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout{};
+ PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR{};
+ PFN_vkDestroyEvent vkDestroyEvent{};
+ PFN_vkDestroyFence vkDestroyFence{};
+ PFN_vkDestroyFramebuffer vkDestroyFramebuffer{};
+ PFN_vkDestroyImage vkDestroyImage{};
+ PFN_vkDestroyImageView vkDestroyImageView{};
+ PFN_vkDestroyPipeline vkDestroyPipeline{};
+ PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout{};
+ PFN_vkDestroyQueryPool vkDestroyQueryPool{};
+ PFN_vkDestroyRenderPass vkDestroyRenderPass{};
+ PFN_vkDestroySampler vkDestroySampler{};
+ PFN_vkDestroySemaphore vkDestroySemaphore{};
+ PFN_vkDestroyShaderModule vkDestroyShaderModule{};
+ PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR{};
+ PFN_vkDeviceWaitIdle vkDeviceWaitIdle{};
+ PFN_vkEndCommandBuffer vkEndCommandBuffer{};
+ PFN_vkFreeCommandBuffers vkFreeCommandBuffers{};
+ PFN_vkFreeDescriptorSets vkFreeDescriptorSets{};
+ PFN_vkFreeMemory vkFreeMemory{};
+ PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements{};
+ PFN_vkGetDeviceQueue vkGetDeviceQueue{};
+ PFN_vkGetEventStatus vkGetEventStatus{};
+ PFN_vkGetFenceStatus vkGetFenceStatus{};
+ PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements{};
+ PFN_vkGetQueryPoolResults vkGetQueryPoolResults{};
+ PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR{};
+ PFN_vkMapMemory vkMapMemory{};
+ PFN_vkQueueSubmit vkQueueSubmit{};
+ PFN_vkResetFences vkResetFences{};
+ PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT{};
+ PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT{};
+ PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT{};
+ PFN_vkUnmapMemory vkUnmapMemory{};
+ PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR{};
+ PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{};
+ PFN_vkWaitForFences vkWaitForFences{};
+ PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR{};
};
/// Loads instance agnostic function pointers.