summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_compute_pipeline.cpp36
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.cpp42
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp10
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h5
-rw-r--r--src/video_core/renderer_vulkan/pipeline_helper.h19
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp60
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp54
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp22
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h41
-rw-r--r--src/video_core/texture_cache/image_base.cpp2
-rw-r--r--src/video_core/texture_cache/image_base.h3
-rw-r--r--src/video_core/texture_cache/image_view_base.cpp2
-rw-r--r--src/video_core/texture_cache/image_view_base.h4
-rw-r--r--src/video_core/texture_cache/texture_cache.h47
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h30
-rw-r--r--src/video_core/texture_cache/types.h7
16 files changed, 192 insertions, 192 deletions
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
index 19c8ca7b2..ab2baefbb 100644
--- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
@@ -79,8 +79,7 @@ void ComputePipeline::Configure() {
79 } 79 }
80 texture_cache.SynchronizeComputeDescriptors(); 80 texture_cache.SynchronizeComputeDescriptors();
81 81
82 std::array<ImageViewId, MAX_TEXTURES + MAX_IMAGES> image_view_ids; 82 boost::container::static_vector<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views;
83 boost::container::static_vector<u32, MAX_TEXTURES + MAX_IMAGES> image_view_indices;
84 std::array<GLuint, MAX_TEXTURES> samplers; 83 std::array<GLuint, MAX_TEXTURES> samplers;
85 std::array<GLuint, MAX_TEXTURES> textures; 84 std::array<GLuint, MAX_TEXTURES> textures;
86 std::array<GLuint, MAX_IMAGES> images; 85 std::array<GLuint, MAX_IMAGES> images;
@@ -110,33 +109,39 @@ void ComputePipeline::Configure() {
110 } 109 }
111 return TexturePair(gpu_memory.Read<u32>(addr), via_header_index); 110 return TexturePair(gpu_memory.Read<u32>(addr), via_header_index);
112 }}; 111 }};
113 const auto add_image{[&](const auto& desc) { 112 const auto add_image{[&](const auto& desc, bool blacklist) {
114 for (u32 index = 0; index < desc.count; ++index) { 113 for (u32 index = 0; index < desc.count; ++index) {
115 const auto handle{read_handle(desc, index)}; 114 const auto handle{read_handle(desc, index)};
116 image_view_indices.push_back(handle.first); 115 views.push_back({
116 .index = handle.first,
117 .blacklist = blacklist,
118 .id = {},
119 });
117 } 120 }
118 }}; 121 }};
119 for (const auto& desc : info.texture_buffer_descriptors) { 122 for (const auto& desc : info.texture_buffer_descriptors) {
120 for (u32 index = 0; index < desc.count; ++index) { 123 for (u32 index = 0; index < desc.count; ++index) {
121 const auto handle{read_handle(desc, index)}; 124 const auto handle{read_handle(desc, index)};
122 image_view_indices.push_back(handle.first); 125 views.push_back({handle.first});
123 samplers[sampler_binding++] = 0; 126 samplers[sampler_binding++] = 0;
124 } 127 }
125 } 128 }
126 std::ranges::for_each(info.image_buffer_descriptors, add_image); 129 for (const auto& desc : info.image_buffer_descriptors) {
130 add_image(desc, false);
131 }
127 for (const auto& desc : info.texture_descriptors) { 132 for (const auto& desc : info.texture_descriptors) {
128 for (u32 index = 0; index < desc.count; ++index) { 133 for (u32 index = 0; index < desc.count; ++index) {
129 const auto handle{read_handle(desc, index)}; 134 const auto handle{read_handle(desc, index)};
130 image_view_indices.push_back(handle.first); 135 views.push_back({handle.first});
131 136
132 Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); 137 Sampler* const sampler = texture_cache.GetComputeSampler(handle.second);
133 samplers[sampler_binding++] = sampler->Handle(); 138 samplers[sampler_binding++] = sampler->Handle();
134 } 139 }
135 } 140 }
136 std::ranges::for_each(info.image_descriptors, add_image); 141 for (const auto& desc : info.image_descriptors) {
137 142 add_image(desc, true);
138 const std::span indices_span(image_view_indices.data(), image_view_indices.size()); 143 }
139 texture_cache.FillComputeImageViews(indices_span, image_view_ids); 144 texture_cache.FillComputeImageViews(std::span(views.data(), views.size()));
140 145
141 if (assembly_program.handle != 0) { 146 if (assembly_program.handle != 0) {
142 program_manager.BindComputeAssemblyProgram(assembly_program.handle); 147 program_manager.BindComputeAssemblyProgram(assembly_program.handle);
@@ -152,7 +157,7 @@ void ComputePipeline::Configure() {
152 if constexpr (is_image) { 157 if constexpr (is_image) {
153 is_written = desc.is_written; 158 is_written = desc.is_written;
154 } 159 }
155 ImageView& image_view{texture_cache.GetImageView(image_view_ids[texbuf_index])}; 160 ImageView& image_view{texture_cache.GetImageView(views[texbuf_index].id)};
156 buffer_cache.BindComputeTextureBuffer(texbuf_index, image_view.GpuAddr(), 161 buffer_cache.BindComputeTextureBuffer(texbuf_index, image_view.GpuAddr(),
157 image_view.BufferSize(), image_view.format, 162 image_view.BufferSize(), image_view.format,
158 is_written, is_image); 163 is_written, is_image);
@@ -168,19 +173,20 @@ void ComputePipeline::Configure() {
168 buffer_cache.runtime.SetImagePointers(textures.data(), images.data()); 173 buffer_cache.runtime.SetImagePointers(textures.data(), images.data());
169 buffer_cache.BindHostComputeBuffers(); 174 buffer_cache.BindHostComputeBuffers();
170 175
171 const ImageId* views_it{image_view_ids.data() + num_texture_buffers + num_image_buffers}; 176 const VideoCommon::ImageViewInOut* views_it{views.data() + num_texture_buffers +
177 num_image_buffers};
172 texture_binding += num_texture_buffers; 178 texture_binding += num_texture_buffers;
173 image_binding += num_image_buffers; 179 image_binding += num_image_buffers;
174 180
175 for (const auto& desc : info.texture_descriptors) { 181 for (const auto& desc : info.texture_descriptors) {
176 for (u32 index = 0; index < desc.count; ++index) { 182 for (u32 index = 0; index < desc.count; ++index) {
177 ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; 183 ImageView& image_view{texture_cache.GetImageView((views_it++)->id)};
178 textures[texture_binding++] = image_view.Handle(desc.type); 184 textures[texture_binding++] = image_view.Handle(desc.type);
179 } 185 }
180 } 186 }
181 for (const auto& desc : info.image_descriptors) { 187 for (const auto& desc : info.image_descriptors) {
182 for (u32 index = 0; index < desc.count; ++index) { 188 for (u32 index = 0; index < desc.count; ++index) {
183 ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; 189 ImageView& image_view{texture_cache.GetImageView((views_it++)->id)};
184 if (desc.is_written) { 190 if (desc.is_written) {
185 texture_cache.MarkModification(image_view.image_id); 191 texture_cache.MarkModification(image_view.image_id);
186 } 192 }
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index 43ab5c03b..0bbda7951 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -15,7 +15,7 @@
15#include "video_core/renderer_opengl/gl_shader_util.h" 15#include "video_core/renderer_opengl/gl_shader_util.h"
16#include "video_core/renderer_opengl/gl_state_tracker.h" 16#include "video_core/renderer_opengl/gl_state_tracker.h"
17#include "video_core/shader_notify.h" 17#include "video_core/shader_notify.h"
18#include "video_core/texture_cache/texture_cache_base.h" 18#include "video_core/texture_cache/texture_cache.h"
19 19
20#if defined(_MSC_VER) && defined(NDEBUG) 20#if defined(_MSC_VER) && defined(NDEBUG)
21#define LAMBDA_FORCEINLINE [[msvc::forceinline]] 21#define LAMBDA_FORCEINLINE [[msvc::forceinline]]
@@ -280,10 +280,9 @@ GraphicsPipeline::GraphicsPipeline(
280 280
281template <typename Spec> 281template <typename Spec>
282void GraphicsPipeline::ConfigureImpl(bool is_indexed) { 282void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
283 std::array<ImageId, MAX_TEXTURES + MAX_IMAGES> image_view_ids; 283 std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views;
284 std::array<u32, MAX_TEXTURES + MAX_IMAGES> image_view_indices;
285 std::array<GLuint, MAX_TEXTURES> samplers; 284 std::array<GLuint, MAX_TEXTURES> samplers;
286 size_t image_view_index{}; 285 size_t views_index{};
287 GLsizei sampler_binding{}; 286 GLsizei sampler_binding{};
288 287
289 texture_cache.SynchronizeGraphicsDescriptors(); 288 texture_cache.SynchronizeGraphicsDescriptors();
@@ -328,30 +327,34 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
328 } 327 }
329 return TexturePair(gpu_memory.Read<u32>(addr), via_header_index); 328 return TexturePair(gpu_memory.Read<u32>(addr), via_header_index);
330 }}; 329 }};
331 const auto add_image{[&](const auto& desc) { 330 const auto add_image{[&](const auto& desc, bool blacklist) LAMBDA_FORCEINLINE {
332 for (u32 index = 0; index < desc.count; ++index) { 331 for (u32 index = 0; index < desc.count; ++index) {
333 const auto handle{read_handle(desc, index)}; 332 const auto handle{read_handle(desc, index)};
334 image_view_indices[image_view_index++] = handle.first; 333 views[views_index++] = {
334 .index = handle.first,
335 .blacklist = blacklist,
336 .id = {},
337 };
335 } 338 }
336 }}; 339 }};
337 if constexpr (Spec::has_texture_buffers) { 340 if constexpr (Spec::has_texture_buffers) {
338 for (const auto& desc : info.texture_buffer_descriptors) { 341 for (const auto& desc : info.texture_buffer_descriptors) {
339 for (u32 index = 0; index < desc.count; ++index) { 342 for (u32 index = 0; index < desc.count; ++index) {
340 const auto handle{read_handle(desc, index)}; 343 const auto handle{read_handle(desc, index)};
341 image_view_indices[image_view_index++] = handle.first; 344 views[views_index++] = {handle.first};
342 samplers[sampler_binding++] = 0; 345 samplers[sampler_binding++] = 0;
343 } 346 }
344 } 347 }
345 } 348 }
346 if constexpr (Spec::has_image_buffers) { 349 if constexpr (Spec::has_image_buffers) {
347 for (const auto& desc : info.image_buffer_descriptors) { 350 for (const auto& desc : info.image_buffer_descriptors) {
348 add_image(desc); 351 add_image(desc, false);
349 } 352 }
350 } 353 }
351 for (const auto& desc : info.texture_descriptors) { 354 for (const auto& desc : info.texture_descriptors) {
352 for (u32 index = 0; index < desc.count; ++index) { 355 for (u32 index = 0; index < desc.count; ++index) {
353 const auto handle{read_handle(desc, index)}; 356 const auto handle{read_handle(desc, index)};
354 image_view_indices[image_view_index++] = handle.first; 357 views[views_index++] = {handle.first};
355 358
356 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; 359 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)};
357 samplers[sampler_binding++] = sampler->Handle(); 360 samplers[sampler_binding++] = sampler->Handle();
@@ -359,7 +362,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
359 } 362 }
360 if constexpr (Spec::has_images) { 363 if constexpr (Spec::has_images) {
361 for (const auto& desc : info.image_descriptors) { 364 for (const auto& desc : info.image_descriptors) {
362 add_image(desc); 365 add_image(desc, true);
363 } 366 }
364 } 367 }
365 }}; 368 }};
@@ -378,13 +381,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
378 if constexpr (Spec::enabled_stages[4]) { 381 if constexpr (Spec::enabled_stages[4]) {
379 config_stage(4); 382 config_stage(4);
380 } 383 }
381 const std::span indices_span(image_view_indices.data(), image_view_index); 384 texture_cache.FillGraphicsImageViews<Spec::has_images>(std::span(views.data(), views_index));
382 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
383 385
384 texture_cache.UpdateRenderTargets(false); 386 texture_cache.UpdateRenderTargets(false);
385 state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle()); 387 state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
386 388
387 ImageId* texture_buffer_index{image_view_ids.data()}; 389 VideoCommon::ImageViewInOut* texture_buffer_it{views.data()};
388 const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE { 390 const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE {
389 size_t index{}; 391 size_t index{};
390 const auto add_buffer{[&](const auto& desc) { 392 const auto add_buffer{[&](const auto& desc) {
@@ -394,12 +396,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
394 if constexpr (is_image) { 396 if constexpr (is_image) {
395 is_written = desc.is_written; 397 is_written = desc.is_written;
396 } 398 }
397 ImageView& image_view{texture_cache.GetImageView(*texture_buffer_index)}; 399 ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)};
398 buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(), 400 buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(),
399 image_view.BufferSize(), image_view.format, 401 image_view.BufferSize(), image_view.format,
400 is_written, is_image); 402 is_written, is_image);
401 ++index; 403 ++index;
402 ++texture_buffer_index; 404 ++texture_buffer_it;
403 } 405 }
404 }}; 406 }};
405 const Shader::Info& info{stage_infos[stage]}; 407 const Shader::Info& info{stage_infos[stage]};
@@ -415,9 +417,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
415 add_buffer(desc); 417 add_buffer(desc);
416 } 418 }
417 } 419 }
418 texture_buffer_index += Shader::NumDescriptors(info.texture_descriptors); 420 texture_buffer_it += Shader::NumDescriptors(info.texture_descriptors);
419 if constexpr (Spec::has_images) { 421 if constexpr (Spec::has_images) {
420 texture_buffer_index += Shader::NumDescriptors(info.image_descriptors); 422 texture_buffer_it += Shader::NumDescriptors(info.image_descriptors);
421 } 423 }
422 }}; 424 }};
423 if constexpr (Spec::enabled_stages[0]) { 425 if constexpr (Spec::enabled_stages[0]) {
@@ -446,7 +448,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
446 } else { 448 } else {
447 program_manager.BindSourcePrograms(source_programs); 449 program_manager.BindSourcePrograms(source_programs);
448 } 450 }
449 const ImageId* views_it{image_view_ids.data()}; 451 const VideoCommon::ImageViewInOut* views_it{views.data()};
450 GLsizei texture_binding = 0; 452 GLsizei texture_binding = 0;
451 GLsizei image_binding = 0; 453 GLsizei image_binding = 0;
452 std::array<GLuint, MAX_TEXTURES> textures; 454 std::array<GLuint, MAX_TEXTURES> textures;
@@ -464,13 +466,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
464 const auto& info{stage_infos[stage]}; 466 const auto& info{stage_infos[stage]};
465 for (const auto& desc : info.texture_descriptors) { 467 for (const auto& desc : info.texture_descriptors) {
466 for (u32 index = 0; index < desc.count; ++index) { 468 for (u32 index = 0; index < desc.count; ++index) {
467 ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; 469 ImageView& image_view{texture_cache.GetImageView((views_it++)->id)};
468 textures[texture_binding++] = image_view.Handle(desc.type); 470 textures[texture_binding++] = image_view.Handle(desc.type);
469 } 471 }
470 } 472 }
471 for (const auto& desc : info.image_descriptors) { 473 for (const auto& desc : info.image_descriptors) {
472 for (u32 index = 0; index < desc.count; ++index) { 474 for (u32 index = 0; index < desc.count; ++index) {
473 ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; 475 ImageView& image_view{texture_cache.GetImageView((views_it++)->id)};
474 if (desc.is_written) { 476 if (desc.is_written) {
475 texture_cache.MarkModification(image_view.image_id); 477 texture_cache.MarkModification(image_view.image_id);
476 } 478 }
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 5e2695576..5d14bfc97 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -472,11 +472,7 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager&
472 set_view(Shader::TextureType::ColorArray1D, null_image_1d_array.handle); 472 set_view(Shader::TextureType::ColorArray1D, null_image_1d_array.handle);
473 set_view(Shader::TextureType::ColorArray2D, null_image_view_2d_array.handle); 473 set_view(Shader::TextureType::ColorArray2D, null_image_view_2d_array.handle);
474 set_view(Shader::TextureType::ColorArrayCube, null_image_cube_array.handle); 474 set_view(Shader::TextureType::ColorArrayCube, null_image_cube_array.handle);
475}
476
477TextureCacheRuntime::~TextureCacheRuntime() = default;
478 475
479void TextureCacheRuntime::Init() {
480 resolution = Settings::values.resolution_info; 476 resolution = Settings::values.resolution_info;
481 is_rescaling_on = resolution.up_scale != 1 || resolution.down_shift != 0; 477 is_rescaling_on = resolution.up_scale != 1 || resolution.down_shift != 0;
482 if (is_rescaling_on) { 478 if (is_rescaling_on) {
@@ -485,6 +481,8 @@ void TextureCacheRuntime::Init() {
485 } 481 }
486} 482}
487 483
484TextureCacheRuntime::~TextureCacheRuntime() = default;
485
488void TextureCacheRuntime::Finish() { 486void TextureCacheRuntime::Finish() {
489 glFinish(); 487 glFinish();
490} 488}
@@ -685,6 +683,8 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_,
685 } 683 }
686} 684}
687 685
686Image::Image(const VideoCommon::NullImageParams& params) : VideoCommon::ImageBase{params} {}
687
688Image::~Image() = default; 688Image::~Image() = default;
689 689
690void Image::UploadMemory(const ImageBufferMap& map, 690void Image::UploadMemory(const ImageBufferMap& map,
@@ -1076,7 +1076,7 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
1076 const VideoCommon::ImageViewInfo& view_info) 1076 const VideoCommon::ImageViewInfo& view_info)
1077 : VideoCommon::ImageViewBase{info, view_info} {} 1077 : VideoCommon::ImageViewBase{info, view_info} {}
1078 1078
1079ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params) 1079ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageViewParams& params)
1080 : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {} 1080 : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {}
1081 1081
1082GLuint ImageView::StorageView(Shader::TextureType texture_type, Shader::ImageFormat image_format) { 1082GLuint ImageView::StorageView(Shader::TextureType texture_type, Shader::ImageFormat image_format) {
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 787b63e87..e76ec522a 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -73,8 +73,6 @@ public:
73 StateTracker& state_tracker); 73 StateTracker& state_tracker);
74 ~TextureCacheRuntime(); 74 ~TextureCacheRuntime();
75 75
76 void Init();
77
78 void Finish(); 76 void Finish();
79 77
80 ImageBufferMap UploadStagingBuffer(size_t size); 78 ImageBufferMap UploadStagingBuffer(size_t size);
@@ -167,6 +165,7 @@ class Image : public VideoCommon::ImageBase {
167public: 165public:
168 explicit Image(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr, 166 explicit Image(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr,
169 VAddr cpu_addr); 167 VAddr cpu_addr);
168 explicit Image(const VideoCommon::NullImageParams&);
170 169
171 ~Image(); 170 ~Image();
172 171
@@ -223,7 +222,7 @@ public:
223 const VideoCommon::ImageViewInfo&, GPUVAddr); 222 const VideoCommon::ImageViewInfo&, GPUVAddr);
224 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, 223 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
225 const VideoCommon::ImageViewInfo& view_info); 224 const VideoCommon::ImageViewInfo& view_info);
226 explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); 225 explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&);
227 226
228 [[nodiscard]] GLuint StorageView(Shader::TextureType texture_type, 227 [[nodiscard]] GLuint StorageView(Shader::TextureType texture_type,
229 Shader::ImageFormat image_format); 228 Shader::ImageFormat image_format);
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h
index 7ba6078df..bf18b34d1 100644
--- a/src/video_core/renderer_vulkan/pipeline_helper.h
+++ b/src/video_core/renderer_vulkan/pipeline_helper.h
@@ -156,28 +156,27 @@ private:
156 u32 texture_bit{1u}; 156 u32 texture_bit{1u};
157}; 157};
158 158
159inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers, 159inline void PushImageDescriptors(TextureCache& texture_cache,
160 const ImageId*& image_view_ids, TextureCache& texture_cache,
161 VKUpdateDescriptorQueue& update_descriptor_queue, 160 VKUpdateDescriptorQueue& update_descriptor_queue,
162 RescalingPushConstant& rescaling) { 161 const Shader::Info& info, RescalingPushConstant& rescaling,
163 static constexpr VideoCommon::ImageViewId NULL_IMAGE_VIEW_ID{0}; 162 const VkSampler*& samplers,
164 image_view_ids += Shader::NumDescriptors(info.texture_buffer_descriptors); 163 const VideoCommon::ImageViewInOut*& views) {
165 image_view_ids += Shader::NumDescriptors(info.image_buffer_descriptors); 164 views += Shader::NumDescriptors(info.texture_buffer_descriptors);
165 views += Shader::NumDescriptors(info.image_buffer_descriptors);
166 for (const auto& desc : info.texture_descriptors) { 166 for (const auto& desc : info.texture_descriptors) {
167 for (u32 index = 0; index < desc.count; ++index) { 167 for (u32 index = 0; index < desc.count; ++index) {
168 const VideoCommon::ImageViewId image_view_id{*(image_view_ids++)}; 168 const VideoCommon::ImageViewId image_view_id{(views++)->id};
169 const VkSampler sampler{*(samplers++)}; 169 const VkSampler sampler{*(samplers++)};
170 ImageView& image_view{texture_cache.GetImageView(image_view_id)}; 170 ImageView& image_view{texture_cache.GetImageView(image_view_id)};
171 const Image& image{texture_cache.GetImage(image_view.image_id)}; 171 const Image& image{texture_cache.GetImage(image_view.image_id)};
172 const VkImageView vk_image_view{image_view.Handle(desc.type)}; 172 const VkImageView vk_image_view{image_view.Handle(desc.type)};
173 update_descriptor_queue.AddSampledImage(vk_image_view, sampler); 173 update_descriptor_queue.AddSampledImage(vk_image_view, sampler);
174 rescaling.PushTexture(image_view_id != NULL_IMAGE_VIEW_ID && 174 rescaling.PushTexture(True(image.flags & VideoCommon::ImageFlagBits::Rescaled));
175 True(image.flags & VideoCommon::ImageFlagBits::Rescaled));
176 } 175 }
177 } 176 }
178 for (const auto& desc : info.image_descriptors) { 177 for (const auto& desc : info.image_descriptors) {
179 for (u32 index = 0; index < desc.count; ++index) { 178 for (u32 index = 0; index < desc.count; ++index) {
180 ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))}; 179 ImageView& image_view{texture_cache.GetImageView((views++)->id)};
181 if (desc.is_written) { 180 if (desc.is_written) {
182 texture_cache.MarkModification(image_view.image_id); 181 texture_cache.MarkModification(image_view.image_id);
183 } 182 }
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 5c591e345..f89b84c6e 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -108,10 +108,8 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
108 texture_cache.SynchronizeComputeDescriptors(); 108 texture_cache.SynchronizeComputeDescriptors();
109 109
110 static constexpr size_t max_elements = 64; 110 static constexpr size_t max_elements = 64;
111 std::array<ImageId, max_elements> image_view_ids; 111 boost::container::static_vector<VideoCommon::ImageViewInOut, max_elements> views;
112 boost::container::static_vector<u32, max_elements> image_view_indices;
113 boost::container::static_vector<VkSampler, max_elements> samplers; 112 boost::container::static_vector<VkSampler, max_elements> samplers;
114 boost::container::static_vector<bool, max_elements> image_view_blacklist;
115 113
116 const auto& qmd{kepler_compute.launch_description}; 114 const auto& qmd{kepler_compute.launch_description};
117 const auto& cbufs{qmd.const_buffer_config}; 115 const auto& cbufs{qmd.const_buffer_config};
@@ -135,54 +133,37 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
135 } 133 }
136 return TexturePair(gpu_memory.Read<u32>(addr), via_header_index); 134 return TexturePair(gpu_memory.Read<u32>(addr), via_header_index);
137 }}; 135 }};
138 const auto add_image{[&](const auto& desc) { 136 const auto add_image{[&](const auto& desc, bool blacklist) {
139 for (u32 index = 0; index < desc.count; ++index) { 137 for (u32 index = 0; index < desc.count; ++index) {
140 const auto handle{read_handle(desc, index)}; 138 const auto handle{read_handle(desc, index)};
141 image_view_indices.push_back(handle.first); 139 views.push_back({
140 .index = handle.first,
141 .blacklist = blacklist,
142 .id = {},
143 });
142 } 144 }
143 }}; 145 }};
144 std::ranges::for_each(info.texture_buffer_descriptors, add_image); 146 for (const auto& desc : info.texture_buffer_descriptors) {
145 std::ranges::for_each(info.image_buffer_descriptors, add_image); 147 add_image(desc, false);
148 }
149 for (const auto& desc : info.image_buffer_descriptors) {
150 add_image(desc, false);
151 }
146 for (const auto& desc : info.texture_descriptors) { 152 for (const auto& desc : info.texture_descriptors) {
147 for (u32 index = 0; index < desc.count; ++index) { 153 for (u32 index = 0; index < desc.count; ++index) {
148 const auto handle{read_handle(desc, index)}; 154 const auto handle{read_handle(desc, index)};
149 image_view_indices.push_back(handle.first); 155 views.push_back({handle.first});
150 156
151 Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); 157 Sampler* const sampler = texture_cache.GetComputeSampler(handle.second);
152 samplers.push_back(sampler->Handle()); 158 samplers.push_back(sampler->Handle());
153 } 159 }
154 } 160 }
155 const u32 black_list_base = image_view_indices.size();
156 bool atleast_one_blacklisted = false;
157 for (const auto& desc : info.image_descriptors) { 161 for (const auto& desc : info.image_descriptors) {
158 const bool is_black_listed = 162 add_image(desc, true);
159 desc.is_written && (desc.type == Shader::TextureType::Color2D ||
160 desc.type == Shader::TextureType::ColorArray2D);
161 for (u32 index = 0; index < desc.count; ++index) {
162 image_view_blacklist.push_back(is_black_listed);
163 }
164 atleast_one_blacklisted |= is_black_listed;
165 add_image(desc);
166 } 163 }
167 164 texture_cache.FillComputeImageViews(std::span(views.data(), views.size()));
168 const std::span indices_span(image_view_indices.data(), image_view_indices.size());
169 bool has_listed_stuffs;
170 do {
171 has_listed_stuffs = false;
172 texture_cache.FillComputeImageViews(indices_span, image_view_ids);
173 if (atleast_one_blacklisted) {
174 for (u32 index = 0; index < image_view_blacklist.size(); index++) {
175 if (image_view_blacklist[index]) {
176 ImageView& image_view{
177 texture_cache.GetImageView(image_view_ids[index + black_list_base])};
178 has_listed_stuffs |= texture_cache.BlackListImage(image_view.image_id);
179 }
180 }
181 }
182 } while (has_listed_stuffs);
183 165
184 buffer_cache.UnbindComputeTextureBuffers(); 166 buffer_cache.UnbindComputeTextureBuffers();
185 ImageId* texture_buffer_ids{image_view_ids.data()};
186 size_t index{}; 167 size_t index{};
187 const auto add_buffer{[&](const auto& desc) { 168 const auto add_buffer{[&](const auto& desc) {
188 constexpr bool is_image = std::is_same_v<decltype(desc), const ImageBufferDescriptor&>; 169 constexpr bool is_image = std::is_same_v<decltype(desc), const ImageBufferDescriptor&>;
@@ -191,11 +172,10 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
191 if constexpr (is_image) { 172 if constexpr (is_image) {
192 is_written = desc.is_written; 173 is_written = desc.is_written;
193 } 174 }
194 ImageView& image_view = texture_cache.GetImageView(*texture_buffer_ids); 175 ImageView& image_view = texture_cache.GetImageView(views[index].id);
195 buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(), 176 buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(),
196 image_view.BufferSize(), image_view.format, 177 image_view.BufferSize(), image_view.format,
197 is_written, is_image); 178 is_written, is_image);
198 ++texture_buffer_ids;
199 ++index; 179 ++index;
200 } 180 }
201 }}; 181 }};
@@ -207,9 +187,9 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
207 187
208 RescalingPushConstant rescaling(num_textures); 188 RescalingPushConstant rescaling(num_textures);
209 const VkSampler* samplers_it{samplers.data()}; 189 const VkSampler* samplers_it{samplers.data()};
210 const ImageId* views_it{image_view_ids.data()}; 190 const VideoCommon::ImageViewInOut* views_it{views.data()};
211 PushImageDescriptors(info, samplers_it, views_it, texture_cache, update_descriptor_queue, 191 PushImageDescriptors(texture_cache, update_descriptor_queue, info, rescaling, samplers_it,
212 rescaling); 192 views_it);
213 193
214 if (!is_built.load(std::memory_order::relaxed)) { 194 if (!is_built.load(std::memory_order::relaxed)) {
215 // Wait for the pipeline to be built 195 // Wait for the pipeline to be built
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 4d966ee4b..4efb5d735 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -278,12 +278,10 @@ void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) {
278 278
279template <typename Spec> 279template <typename Spec>
280void GraphicsPipeline::ConfigureImpl(bool is_indexed) { 280void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
281 std::array<ImageId, MAX_IMAGE_ELEMENTS> image_view_ids; 281 std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views;
282 std::array<u32, MAX_IMAGE_ELEMENTS> image_view_indices;
283 std::array<bool, MAX_IMAGE_ELEMENTS> image_view_blacklist;
284 std::array<VkSampler, MAX_IMAGE_ELEMENTS> samplers; 282 std::array<VkSampler, MAX_IMAGE_ELEMENTS> samplers;
285 size_t sampler_index{}; 283 size_t sampler_index{};
286 size_t image_index{}; 284 size_t view_index{};
287 285
288 texture_cache.SynchronizeGraphicsDescriptors(); 286 texture_cache.SynchronizeGraphicsDescriptors();
289 287
@@ -291,8 +289,6 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
291 289
292 const auto& regs{maxwell3d.regs}; 290 const auto& regs{maxwell3d.regs};
293 const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex}; 291 const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
294 u32 start_black_list = std::numeric_limits<u32>::max();
295 u32 end_black_list = 0;
296 const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE { 292 const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
297 const Shader::Info& info{stage_infos[stage]}; 293 const Shader::Info& info{stage_infos[stage]};
298 buffer_cache.UnbindGraphicsStorageBuffers(stage); 294 buffer_cache.UnbindGraphicsStorageBuffers(stage);
@@ -329,7 +325,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
329 const auto add_image{[&](const auto& desc) { 325 const auto add_image{[&](const auto& desc) {
330 for (u32 index = 0; index < desc.count; ++index) { 326 for (u32 index = 0; index < desc.count; ++index) {
331 const auto handle{read_handle(desc, index)}; 327 const auto handle{read_handle(desc, index)};
332 image_view_indices[image_index++] = handle.first; 328 views[view_index++] = {handle.first};
333 } 329 }
334 }}; 330 }};
335 if constexpr (Spec::has_texture_buffers) { 331 if constexpr (Spec::has_texture_buffers) {
@@ -345,7 +341,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
345 for (const auto& desc : info.texture_descriptors) { 341 for (const auto& desc : info.texture_descriptors) {
346 for (u32 index = 0; index < desc.count; ++index) { 342 for (u32 index = 0; index < desc.count; ++index) {
347 const auto handle{read_handle(desc, index)}; 343 const auto handle{read_handle(desc, index)};
348 image_view_indices[image_index++] = handle.first; 344 views[view_index++] = {handle.first};
349 345
350 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; 346 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)};
351 samplers[sampler_index++] = sampler->Handle(); 347 samplers[sampler_index++] = sampler->Handle();
@@ -353,15 +349,6 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
353 } 349 }
354 if constexpr (Spec::has_images) { 350 if constexpr (Spec::has_images) {
355 for (const auto& desc : info.image_descriptors) { 351 for (const auto& desc : info.image_descriptors) {
356 if (desc.is_written && (desc.type == Shader::TextureType::Color2D ||
357 desc.type == Shader::TextureType::ColorArray2D)) {
358 auto index_copy = image_index;
359 for (u32 index = 0; index < desc.count; ++index) {
360 start_black_list = std::min<u32>(start_black_list, index_copy);
361 image_view_blacklist[index_copy++] = true;
362 end_black_list = std::max<u32>(end_black_list, index_copy);
363 }
364 }
365 add_image(desc); 352 add_image(desc);
366 } 353 }
367 } 354 }
@@ -381,24 +368,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
381 if constexpr (Spec::enabled_stages[4]) { 368 if constexpr (Spec::enabled_stages[4]) {
382 config_stage(4); 369 config_stage(4);
383 } 370 }
384 const std::span indices_span(image_view_indices.data(), image_index); 371 texture_cache.FillGraphicsImageViews<Spec::has_images>(std::span(views.data(), view_index));
385 bool has_listed_stuffs;
386 do {
387 has_listed_stuffs = false;
388 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
389 if constexpr (Spec::has_images) {
390 if (start_black_list < end_black_list) {
391 for (u32 index = start_black_list; index < end_black_list; index++) {
392 if (image_view_blacklist[index]) {
393 ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])};
394 has_listed_stuffs |= texture_cache.BlackListImage(image_view.image_id);
395 }
396 }
397 }
398 }
399 } while (has_listed_stuffs);
400 372
401 ImageId* texture_buffer_index{image_view_ids.data()}; 373 VideoCommon::ImageViewInOut* texture_buffer_it{views.data()};
402 const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE { 374 const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE {
403 size_t index{}; 375 size_t index{};
404 const auto add_buffer{[&](const auto& desc) { 376 const auto add_buffer{[&](const auto& desc) {
@@ -408,12 +380,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
408 if constexpr (is_image) { 380 if constexpr (is_image) {
409 is_written = desc.is_written; 381 is_written = desc.is_written;
410 } 382 }
411 ImageView& image_view{texture_cache.GetImageView(*texture_buffer_index)}; 383 ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)};
412 buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(), 384 buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(),
413 image_view.BufferSize(), image_view.format, 385 image_view.BufferSize(), image_view.format,
414 is_written, is_image); 386 is_written, is_image);
415 ++index; 387 ++index;
416 ++texture_buffer_index; 388 ++texture_buffer_it;
417 } 389 }
418 }}; 390 }};
419 buffer_cache.UnbindGraphicsTextureBuffers(stage); 391 buffer_cache.UnbindGraphicsTextureBuffers(stage);
@@ -429,9 +401,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
429 add_buffer(desc); 401 add_buffer(desc);
430 } 402 }
431 } 403 }
432 texture_buffer_index += Shader::NumDescriptors(info.texture_descriptors); 404 texture_buffer_it += Shader::NumDescriptors(info.texture_descriptors);
433 if constexpr (Spec::has_images) { 405 if constexpr (Spec::has_images) {
434 texture_buffer_index += Shader::NumDescriptors(info.image_descriptors); 406 texture_buffer_it += Shader::NumDescriptors(info.image_descriptors);
435 } 407 }
436 }}; 408 }};
437 if constexpr (Spec::enabled_stages[0]) { 409 if constexpr (Spec::enabled_stages[0]) {
@@ -457,11 +429,11 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
457 429
458 RescalingPushConstant rescaling(num_textures); 430 RescalingPushConstant rescaling(num_textures);
459 const VkSampler* samplers_it{samplers.data()}; 431 const VkSampler* samplers_it{samplers.data()};
460 const ImageId* views_it{image_view_ids.data()}; 432 const VideoCommon::ImageViewInOut* views_it{views.data()};
461 const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { 433 const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
462 buffer_cache.BindHostStageBuffers(stage); 434 buffer_cache.BindHostStageBuffers(stage);
463 PushImageDescriptors(stage_infos[stage], samplers_it, views_it, texture_cache, 435 PushImageDescriptors(texture_cache, update_descriptor_queue, stage_infos[stage], rescaling,
464 update_descriptor_queue, rescaling); 436 samplers_it, views_it);
465 }}; 437 }};
466 if constexpr (Spec::enabled_stages[0]) { 438 if constexpr (Spec::enabled_stages[0]) {
467 prepare_stage(0); 439 prepare_stage(0);
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index b21992fce..3400066a6 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -730,10 +730,17 @@ void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, con
730} 730}
731} // Anonymous namespace 731} // Anonymous namespace
732 732
733void TextureCacheRuntime::Init() { 733TextureCacheRuntime::TextureCacheRuntime(const Device& device_, VKScheduler& scheduler_,
734 resolution = Settings::values.resolution_info; 734 MemoryAllocator& memory_allocator_,
735 is_rescaling_on = resolution.up_scale != 1 || resolution.down_shift != 0; 735 StagingBufferPool& staging_buffer_pool_,
736} 736 BlitImageHelper& blit_image_helper_,
737 ASTCDecoderPass& astc_decoder_pass_,
738 RenderPassCache& render_pass_cache_)
739 : device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_},
740 staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_},
741 astc_decoder_pass{astc_decoder_pass_}, render_pass_cache{render_pass_cache_},
742 resolution{Settings::values.resolution_info},
743 is_rescaling_on(resolution.up_scale != 1 || resolution.down_shift != 0) {}
737 744
738void TextureCacheRuntime::Finish() { 745void TextureCacheRuntime::Finish() {
739 scheduler.Finish(); 746 scheduler.Finish();
@@ -1040,6 +1047,8 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
1040 } 1047 }
1041} 1048}
1042 1049
1050Image::Image(const VideoCommon::NullImageParams& params) : VideoCommon::ImageBase{params} {}
1051
1043Image::~Image() = default; 1052Image::~Image() = default;
1044 1053
1045void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { 1054void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) {
@@ -1187,8 +1196,7 @@ bool Image::ScaleDown(bool save_as_backup) {
1187 }*/ 1196 }*/
1188 1197
1189 const auto& resolution = runtime->resolution; 1198 const auto& resolution = runtime->resolution;
1190 vk::Image downscaled_image = 1199 vk::Image downscaled_image = MakeImage(runtime->device, info);
1191 MakeImage(runtime->device, info);
1192 MemoryCommit new_commit( 1200 MemoryCommit new_commit(
1193 runtime->memory_allocator.Commit(downscaled_image, MemoryUsage::DeviceLocal)); 1201 runtime->memory_allocator.Commit(downscaled_image, MemoryUsage::DeviceLocal));
1194 1202
@@ -1301,7 +1309,7 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
1301 : VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_}, 1309 : VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_},
1302 buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {} 1310 buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {}
1303 1311
1304ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams& params) 1312ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams& params)
1305 : VideoCommon::ImageViewBase{params} {} 1313 : VideoCommon::ImageViewBase{params} {}
1306 1314
1307VkImageView ImageView::DepthView() { 1315VkImageView ImageView::DepthView() {
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 958a64651..9c39a6d99 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -34,21 +34,16 @@ class RenderPassCache;
34class StagingBufferPool; 34class StagingBufferPool;
35class VKScheduler; 35class VKScheduler;
36 36
37struct TextureCacheRuntime { 37class TextureCacheRuntime {
38 const Device& device; 38public:
39 VKScheduler& scheduler;
40 MemoryAllocator& memory_allocator;
41 StagingBufferPool& staging_buffer_pool;
42 BlitImageHelper& blit_image_helper;
43 ASTCDecoderPass& astc_decoder_pass;
44 RenderPassCache& render_pass_cache;
45 static constexpr size_t TICKS_TO_DESTROY = 6; 39 static constexpr size_t TICKS_TO_DESTROY = 6;
46 DelayedDestructionRing<vk::Image, TICKS_TO_DESTROY> prescaled_images;
47 DelayedDestructionRing<MemoryCommit, TICKS_TO_DESTROY> prescaled_commits;
48 Settings::ResolutionScalingInfo resolution;
49 bool is_rescaling_on{};
50 40
51 void Init(); 41 explicit TextureCacheRuntime(const Device& device_, VKScheduler& scheduler_,
42 MemoryAllocator& memory_allocator_,
43 StagingBufferPool& staging_buffer_pool_,
44 BlitImageHelper& blit_image_helper_,
45 ASTCDecoderPass& astc_decoder_pass_,
46 RenderPassCache& render_pass_cache_);
52 47
53 void Finish(); 48 void Finish();
54 49
@@ -56,6 +51,10 @@ struct TextureCacheRuntime {
56 51
57 StagingBufferRef DownloadStagingBuffer(size_t size); 52 StagingBufferRef DownloadStagingBuffer(size_t size);
58 53
54 void TickFrame();
55
56 u64 GetDeviceLocalMemory() const;
57
59 void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, 58 void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
60 const Region2D& dst_region, const Region2D& src_region, 59 const Region2D& dst_region, const Region2D& src_region,
61 Tegra::Engines::Fermi2D::Filter filter, 60 Tegra::Engines::Fermi2D::Filter filter,
@@ -84,15 +83,25 @@ struct TextureCacheRuntime {
84 return true; 83 return true;
85 } 84 }
86 85
87 void TickFrame(); 86 const Device& device;
87 VKScheduler& scheduler;
88 MemoryAllocator& memory_allocator;
89 StagingBufferPool& staging_buffer_pool;
90 BlitImageHelper& blit_image_helper;
91 ASTCDecoderPass& astc_decoder_pass;
92 RenderPassCache& render_pass_cache;
88 93
89 u64 GetDeviceLocalMemory() const; 94 DelayedDestructionRing<vk::Image, TICKS_TO_DESTROY> prescaled_images;
95 DelayedDestructionRing<MemoryCommit, TICKS_TO_DESTROY> prescaled_commits;
96 Settings::ResolutionScalingInfo resolution;
97 bool is_rescaling_on{};
90}; 98};
91 99
92class Image : public VideoCommon::ImageBase { 100class Image : public VideoCommon::ImageBase {
93public: 101public:
94 explicit Image(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr, 102 explicit Image(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr,
95 VAddr cpu_addr); 103 VAddr cpu_addr);
104 explicit Image(const VideoCommon::NullImageParams&);
96 105
97 ~Image(); 106 ~Image();
98 107
@@ -151,7 +160,7 @@ public:
151 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); 160 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
152 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&, 161 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
153 const VideoCommon::ImageViewInfo&, GPUVAddr); 162 const VideoCommon::ImageViewInfo&, GPUVAddr);
154 explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); 163 explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&);
155 164
156 [[nodiscard]] VkImageView DepthView(); 165 [[nodiscard]] VkImageView DepthView();
157 166
diff --git a/src/video_core/texture_cache/image_base.cpp b/src/video_core/texture_cache/image_base.cpp
index e9e725edf..25a211df8 100644
--- a/src/video_core/texture_cache/image_base.cpp
+++ b/src/video_core/texture_cache/image_base.cpp
@@ -69,6 +69,8 @@ ImageBase::ImageBase(const ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_
69 } 69 }
70} 70}
71 71
72ImageBase::ImageBase(const NullImageParams&) {}
73
72ImageMapView::ImageMapView(GPUVAddr gpu_addr_, VAddr cpu_addr_, size_t size_, ImageId image_id_) 74ImageMapView::ImageMapView(GPUVAddr gpu_addr_, VAddr cpu_addr_, size_t size_, ImageId image_id_)
73 : gpu_addr{gpu_addr_}, cpu_addr{cpu_addr_}, size{size_}, image_id{image_id_} {} 75 : gpu_addr{gpu_addr_}, cpu_addr{cpu_addr_}, size{size_}, image_id{image_id_} {}
74 76
diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h
index 97f107b4d..9c34687e0 100644
--- a/src/video_core/texture_cache/image_base.h
+++ b/src/video_core/texture_cache/image_base.h
@@ -48,8 +48,11 @@ struct AliasedImage {
48 ImageId id; 48 ImageId id;
49}; 49};
50 50
51struct NullImageParams {};
52
51struct ImageBase { 53struct ImageBase {
52 explicit ImageBase(const ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr); 54 explicit ImageBase(const ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr);
55 explicit ImageBase(const NullImageParams&);
53 56
54 [[nodiscard]] std::optional<SubresourceBase> TryFindBase(GPUVAddr other_addr) const noexcept; 57 [[nodiscard]] std::optional<SubresourceBase> TryFindBase(GPUVAddr other_addr) const noexcept;
55 58
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp
index 450becbeb..e66dc9320 100644
--- a/src/video_core/texture_cache/image_view_base.cpp
+++ b/src/video_core/texture_cache/image_view_base.cpp
@@ -45,6 +45,6 @@ ImageViewBase::ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_in
45 ASSERT_MSG(view_info.type == ImageViewType::Buffer, "Expected texture buffer"); 45 ASSERT_MSG(view_info.type == ImageViewType::Buffer, "Expected texture buffer");
46} 46}
47 47
48ImageViewBase::ImageViewBase(const NullImageParams&) {} 48ImageViewBase::ImageViewBase(const NullImageViewParams&) : image_id{NULL_IMAGE_ID} {}
49 49
50} // namespace VideoCommon 50} // namespace VideoCommon
diff --git a/src/video_core/texture_cache/image_view_base.h b/src/video_core/texture_cache/image_view_base.h
index 903f715c5..9c24c5359 100644
--- a/src/video_core/texture_cache/image_view_base.h
+++ b/src/video_core/texture_cache/image_view_base.h
@@ -15,7 +15,7 @@ using VideoCore::Surface::PixelFormat;
15struct ImageViewInfo; 15struct ImageViewInfo;
16struct ImageInfo; 16struct ImageInfo;
17 17
18struct NullImageParams {}; 18struct NullImageViewParams {};
19 19
20enum class ImageViewFlagBits : u16 { 20enum class ImageViewFlagBits : u16 {
21 PreemtiveDownload = 1 << 0, 21 PreemtiveDownload = 1 << 0,
@@ -28,7 +28,7 @@ struct ImageViewBase {
28 explicit ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_info, 28 explicit ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_info,
29 ImageId image_id); 29 ImageId image_id);
30 explicit ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info); 30 explicit ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info);
31 explicit ImageViewBase(const NullImageParams&); 31 explicit ImageViewBase(const NullImageViewParams&);
32 32
33 [[nodiscard]] bool IsBuffer() const noexcept { 33 [[nodiscard]] bool IsBuffer() const noexcept {
34 return type == ImageViewType::Buffer; 34 return type == ImageViewType::Buffer;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index be40f6b88..4e97a9e6a 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -36,7 +36,6 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
36 Tegra::MemoryManager& gpu_memory_) 36 Tegra::MemoryManager& gpu_memory_)
37 : runtime{runtime_}, rasterizer{rasterizer_}, maxwell3d{maxwell3d_}, 37 : runtime{runtime_}, rasterizer{rasterizer_}, maxwell3d{maxwell3d_},
38 kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_} { 38 kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_} {
39 runtime.Init();
40 // Configure null sampler 39 // Configure null sampler
41 TSCEntry sampler_descriptor{}; 40 TSCEntry sampler_descriptor{};
42 sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear); 41 sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear);
@@ -46,7 +45,8 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
46 45
47 // Make sure the first index is reserved for the null resources 46 // Make sure the first index is reserved for the null resources
48 // This way the null resource becomes a compile time constant 47 // This way the null resource becomes a compile time constant
49 void(slot_image_views.insert(runtime, NullImageParams{})); 48 void(slot_images.insert(NullImageParams{}));
49 void(slot_image_views.insert(runtime, NullImageViewParams{}));
50 void(slot_samplers.insert(runtime, sampler_descriptor)); 50 void(slot_samplers.insert(runtime, sampler_descriptor));
51 51
52 if constexpr (HAS_DEVICE_MEMORY_INFO) { 52 if constexpr (HAS_DEVICE_MEMORY_INFO) {
@@ -57,7 +57,7 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
57 critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY); 57 critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY);
58 minimum_memory = 0; 58 minimum_memory = 0;
59 } else { 59 } else {
60 // on OGL we can be more conservatives as the driver takes care. 60 // On OpenGL we can be more conservatives as the driver takes care.
61 expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB; 61 expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB;
62 critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB; 62 critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB;
63 minimum_memory = expected_memory; 63 minimum_memory = expected_memory;
@@ -135,15 +135,14 @@ void TextureCache<P>::MarkModification(ImageId id) noexcept {
135} 135}
136 136
137template <class P> 137template <class P>
138void TextureCache<P>::FillGraphicsImageViews(std::span<const u32> indices, 138template <bool has_blacklists>
139 std::span<ImageViewId> image_view_ids) { 139void TextureCache<P>::FillGraphicsImageViews(std::span<ImageViewInOut> views) {
140 FillImageViews(graphics_image_table, graphics_image_view_ids, indices, image_view_ids); 140 FillImageViews<has_blacklists>(graphics_image_table, graphics_image_view_ids, views);
141} 141}
142 142
143template <class P> 143template <class P>
144void TextureCache<P>::FillComputeImageViews(std::span<const u32> indices, 144void TextureCache<P>::FillComputeImageViews(std::span<ImageViewInOut> views) {
145 std::span<ImageViewId> image_view_ids) { 145 FillImageViews<false>(compute_image_table, compute_image_view_ids, views);
146 FillImageViews(compute_image_table, compute_image_view_ids, indices, image_view_ids);
147} 146}
148 147
149template <class P> 148template <class P>
@@ -346,17 +345,26 @@ typename P::Framebuffer* TextureCache<P>::GetFramebuffer() {
346} 345}
347 346
348template <class P> 347template <class P>
348template <bool has_blacklists>
349void TextureCache<P>::FillImageViews(DescriptorTable<TICEntry>& table, 349void TextureCache<P>::FillImageViews(DescriptorTable<TICEntry>& table,
350 std::span<ImageViewId> cached_image_view_ids, 350 std::span<ImageViewId> cached_image_view_ids,
351 std::span<const u32> indices, 351 std::span<ImageViewInOut> views) {
352 std::span<ImageViewId> image_view_ids) { 352 bool has_blacklisted;
353 ASSERT(indices.size() <= image_view_ids.size());
354 do { 353 do {
355 has_deleted_images = false; 354 has_deleted_images = false;
356 std::ranges::transform(indices, image_view_ids.begin(), [&](u32 index) { 355 if constexpr (has_blacklists) {
357 return VisitImageView(table, cached_image_view_ids, index); 356 has_blacklisted = false;
358 }); 357 }
359 } while (has_deleted_images); 358 for (ImageViewInOut& view : views) {
359 view.id = VisitImageView(table, cached_image_view_ids, view.index);
360 if constexpr (has_blacklists) {
361 if (view.blacklist && view.id != NULL_IMAGE_VIEW_ID) {
362 const ImageViewBase& image_view{slot_image_views[view.id]};
363 has_blacklisted |= BlackListImage(image_view.image_id);
364 }
365 }
366 }
367 } while (has_deleted_images || (has_blacklists && has_blacklisted));
360} 368}
361 369
362template <class P> 370template <class P>
@@ -622,7 +630,7 @@ void TextureCache<P>::PopAsyncFlushes() {
622} 630}
623 631
624template <class P> 632template <class P>
625bool TextureCache<P>::IsRescaling() { 633bool TextureCache<P>::IsRescaling() const noexcept {
626 return is_rescaling; 634 return is_rescaling;
627} 635}
628 636
@@ -775,12 +783,11 @@ bool TextureCache<P>::BlackListImage(ImageId image_id) {
775} 783}
776 784
777template <class P> 785template <class P>
778bool TextureCache<P>::ImageCanRescale(Image& image) { 786bool TextureCache<P>::ImageCanRescale(ImageBase& image) {
779 if (True(image.flags & ImageFlagBits::Blacklisted)) { 787 if (True(image.flags & ImageFlagBits::Blacklisted)) {
780 return false; 788 return false;
781 } 789 }
782 if (True(image.flags & ImageFlagBits::Rescaled) || 790 if (True(image.flags & (ImageFlagBits::Rescaled | ImageFlagBits::RescaleChecked))) {
783 True(image.flags & ImageFlagBits::RescaleChecked)) {
784 return true; 791 return true;
785 } 792 }
786 if (!image.info.rescaleable) { 793 if (!image.info.rescaleable) {
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index 35a29cd9b..b6cc09682 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -39,6 +39,16 @@ using VideoCore::Surface::PixelFormatFromDepthFormat;
39using VideoCore::Surface::PixelFormatFromRenderTargetFormat; 39using VideoCore::Surface::PixelFormatFromRenderTargetFormat;
40using namespace Common::Literals; 40using namespace Common::Literals;
41 41
42struct ImageViewInOut {
43 u32 index;
44 bool blacklist;
45 union {
46 struct Empty {
47 } empty{};
48 ImageViewId id;
49 };
50};
51
42template <class P> 52template <class P>
43class TextureCache { 53class TextureCache {
44 /// Address shift for caching images into a hash table 54 /// Address shift for caching images into a hash table
@@ -53,11 +63,6 @@ class TextureCache {
53 /// True when the API can provide info about the memory of the device. 63 /// True when the API can provide info about the memory of the device.
54 static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; 64 static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO;
55 65
56 /// Image view ID for null descriptors
57 static constexpr ImageViewId NULL_IMAGE_VIEW_ID{0};
58 /// Sampler ID for bugged sampler ids
59 static constexpr SamplerId NULL_SAMPLER_ID{0};
60
61 static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB; 66 static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB;
62 static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB; 67 static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB;
63 68
@@ -105,11 +110,11 @@ public:
105 void MarkModification(ImageId id) noexcept; 110 void MarkModification(ImageId id) noexcept;
106 111
107 /// Fill image_view_ids with the graphics images in indices 112 /// Fill image_view_ids with the graphics images in indices
108 void FillGraphicsImageViews(std::span<const u32> indices, 113 template <bool has_blacklists>
109 std::span<ImageViewId> image_view_ids); 114 void FillGraphicsImageViews(std::span<ImageViewInOut> views);
110 115
111 /// Fill image_view_ids with the compute images in indices 116 /// Fill image_view_ids with the compute images in indices
112 void FillComputeImageViews(std::span<const u32> indices, std::span<ImageViewId> image_view_ids); 117 void FillComputeImageViews(std::span<ImageViewInOut> views);
113 118
114 /// Get the sampler from the graphics descriptor table in the specified index 119 /// Get the sampler from the graphics descriptor table in the specified index
115 Sampler* GetGraphicsSampler(u32 index); 120 Sampler* GetGraphicsSampler(u32 index);
@@ -174,7 +179,7 @@ public:
174 /// Return true when a CPU region is modified from the GPU 179 /// Return true when a CPU region is modified from the GPU
175 [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); 180 [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size);
176 181
177 [[nodiscard]] bool IsRescaling(); 182 [[nodiscard]] bool IsRescaling() const noexcept;
178 183
179 [[nodiscard]] bool BlackListImage(ImageId image_id); 184 [[nodiscard]] bool BlackListImage(ImageId image_id);
180 185
@@ -216,9 +221,10 @@ private:
216 void RunGarbageCollector(); 221 void RunGarbageCollector();
217 222
218 /// Fills image_view_ids in the image views in indices 223 /// Fills image_view_ids in the image views in indices
224 template <bool has_blacklists>
219 void FillImageViews(DescriptorTable<TICEntry>& table, 225 void FillImageViews(DescriptorTable<TICEntry>& table,
220 std::span<ImageViewId> cached_image_view_ids, std::span<const u32> indices, 226 std::span<ImageViewId> cached_image_view_ids,
221 std::span<ImageViewId> image_view_ids); 227 std::span<ImageViewInOut> views);
222 228
223 /// Find or create an image view in the guest descriptor table 229 /// Find or create an image view in the guest descriptor table
224 ImageViewId VisitImageView(DescriptorTable<TICEntry>& table, 230 ImageViewId VisitImageView(DescriptorTable<TICEntry>& table,
@@ -336,7 +342,7 @@ private:
336 /// Returns true if the current clear parameters clear the whole image of a given image view 342 /// Returns true if the current clear parameters clear the whole image of a given image view
337 [[nodiscard]] bool IsFullClear(ImageViewId id); 343 [[nodiscard]] bool IsFullClear(ImageViewId id);
338 344
339 bool ImageCanRescale(Image& image); 345 bool ImageCanRescale(ImageBase& image);
340 void InvalidateScale(Image& image); 346 void InvalidateScale(Image& image);
341 bool ScaleUp(Image& image); 347 bool ScaleUp(Image& image);
342 bool ScaleDown(Image& image); 348 bool ScaleDown(Image& image);
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h
index 47a11cb2f..5c274abdf 100644
--- a/src/video_core/texture_cache/types.h
+++ b/src/video_core/texture_cache/types.h
@@ -22,6 +22,13 @@ using ImageAllocId = SlotId;
22using SamplerId = SlotId; 22using SamplerId = SlotId;
23using FramebufferId = SlotId; 23using FramebufferId = SlotId;
24 24
25/// Fake image ID for null image views
26constexpr ImageId NULL_IMAGE_ID{0};
27/// Image view ID for null descriptors
28constexpr ImageViewId NULL_IMAGE_VIEW_ID{0};
29/// Sampler ID for bugged sampler ids
30constexpr SamplerId NULL_SAMPLER_ID{0};
31
25enum class ImageType : u32 { 32enum class ImageType : u32 {
26 e1D, 33 e1D,
27 e2D, 34 e2D,