texture_cache: Simplify image view queries and blacklisting
This commit is contained in:
		 ReinUsesLisp
					ReinUsesLisp
				
			
				
					committed by
					
						 Fernando Sahmkow
						Fernando Sahmkow
					
				
			
			
				
	
			
			
			 Fernando Sahmkow
						Fernando Sahmkow
					
				
			
						parent
						
							48d81506a3
						
					
				
				
					commit
					56ccda1d99
				
			| @@ -79,8 +79,7 @@ void ComputePipeline::Configure() { | ||||
|     } | ||||
|     texture_cache.SynchronizeComputeDescriptors(); | ||||
|  | ||||
|     std::array<ImageViewId, MAX_TEXTURES + MAX_IMAGES> image_view_ids; | ||||
|     boost::container::static_vector<u32, MAX_TEXTURES + MAX_IMAGES> image_view_indices; | ||||
|     boost::container::static_vector<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views; | ||||
|     std::array<GLuint, MAX_TEXTURES> samplers; | ||||
|     std::array<GLuint, MAX_TEXTURES> textures; | ||||
|     std::array<GLuint, MAX_IMAGES> images; | ||||
| @@ -110,33 +109,39 @@ void ComputePipeline::Configure() { | ||||
|         } | ||||
|         return TexturePair(gpu_memory.Read<u32>(addr), via_header_index); | ||||
|     }}; | ||||
|     const auto add_image{[&](const auto& desc) { | ||||
|     const auto add_image{[&](const auto& desc, bool blacklist) { | ||||
|         for (u32 index = 0; index < desc.count; ++index) { | ||||
|             const auto handle{read_handle(desc, index)}; | ||||
|             image_view_indices.push_back(handle.first); | ||||
|             views.push_back({ | ||||
|                 .index = handle.first, | ||||
|                 .blacklist = blacklist, | ||||
|                 .id = {}, | ||||
|             }); | ||||
|         } | ||||
|     }}; | ||||
|     for (const auto& desc : info.texture_buffer_descriptors) { | ||||
|         for (u32 index = 0; index < desc.count; ++index) { | ||||
|             const auto handle{read_handle(desc, index)}; | ||||
|             image_view_indices.push_back(handle.first); | ||||
|             views.push_back({handle.first}); | ||||
|             samplers[sampler_binding++] = 0; | ||||
|         } | ||||
|     } | ||||
|     std::ranges::for_each(info.image_buffer_descriptors, add_image); | ||||
|     for (const auto& desc : info.image_buffer_descriptors) { | ||||
|         add_image(desc, false); | ||||
|     } | ||||
|     for (const auto& desc : info.texture_descriptors) { | ||||
|         for (u32 index = 0; index < desc.count; ++index) { | ||||
|             const auto handle{read_handle(desc, index)}; | ||||
|             image_view_indices.push_back(handle.first); | ||||
|             views.push_back({handle.first}); | ||||
|  | ||||
|             Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); | ||||
|             samplers[sampler_binding++] = sampler->Handle(); | ||||
|         } | ||||
|     } | ||||
|     std::ranges::for_each(info.image_descriptors, add_image); | ||||
|  | ||||
|     const std::span indices_span(image_view_indices.data(), image_view_indices.size()); | ||||
|     texture_cache.FillComputeImageViews(indices_span, image_view_ids); | ||||
|     for (const auto& desc : info.image_descriptors) { | ||||
|         add_image(desc, true); | ||||
|     } | ||||
|     texture_cache.FillComputeImageViews(std::span(views.data(), views.size())); | ||||
|  | ||||
|     if (assembly_program.handle != 0) { | ||||
|         program_manager.BindComputeAssemblyProgram(assembly_program.handle); | ||||
| @@ -152,7 +157,7 @@ void ComputePipeline::Configure() { | ||||
|             if constexpr (is_image) { | ||||
|                 is_written = desc.is_written; | ||||
|             } | ||||
|             ImageView& image_view{texture_cache.GetImageView(image_view_ids[texbuf_index])}; | ||||
|             ImageView& image_view{texture_cache.GetImageView(views[texbuf_index].id)}; | ||||
|             buffer_cache.BindComputeTextureBuffer(texbuf_index, image_view.GpuAddr(), | ||||
|                                                   image_view.BufferSize(), image_view.format, | ||||
|                                                   is_written, is_image); | ||||
| @@ -168,19 +173,20 @@ void ComputePipeline::Configure() { | ||||
|     buffer_cache.runtime.SetImagePointers(textures.data(), images.data()); | ||||
|     buffer_cache.BindHostComputeBuffers(); | ||||
|  | ||||
|     const ImageId* views_it{image_view_ids.data() + num_texture_buffers + num_image_buffers}; | ||||
|     const VideoCommon::ImageViewInOut* views_it{views.data() + num_texture_buffers + | ||||
|                                                 num_image_buffers}; | ||||
|     texture_binding += num_texture_buffers; | ||||
|     image_binding += num_image_buffers; | ||||
|  | ||||
|     for (const auto& desc : info.texture_descriptors) { | ||||
|         for (u32 index = 0; index < desc.count; ++index) { | ||||
|             ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; | ||||
|             ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; | ||||
|             textures[texture_binding++] = image_view.Handle(desc.type); | ||||
|         } | ||||
|     } | ||||
|     for (const auto& desc : info.image_descriptors) { | ||||
|         for (u32 index = 0; index < desc.count; ++index) { | ||||
|             ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; | ||||
|             ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; | ||||
|             if (desc.is_written) { | ||||
|                 texture_cache.MarkModification(image_view.image_id); | ||||
|             } | ||||
|   | ||||
| @@ -15,7 +15,7 @@ | ||||
| #include "video_core/renderer_opengl/gl_shader_util.h" | ||||
| #include "video_core/renderer_opengl/gl_state_tracker.h" | ||||
| #include "video_core/shader_notify.h" | ||||
| #include "video_core/texture_cache/texture_cache_base.h" | ||||
| #include "video_core/texture_cache/texture_cache.h" | ||||
|  | ||||
| #if defined(_MSC_VER) && defined(NDEBUG) | ||||
| #define LAMBDA_FORCEINLINE [[msvc::forceinline]] | ||||
| @@ -280,10 +280,9 @@ GraphicsPipeline::GraphicsPipeline( | ||||
|  | ||||
| template <typename Spec> | ||||
| void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|     std::array<ImageId, MAX_TEXTURES + MAX_IMAGES> image_view_ids; | ||||
|     std::array<u32, MAX_TEXTURES + MAX_IMAGES> image_view_indices; | ||||
|     std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views; | ||||
|     std::array<GLuint, MAX_TEXTURES> samplers; | ||||
|     size_t image_view_index{}; | ||||
|     size_t views_index{}; | ||||
|     GLsizei sampler_binding{}; | ||||
|  | ||||
|     texture_cache.SynchronizeGraphicsDescriptors(); | ||||
| @@ -328,30 +327,34 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|             } | ||||
|             return TexturePair(gpu_memory.Read<u32>(addr), via_header_index); | ||||
|         }}; | ||||
|         const auto add_image{[&](const auto& desc) { | ||||
|         const auto add_image{[&](const auto& desc, bool blacklist) LAMBDA_FORCEINLINE { | ||||
|             for (u32 index = 0; index < desc.count; ++index) { | ||||
|                 const auto handle{read_handle(desc, index)}; | ||||
|                 image_view_indices[image_view_index++] = handle.first; | ||||
|                 views[views_index++] = { | ||||
|                     .index = handle.first, | ||||
|                     .blacklist = blacklist, | ||||
|                     .id = {}, | ||||
|                 }; | ||||
|             } | ||||
|         }}; | ||||
|         if constexpr (Spec::has_texture_buffers) { | ||||
|             for (const auto& desc : info.texture_buffer_descriptors) { | ||||
|                 for (u32 index = 0; index < desc.count; ++index) { | ||||
|                     const auto handle{read_handle(desc, index)}; | ||||
|                     image_view_indices[image_view_index++] = handle.first; | ||||
|                     views[views_index++] = {handle.first}; | ||||
|                     samplers[sampler_binding++] = 0; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if constexpr (Spec::has_image_buffers) { | ||||
|             for (const auto& desc : info.image_buffer_descriptors) { | ||||
|                 add_image(desc); | ||||
|                 add_image(desc, false); | ||||
|             } | ||||
|         } | ||||
|         for (const auto& desc : info.texture_descriptors) { | ||||
|             for (u32 index = 0; index < desc.count; ++index) { | ||||
|                 const auto handle{read_handle(desc, index)}; | ||||
|                 image_view_indices[image_view_index++] = handle.first; | ||||
|                 views[views_index++] = {handle.first}; | ||||
|  | ||||
|                 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; | ||||
|                 samplers[sampler_binding++] = sampler->Handle(); | ||||
| @@ -359,7 +362,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|         } | ||||
|         if constexpr (Spec::has_images) { | ||||
|             for (const auto& desc : info.image_descriptors) { | ||||
|                 add_image(desc); | ||||
|                 add_image(desc, true); | ||||
|             } | ||||
|         } | ||||
|     }}; | ||||
| @@ -378,13 +381,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|     if constexpr (Spec::enabled_stages[4]) { | ||||
|         config_stage(4); | ||||
|     } | ||||
|     const std::span indices_span(image_view_indices.data(), image_view_index); | ||||
|     texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); | ||||
|     texture_cache.FillGraphicsImageViews<Spec::has_images>(std::span(views.data(), views_index)); | ||||
|  | ||||
|     texture_cache.UpdateRenderTargets(false); | ||||
|     state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle()); | ||||
|  | ||||
|     ImageId* texture_buffer_index{image_view_ids.data()}; | ||||
|     VideoCommon::ImageViewInOut* texture_buffer_it{views.data()}; | ||||
|     const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE { | ||||
|         size_t index{}; | ||||
|         const auto add_buffer{[&](const auto& desc) { | ||||
| @@ -394,12 +396,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|                 if constexpr (is_image) { | ||||
|                     is_written = desc.is_written; | ||||
|                 } | ||||
|                 ImageView& image_view{texture_cache.GetImageView(*texture_buffer_index)}; | ||||
|                 ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)}; | ||||
|                 buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(), | ||||
|                                                        image_view.BufferSize(), image_view.format, | ||||
|                                                        is_written, is_image); | ||||
|                 ++index; | ||||
|                 ++texture_buffer_index; | ||||
|                 ++texture_buffer_it; | ||||
|             } | ||||
|         }}; | ||||
|         const Shader::Info& info{stage_infos[stage]}; | ||||
| @@ -415,9 +417,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|                 add_buffer(desc); | ||||
|             } | ||||
|         } | ||||
|         texture_buffer_index += Shader::NumDescriptors(info.texture_descriptors); | ||||
|         texture_buffer_it += Shader::NumDescriptors(info.texture_descriptors); | ||||
|         if constexpr (Spec::has_images) { | ||||
|             texture_buffer_index += Shader::NumDescriptors(info.image_descriptors); | ||||
|             texture_buffer_it += Shader::NumDescriptors(info.image_descriptors); | ||||
|         } | ||||
|     }}; | ||||
|     if constexpr (Spec::enabled_stages[0]) { | ||||
| @@ -446,7 +448,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|     } else { | ||||
|         program_manager.BindSourcePrograms(source_programs); | ||||
|     } | ||||
|     const ImageId* views_it{image_view_ids.data()}; | ||||
|     const VideoCommon::ImageViewInOut* views_it{views.data()}; | ||||
|     GLsizei texture_binding = 0; | ||||
|     GLsizei image_binding = 0; | ||||
|     std::array<GLuint, MAX_TEXTURES> textures; | ||||
| @@ -464,13 +466,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|         const auto& info{stage_infos[stage]}; | ||||
|         for (const auto& desc : info.texture_descriptors) { | ||||
|             for (u32 index = 0; index < desc.count; ++index) { | ||||
|                 ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; | ||||
|                 ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; | ||||
|                 textures[texture_binding++] = image_view.Handle(desc.type); | ||||
|             } | ||||
|         } | ||||
|         for (const auto& desc : info.image_descriptors) { | ||||
|             for (u32 index = 0; index < desc.count; ++index) { | ||||
|                 ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; | ||||
|                 ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; | ||||
|                 if (desc.is_written) { | ||||
|                     texture_cache.MarkModification(image_view.image_id); | ||||
|                 } | ||||
|   | ||||
| @@ -472,11 +472,7 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager& | ||||
|     set_view(Shader::TextureType::ColorArray1D, null_image_1d_array.handle); | ||||
|     set_view(Shader::TextureType::ColorArray2D, null_image_view_2d_array.handle); | ||||
|     set_view(Shader::TextureType::ColorArrayCube, null_image_cube_array.handle); | ||||
| } | ||||
|  | ||||
| TextureCacheRuntime::~TextureCacheRuntime() = default; | ||||
|  | ||||
| void TextureCacheRuntime::Init() { | ||||
|     resolution = Settings::values.resolution_info; | ||||
|     is_rescaling_on = resolution.up_scale != 1 || resolution.down_shift != 0; | ||||
|     if (is_rescaling_on) { | ||||
| @@ -485,6 +481,8 @@ void TextureCacheRuntime::Init() { | ||||
|     } | ||||
| } | ||||
|  | ||||
| TextureCacheRuntime::~TextureCacheRuntime() = default; | ||||
|  | ||||
| void TextureCacheRuntime::Finish() { | ||||
|     glFinish(); | ||||
| } | ||||
| @@ -685,6 +683,8 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, | ||||
|     } | ||||
| } | ||||
|  | ||||
| Image::Image(const VideoCommon::NullImageParams& params) : VideoCommon::ImageBase{params} {} | ||||
|  | ||||
| Image::~Image() = default; | ||||
|  | ||||
| void Image::UploadMemory(const ImageBufferMap& map, | ||||
| @@ -1076,7 +1076,7 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, | ||||
|                      const VideoCommon::ImageViewInfo& view_info) | ||||
|     : VideoCommon::ImageViewBase{info, view_info} {} | ||||
|  | ||||
| ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params) | ||||
| ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageViewParams& params) | ||||
|     : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {} | ||||
|  | ||||
| GLuint ImageView::StorageView(Shader::TextureType texture_type, Shader::ImageFormat image_format) { | ||||
|   | ||||
| @@ -73,8 +73,6 @@ public: | ||||
|                                  StateTracker& state_tracker); | ||||
|     ~TextureCacheRuntime(); | ||||
|  | ||||
|     void Init(); | ||||
|  | ||||
|     void Finish(); | ||||
|  | ||||
|     ImageBufferMap UploadStagingBuffer(size_t size); | ||||
| @@ -167,6 +165,7 @@ class Image : public VideoCommon::ImageBase { | ||||
| public: | ||||
|     explicit Image(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr, | ||||
|                    VAddr cpu_addr); | ||||
|     explicit Image(const VideoCommon::NullImageParams&); | ||||
|  | ||||
|     ~Image(); | ||||
|  | ||||
| @@ -223,7 +222,7 @@ public: | ||||
|                        const VideoCommon::ImageViewInfo&, GPUVAddr); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, | ||||
|                        const VideoCommon::ImageViewInfo& view_info); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&); | ||||
|  | ||||
|     [[nodiscard]] GLuint StorageView(Shader::TextureType texture_type, | ||||
|                                      Shader::ImageFormat image_format); | ||||
|   | ||||
| @@ -156,28 +156,27 @@ private: | ||||
|     u32 texture_bit{1u}; | ||||
| }; | ||||
|  | ||||
| inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers, | ||||
|                                  const ImageId*& image_view_ids, TextureCache& texture_cache, | ||||
| inline void PushImageDescriptors(TextureCache& texture_cache, | ||||
|                                  VKUpdateDescriptorQueue& update_descriptor_queue, | ||||
|                                  RescalingPushConstant& rescaling) { | ||||
|     static constexpr VideoCommon::ImageViewId NULL_IMAGE_VIEW_ID{0}; | ||||
|     image_view_ids += Shader::NumDescriptors(info.texture_buffer_descriptors); | ||||
|     image_view_ids += Shader::NumDescriptors(info.image_buffer_descriptors); | ||||
|                                  const Shader::Info& info, RescalingPushConstant& rescaling, | ||||
|                                  const VkSampler*& samplers, | ||||
|                                  const VideoCommon::ImageViewInOut*& views) { | ||||
|     views += Shader::NumDescriptors(info.texture_buffer_descriptors); | ||||
|     views += Shader::NumDescriptors(info.image_buffer_descriptors); | ||||
|     for (const auto& desc : info.texture_descriptors) { | ||||
|         for (u32 index = 0; index < desc.count; ++index) { | ||||
|             const VideoCommon::ImageViewId image_view_id{*(image_view_ids++)}; | ||||
|             const VideoCommon::ImageViewId image_view_id{(views++)->id}; | ||||
|             const VkSampler sampler{*(samplers++)}; | ||||
|             ImageView& image_view{texture_cache.GetImageView(image_view_id)}; | ||||
|             const Image& image{texture_cache.GetImage(image_view.image_id)}; | ||||
|             const VkImageView vk_image_view{image_view.Handle(desc.type)}; | ||||
|             update_descriptor_queue.AddSampledImage(vk_image_view, sampler); | ||||
|             rescaling.PushTexture(image_view_id != NULL_IMAGE_VIEW_ID && | ||||
|                                   True(image.flags & VideoCommon::ImageFlagBits::Rescaled)); | ||||
|             rescaling.PushTexture(True(image.flags & VideoCommon::ImageFlagBits::Rescaled)); | ||||
|         } | ||||
|     } | ||||
|     for (const auto& desc : info.image_descriptors) { | ||||
|         for (u32 index = 0; index < desc.count; ++index) { | ||||
|             ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))}; | ||||
|             ImageView& image_view{texture_cache.GetImageView((views++)->id)}; | ||||
|             if (desc.is_written) { | ||||
|                 texture_cache.MarkModification(image_view.image_id); | ||||
|             } | ||||
|   | ||||
| @@ -108,10 +108,8 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | ||||
|     texture_cache.SynchronizeComputeDescriptors(); | ||||
|  | ||||
|     static constexpr size_t max_elements = 64; | ||||
|     std::array<ImageId, max_elements> image_view_ids; | ||||
|     boost::container::static_vector<u32, max_elements> image_view_indices; | ||||
|     boost::container::static_vector<VideoCommon::ImageViewInOut, max_elements> views; | ||||
|     boost::container::static_vector<VkSampler, max_elements> samplers; | ||||
|     boost::container::static_vector<bool, max_elements> image_view_blacklist; | ||||
|  | ||||
|     const auto& qmd{kepler_compute.launch_description}; | ||||
|     const auto& cbufs{qmd.const_buffer_config}; | ||||
| @@ -135,54 +133,37 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | ||||
|         } | ||||
|         return TexturePair(gpu_memory.Read<u32>(addr), via_header_index); | ||||
|     }}; | ||||
|     const auto add_image{[&](const auto& desc) { | ||||
|     const auto add_image{[&](const auto& desc, bool blacklist) { | ||||
|         for (u32 index = 0; index < desc.count; ++index) { | ||||
|             const auto handle{read_handle(desc, index)}; | ||||
|             image_view_indices.push_back(handle.first); | ||||
|             views.push_back({ | ||||
|                 .index = handle.first, | ||||
|                 .blacklist = blacklist, | ||||
|                 .id = {}, | ||||
|             }); | ||||
|         } | ||||
|     }}; | ||||
|     std::ranges::for_each(info.texture_buffer_descriptors, add_image); | ||||
|     std::ranges::for_each(info.image_buffer_descriptors, add_image); | ||||
|     for (const auto& desc : info.texture_buffer_descriptors) { | ||||
|         add_image(desc, false); | ||||
|     } | ||||
|     for (const auto& desc : info.image_buffer_descriptors) { | ||||
|         add_image(desc, false); | ||||
|     } | ||||
|     for (const auto& desc : info.texture_descriptors) { | ||||
|         for (u32 index = 0; index < desc.count; ++index) { | ||||
|             const auto handle{read_handle(desc, index)}; | ||||
|             image_view_indices.push_back(handle.first); | ||||
|             views.push_back({handle.first}); | ||||
|  | ||||
|             Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); | ||||
|             samplers.push_back(sampler->Handle()); | ||||
|         } | ||||
|     } | ||||
|     const u32 black_list_base = image_view_indices.size(); | ||||
|     bool atleast_one_blacklisted = false; | ||||
|     for (const auto& desc : info.image_descriptors) { | ||||
|         const bool is_black_listed = | ||||
|             desc.is_written && (desc.type == Shader::TextureType::Color2D || | ||||
|                                 desc.type == Shader::TextureType::ColorArray2D); | ||||
|         for (u32 index = 0; index < desc.count; ++index) { | ||||
|             image_view_blacklist.push_back(is_black_listed); | ||||
|         } | ||||
|         atleast_one_blacklisted |= is_black_listed; | ||||
|         add_image(desc); | ||||
|         add_image(desc, true); | ||||
|     } | ||||
|  | ||||
|     const std::span indices_span(image_view_indices.data(), image_view_indices.size()); | ||||
|     bool has_listed_stuffs; | ||||
|     do { | ||||
|         has_listed_stuffs = false; | ||||
|         texture_cache.FillComputeImageViews(indices_span, image_view_ids); | ||||
|         if (atleast_one_blacklisted) { | ||||
|             for (u32 index = 0; index < image_view_blacklist.size(); index++) { | ||||
|                 if (image_view_blacklist[index]) { | ||||
|                     ImageView& image_view{ | ||||
|                         texture_cache.GetImageView(image_view_ids[index + black_list_base])}; | ||||
|                     has_listed_stuffs |= texture_cache.BlackListImage(image_view.image_id); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } while (has_listed_stuffs); | ||||
|     texture_cache.FillComputeImageViews(std::span(views.data(), views.size())); | ||||
|  | ||||
|     buffer_cache.UnbindComputeTextureBuffers(); | ||||
|     ImageId* texture_buffer_ids{image_view_ids.data()}; | ||||
|     size_t index{}; | ||||
|     const auto add_buffer{[&](const auto& desc) { | ||||
|         constexpr bool is_image = std::is_same_v<decltype(desc), const ImageBufferDescriptor&>; | ||||
| @@ -191,11 +172,10 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | ||||
|             if constexpr (is_image) { | ||||
|                 is_written = desc.is_written; | ||||
|             } | ||||
|             ImageView& image_view = texture_cache.GetImageView(*texture_buffer_ids); | ||||
|             ImageView& image_view = texture_cache.GetImageView(views[index].id); | ||||
|             buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(), | ||||
|                                                   image_view.BufferSize(), image_view.format, | ||||
|                                                   is_written, is_image); | ||||
|             ++texture_buffer_ids; | ||||
|             ++index; | ||||
|         } | ||||
|     }}; | ||||
| @@ -207,9 +187,9 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | ||||
|  | ||||
|     RescalingPushConstant rescaling(num_textures); | ||||
|     const VkSampler* samplers_it{samplers.data()}; | ||||
|     const ImageId* views_it{image_view_ids.data()}; | ||||
|     PushImageDescriptors(info, samplers_it, views_it, texture_cache, update_descriptor_queue, | ||||
|                          rescaling); | ||||
|     const VideoCommon::ImageViewInOut* views_it{views.data()}; | ||||
|     PushImageDescriptors(texture_cache, update_descriptor_queue, info, rescaling, samplers_it, | ||||
|                          views_it); | ||||
|  | ||||
|     if (!is_built.load(std::memory_order::relaxed)) { | ||||
|         // Wait for the pipeline to be built | ||||
|   | ||||
| @@ -278,12 +278,10 @@ void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) { | ||||
|  | ||||
| template <typename Spec> | ||||
| void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|     std::array<ImageId, MAX_IMAGE_ELEMENTS> image_view_ids; | ||||
|     std::array<u32, MAX_IMAGE_ELEMENTS> image_view_indices; | ||||
|     std::array<bool, MAX_IMAGE_ELEMENTS> image_view_blacklist; | ||||
|     std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views; | ||||
|     std::array<VkSampler, MAX_IMAGE_ELEMENTS> samplers; | ||||
|     size_t sampler_index{}; | ||||
|     size_t image_index{}; | ||||
|     size_t view_index{}; | ||||
|  | ||||
|     texture_cache.SynchronizeGraphicsDescriptors(); | ||||
|  | ||||
| @@ -291,8 +289,6 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|  | ||||
|     const auto& regs{maxwell3d.regs}; | ||||
|     const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex}; | ||||
|     u32 start_black_list = std::numeric_limits<u32>::max(); | ||||
|     u32 end_black_list = 0; | ||||
|     const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE { | ||||
|         const Shader::Info& info{stage_infos[stage]}; | ||||
|         buffer_cache.UnbindGraphicsStorageBuffers(stage); | ||||
| @@ -329,7 +325,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|         const auto add_image{[&](const auto& desc) { | ||||
|             for (u32 index = 0; index < desc.count; ++index) { | ||||
|                 const auto handle{read_handle(desc, index)}; | ||||
|                 image_view_indices[image_index++] = handle.first; | ||||
|                 views[view_index++] = {handle.first}; | ||||
|             } | ||||
|         }}; | ||||
|         if constexpr (Spec::has_texture_buffers) { | ||||
| @@ -345,7 +341,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|         for (const auto& desc : info.texture_descriptors) { | ||||
|             for (u32 index = 0; index < desc.count; ++index) { | ||||
|                 const auto handle{read_handle(desc, index)}; | ||||
|                 image_view_indices[image_index++] = handle.first; | ||||
|                 views[view_index++] = {handle.first}; | ||||
|  | ||||
|                 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; | ||||
|                 samplers[sampler_index++] = sampler->Handle(); | ||||
| @@ -353,15 +349,6 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|         } | ||||
|         if constexpr (Spec::has_images) { | ||||
|             for (const auto& desc : info.image_descriptors) { | ||||
|                 if (desc.is_written && (desc.type == Shader::TextureType::Color2D || | ||||
|                                         desc.type == Shader::TextureType::ColorArray2D)) { | ||||
|                     auto index_copy = image_index; | ||||
|                     for (u32 index = 0; index < desc.count; ++index) { | ||||
|                         start_black_list = std::min<u32>(start_black_list, index_copy); | ||||
|                         image_view_blacklist[index_copy++] = true; | ||||
|                         end_black_list = std::max<u32>(end_black_list, index_copy); | ||||
|                     } | ||||
|                 } | ||||
|                 add_image(desc); | ||||
|             } | ||||
|         } | ||||
| @@ -381,24 +368,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|     if constexpr (Spec::enabled_stages[4]) { | ||||
|         config_stage(4); | ||||
|     } | ||||
|     const std::span indices_span(image_view_indices.data(), image_index); | ||||
|     bool has_listed_stuffs; | ||||
|     do { | ||||
|         has_listed_stuffs = false; | ||||
|         texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); | ||||
|         if constexpr (Spec::has_images) { | ||||
|             if (start_black_list < end_black_list) { | ||||
|                 for (u32 index = start_black_list; index < end_black_list; index++) { | ||||
|                     if (image_view_blacklist[index]) { | ||||
|                         ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])}; | ||||
|                         has_listed_stuffs |= texture_cache.BlackListImage(image_view.image_id); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } while (has_listed_stuffs); | ||||
|     texture_cache.FillGraphicsImageViews<Spec::has_images>(std::span(views.data(), view_index)); | ||||
|  | ||||
|     ImageId* texture_buffer_index{image_view_ids.data()}; | ||||
|     VideoCommon::ImageViewInOut* texture_buffer_it{views.data()}; | ||||
|     const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE { | ||||
|         size_t index{}; | ||||
|         const auto add_buffer{[&](const auto& desc) { | ||||
| @@ -408,12 +380,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|                 if constexpr (is_image) { | ||||
|                     is_written = desc.is_written; | ||||
|                 } | ||||
|                 ImageView& image_view{texture_cache.GetImageView(*texture_buffer_index)}; | ||||
|                 ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)}; | ||||
|                 buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(), | ||||
|                                                        image_view.BufferSize(), image_view.format, | ||||
|                                                        is_written, is_image); | ||||
|                 ++index; | ||||
|                 ++texture_buffer_index; | ||||
|                 ++texture_buffer_it; | ||||
|             } | ||||
|         }}; | ||||
|         buffer_cache.UnbindGraphicsTextureBuffers(stage); | ||||
| @@ -429,9 +401,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|                 add_buffer(desc); | ||||
|             } | ||||
|         } | ||||
|         texture_buffer_index += Shader::NumDescriptors(info.texture_descriptors); | ||||
|         texture_buffer_it += Shader::NumDescriptors(info.texture_descriptors); | ||||
|         if constexpr (Spec::has_images) { | ||||
|             texture_buffer_index += Shader::NumDescriptors(info.image_descriptors); | ||||
|             texture_buffer_it += Shader::NumDescriptors(info.image_descriptors); | ||||
|         } | ||||
|     }}; | ||||
|     if constexpr (Spec::enabled_stages[0]) { | ||||
| @@ -457,11 +429,11 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|  | ||||
|     RescalingPushConstant rescaling(num_textures); | ||||
|     const VkSampler* samplers_it{samplers.data()}; | ||||
|     const ImageId* views_it{image_view_ids.data()}; | ||||
|     const VideoCommon::ImageViewInOut* views_it{views.data()}; | ||||
|     const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { | ||||
|         buffer_cache.BindHostStageBuffers(stage); | ||||
|         PushImageDescriptors(stage_infos[stage], samplers_it, views_it, texture_cache, | ||||
|                              update_descriptor_queue, rescaling); | ||||
|         PushImageDescriptors(texture_cache, update_descriptor_queue, stage_infos[stage], rescaling, | ||||
|                              samplers_it, views_it); | ||||
|     }}; | ||||
|     if constexpr (Spec::enabled_stages[0]) { | ||||
|         prepare_stage(0); | ||||
|   | ||||
| @@ -730,10 +730,17 @@ void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, con | ||||
| } | ||||
| } // Anonymous namespace | ||||
|  | ||||
| void TextureCacheRuntime::Init() { | ||||
|     resolution = Settings::values.resolution_info; | ||||
|     is_rescaling_on = resolution.up_scale != 1 || resolution.down_shift != 0; | ||||
| } | ||||
| TextureCacheRuntime::TextureCacheRuntime(const Device& device_, VKScheduler& scheduler_, | ||||
|                                          MemoryAllocator& memory_allocator_, | ||||
|                                          StagingBufferPool& staging_buffer_pool_, | ||||
|                                          BlitImageHelper& blit_image_helper_, | ||||
|                                          ASTCDecoderPass& astc_decoder_pass_, | ||||
|                                          RenderPassCache& render_pass_cache_) | ||||
|     : device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_}, | ||||
|       staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_}, | ||||
|       astc_decoder_pass{astc_decoder_pass_}, render_pass_cache{render_pass_cache_}, | ||||
|       resolution{Settings::values.resolution_info}, | ||||
|       is_rescaling_on(resolution.up_scale != 1 || resolution.down_shift != 0) {} | ||||
|  | ||||
| void TextureCacheRuntime::Finish() { | ||||
|     scheduler.Finish(); | ||||
| @@ -1040,6 +1047,8 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu | ||||
|     } | ||||
| } | ||||
|  | ||||
| Image::Image(const VideoCommon::NullImageParams& params) : VideoCommon::ImageBase{params} {} | ||||
|  | ||||
| Image::~Image() = default; | ||||
|  | ||||
| void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { | ||||
| @@ -1187,8 +1196,7 @@ bool Image::ScaleDown(bool save_as_backup) { | ||||
|     }*/ | ||||
|  | ||||
|     const auto& resolution = runtime->resolution; | ||||
|     vk::Image downscaled_image = | ||||
|         MakeImage(runtime->device, info); | ||||
|     vk::Image downscaled_image = MakeImage(runtime->device, info); | ||||
|     MemoryCommit new_commit( | ||||
|         runtime->memory_allocator.Commit(downscaled_image, MemoryUsage::DeviceLocal)); | ||||
|  | ||||
| @@ -1301,7 +1309,7 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, | ||||
|     : VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_}, | ||||
|       buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {} | ||||
|  | ||||
| ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams& params) | ||||
| ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams& params) | ||||
|     : VideoCommon::ImageViewBase{params} {} | ||||
|  | ||||
| VkImageView ImageView::DepthView() { | ||||
|   | ||||
| @@ -34,21 +34,16 @@ class RenderPassCache; | ||||
| class StagingBufferPool; | ||||
| class VKScheduler; | ||||
|  | ||||
| struct TextureCacheRuntime { | ||||
|     const Device& device; | ||||
|     VKScheduler& scheduler; | ||||
|     MemoryAllocator& memory_allocator; | ||||
|     StagingBufferPool& staging_buffer_pool; | ||||
|     BlitImageHelper& blit_image_helper; | ||||
|     ASTCDecoderPass& astc_decoder_pass; | ||||
|     RenderPassCache& render_pass_cache; | ||||
| class TextureCacheRuntime { | ||||
| public: | ||||
|     static constexpr size_t TICKS_TO_DESTROY = 6; | ||||
|     DelayedDestructionRing<vk::Image, TICKS_TO_DESTROY> prescaled_images; | ||||
|     DelayedDestructionRing<MemoryCommit, TICKS_TO_DESTROY> prescaled_commits; | ||||
|     Settings::ResolutionScalingInfo resolution; | ||||
|     bool is_rescaling_on{}; | ||||
|  | ||||
|     void Init(); | ||||
|     explicit TextureCacheRuntime(const Device& device_, VKScheduler& scheduler_, | ||||
|                                  MemoryAllocator& memory_allocator_, | ||||
|                                  StagingBufferPool& staging_buffer_pool_, | ||||
|                                  BlitImageHelper& blit_image_helper_, | ||||
|                                  ASTCDecoderPass& astc_decoder_pass_, | ||||
|                                  RenderPassCache& render_pass_cache_); | ||||
|  | ||||
|     void Finish(); | ||||
|  | ||||
| @@ -56,6 +51,10 @@ struct TextureCacheRuntime { | ||||
|  | ||||
|     StagingBufferRef DownloadStagingBuffer(size_t size); | ||||
|  | ||||
|     void TickFrame(); | ||||
|  | ||||
|     u64 GetDeviceLocalMemory() const; | ||||
|  | ||||
|     void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | ||||
|                    const Region2D& dst_region, const Region2D& src_region, | ||||
|                    Tegra::Engines::Fermi2D::Filter filter, | ||||
| @@ -84,15 +83,25 @@ struct TextureCacheRuntime { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     void TickFrame(); | ||||
|     const Device& device; | ||||
|     VKScheduler& scheduler; | ||||
|     MemoryAllocator& memory_allocator; | ||||
|     StagingBufferPool& staging_buffer_pool; | ||||
|     BlitImageHelper& blit_image_helper; | ||||
|     ASTCDecoderPass& astc_decoder_pass; | ||||
|     RenderPassCache& render_pass_cache; | ||||
|  | ||||
|     u64 GetDeviceLocalMemory() const; | ||||
|     DelayedDestructionRing<vk::Image, TICKS_TO_DESTROY> prescaled_images; | ||||
|     DelayedDestructionRing<MemoryCommit, TICKS_TO_DESTROY> prescaled_commits; | ||||
|     Settings::ResolutionScalingInfo resolution; | ||||
|     bool is_rescaling_on{}; | ||||
| }; | ||||
|  | ||||
| class Image : public VideoCommon::ImageBase { | ||||
| public: | ||||
|     explicit Image(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr, | ||||
|                    VAddr cpu_addr); | ||||
|     explicit Image(const VideoCommon::NullImageParams&); | ||||
|  | ||||
|     ~Image(); | ||||
|  | ||||
| @@ -151,7 +160,7 @@ public: | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&, | ||||
|                        const VideoCommon::ImageViewInfo&, GPUVAddr); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); | ||||
|     explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&); | ||||
|  | ||||
|     [[nodiscard]] VkImageView DepthView(); | ||||
|  | ||||
|   | ||||
| @@ -69,6 +69,8 @@ ImageBase::ImageBase(const ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_ | ||||
|     } | ||||
| } | ||||
|  | ||||
| ImageBase::ImageBase(const NullImageParams&) {} | ||||
|  | ||||
| ImageMapView::ImageMapView(GPUVAddr gpu_addr_, VAddr cpu_addr_, size_t size_, ImageId image_id_) | ||||
|     : gpu_addr{gpu_addr_}, cpu_addr{cpu_addr_}, size{size_}, image_id{image_id_} {} | ||||
|  | ||||
|   | ||||
| @@ -48,8 +48,11 @@ struct AliasedImage { | ||||
|     ImageId id; | ||||
| }; | ||||
|  | ||||
| struct NullImageParams {}; | ||||
|  | ||||
| struct ImageBase { | ||||
|     explicit ImageBase(const ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr); | ||||
|     explicit ImageBase(const NullImageParams&); | ||||
|  | ||||
|     [[nodiscard]] std::optional<SubresourceBase> TryFindBase(GPUVAddr other_addr) const noexcept; | ||||
|  | ||||
|   | ||||
| @@ -45,6 +45,6 @@ ImageViewBase::ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_in | ||||
|     ASSERT_MSG(view_info.type == ImageViewType::Buffer, "Expected texture buffer"); | ||||
| } | ||||
|  | ||||
| ImageViewBase::ImageViewBase(const NullImageParams&) {} | ||||
| ImageViewBase::ImageViewBase(const NullImageViewParams&) : image_id{NULL_IMAGE_ID} {} | ||||
|  | ||||
| } // namespace VideoCommon | ||||
|   | ||||
| @@ -15,7 +15,7 @@ using VideoCore::Surface::PixelFormat; | ||||
| struct ImageViewInfo; | ||||
| struct ImageInfo; | ||||
|  | ||||
| struct NullImageParams {}; | ||||
| struct NullImageViewParams {}; | ||||
|  | ||||
| enum class ImageViewFlagBits : u16 { | ||||
|     PreemtiveDownload = 1 << 0, | ||||
| @@ -28,7 +28,7 @@ struct ImageViewBase { | ||||
|     explicit ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_info, | ||||
|                            ImageId image_id); | ||||
|     explicit ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info); | ||||
|     explicit ImageViewBase(const NullImageParams&); | ||||
|     explicit ImageViewBase(const NullImageViewParams&); | ||||
|  | ||||
|     [[nodiscard]] bool IsBuffer() const noexcept { | ||||
|         return type == ImageViewType::Buffer; | ||||
|   | ||||
| @@ -36,7 +36,6 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& | ||||
|                               Tegra::MemoryManager& gpu_memory_) | ||||
|     : runtime{runtime_}, rasterizer{rasterizer_}, maxwell3d{maxwell3d_}, | ||||
|       kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_} { | ||||
|     runtime.Init(); | ||||
|     // Configure null sampler | ||||
|     TSCEntry sampler_descriptor{}; | ||||
|     sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear); | ||||
| @@ -46,7 +45,8 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& | ||||
|  | ||||
|     // Make sure the first index is reserved for the null resources | ||||
|     // This way the null resource becomes a compile time constant | ||||
|     void(slot_image_views.insert(runtime, NullImageParams{})); | ||||
|     void(slot_images.insert(NullImageParams{})); | ||||
|     void(slot_image_views.insert(runtime, NullImageViewParams{})); | ||||
|     void(slot_samplers.insert(runtime, sampler_descriptor)); | ||||
|  | ||||
|     if constexpr (HAS_DEVICE_MEMORY_INFO) { | ||||
| @@ -57,7 +57,7 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& | ||||
|         critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY); | ||||
|         minimum_memory = 0; | ||||
|     } else { | ||||
|         // on OGL we can be more conservatives as the driver takes care. | ||||
|         // On OpenGL we can be more conservatives as the driver takes care. | ||||
|         expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB; | ||||
|         critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB; | ||||
|         minimum_memory = expected_memory; | ||||
| @@ -135,15 +135,14 @@ void TextureCache<P>::MarkModification(ImageId id) noexcept { | ||||
| } | ||||
|  | ||||
| template <class P> | ||||
| void TextureCache<P>::FillGraphicsImageViews(std::span<const u32> indices, | ||||
|                                              std::span<ImageViewId> image_view_ids) { | ||||
|     FillImageViews(graphics_image_table, graphics_image_view_ids, indices, image_view_ids); | ||||
| template <bool has_blacklists> | ||||
| void TextureCache<P>::FillGraphicsImageViews(std::span<ImageViewInOut> views) { | ||||
|     FillImageViews<has_blacklists>(graphics_image_table, graphics_image_view_ids, views); | ||||
| } | ||||
|  | ||||
| template <class P> | ||||
| void TextureCache<P>::FillComputeImageViews(std::span<const u32> indices, | ||||
|                                             std::span<ImageViewId> image_view_ids) { | ||||
|     FillImageViews(compute_image_table, compute_image_view_ids, indices, image_view_ids); | ||||
| void TextureCache<P>::FillComputeImageViews(std::span<ImageViewInOut> views) { | ||||
|     FillImageViews<false>(compute_image_table, compute_image_view_ids, views); | ||||
| } | ||||
|  | ||||
| template <class P> | ||||
| @@ -346,17 +345,26 @@ typename P::Framebuffer* TextureCache<P>::GetFramebuffer() { | ||||
| } | ||||
|  | ||||
| template <class P> | ||||
| template <bool has_blacklists> | ||||
| void TextureCache<P>::FillImageViews(DescriptorTable<TICEntry>& table, | ||||
|                                      std::span<ImageViewId> cached_image_view_ids, | ||||
|                                      std::span<const u32> indices, | ||||
|                                      std::span<ImageViewId> image_view_ids) { | ||||
|     ASSERT(indices.size() <= image_view_ids.size()); | ||||
|                                      std::span<ImageViewInOut> views) { | ||||
|     bool has_blacklisted; | ||||
|     do { | ||||
|         has_deleted_images = false; | ||||
|         std::ranges::transform(indices, image_view_ids.begin(), [&](u32 index) { | ||||
|             return VisitImageView(table, cached_image_view_ids, index); | ||||
|         }); | ||||
|     } while (has_deleted_images); | ||||
|         if constexpr (has_blacklists) { | ||||
|             has_blacklisted = false; | ||||
|         } | ||||
|         for (ImageViewInOut& view : views) { | ||||
|             view.id = VisitImageView(table, cached_image_view_ids, view.index); | ||||
|             if constexpr (has_blacklists) { | ||||
|                 if (view.blacklist && view.id != NULL_IMAGE_VIEW_ID) { | ||||
|                     const ImageViewBase& image_view{slot_image_views[view.id]}; | ||||
|                     has_blacklisted |= BlackListImage(image_view.image_id); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } while (has_deleted_images || (has_blacklists && has_blacklisted)); | ||||
| } | ||||
|  | ||||
| template <class P> | ||||
| @@ -622,7 +630,7 @@ void TextureCache<P>::PopAsyncFlushes() { | ||||
| } | ||||
|  | ||||
| template <class P> | ||||
| bool TextureCache<P>::IsRescaling() { | ||||
| bool TextureCache<P>::IsRescaling() const noexcept { | ||||
|     return is_rescaling; | ||||
| } | ||||
|  | ||||
| @@ -775,12 +783,11 @@ bool TextureCache<P>::BlackListImage(ImageId image_id) { | ||||
| } | ||||
|  | ||||
| template <class P> | ||||
| bool TextureCache<P>::ImageCanRescale(Image& image) { | ||||
| bool TextureCache<P>::ImageCanRescale(ImageBase& image) { | ||||
|     if (True(image.flags & ImageFlagBits::Blacklisted)) { | ||||
|         return false; | ||||
|     } | ||||
|     if (True(image.flags & ImageFlagBits::Rescaled) || | ||||
|         True(image.flags & ImageFlagBits::RescaleChecked)) { | ||||
|     if (True(image.flags & (ImageFlagBits::Rescaled | ImageFlagBits::RescaleChecked))) { | ||||
|         return true; | ||||
|     } | ||||
|     if (!image.info.rescaleable) { | ||||
|   | ||||
| @@ -39,6 +39,16 @@ using VideoCore::Surface::PixelFormatFromDepthFormat; | ||||
| using VideoCore::Surface::PixelFormatFromRenderTargetFormat; | ||||
| using namespace Common::Literals; | ||||
|  | ||||
| struct ImageViewInOut { | ||||
|     u32 index; | ||||
|     bool blacklist; | ||||
|     union { | ||||
|         struct Empty { | ||||
|         } empty{}; | ||||
|         ImageViewId id; | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| template <class P> | ||||
| class TextureCache { | ||||
|     /// Address shift for caching images into a hash table | ||||
| @@ -53,11 +63,6 @@ class TextureCache { | ||||
|     /// True when the API can provide info about the memory of the device. | ||||
|     static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; | ||||
|  | ||||
|     /// Image view ID for null descriptors | ||||
|     static constexpr ImageViewId NULL_IMAGE_VIEW_ID{0}; | ||||
|     /// Sampler ID for bugged sampler ids | ||||
|     static constexpr SamplerId NULL_SAMPLER_ID{0}; | ||||
|  | ||||
|     static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB; | ||||
|     static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB; | ||||
|  | ||||
| @@ -105,11 +110,11 @@ public: | ||||
|     void MarkModification(ImageId id) noexcept; | ||||
|  | ||||
|     /// Fill image_view_ids with the graphics images in indices | ||||
|     void FillGraphicsImageViews(std::span<const u32> indices, | ||||
|                                 std::span<ImageViewId> image_view_ids); | ||||
|     template <bool has_blacklists> | ||||
|     void FillGraphicsImageViews(std::span<ImageViewInOut> views); | ||||
|  | ||||
|     /// Fill image_view_ids with the compute images in indices | ||||
|     void FillComputeImageViews(std::span<const u32> indices, std::span<ImageViewId> image_view_ids); | ||||
|     void FillComputeImageViews(std::span<ImageViewInOut> views); | ||||
|  | ||||
|     /// Get the sampler from the graphics descriptor table in the specified index | ||||
|     Sampler* GetGraphicsSampler(u32 index); | ||||
| @@ -174,7 +179,7 @@ public: | ||||
|     /// Return true when a CPU region is modified from the GPU | ||||
|     [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); | ||||
|  | ||||
|     [[nodiscard]] bool IsRescaling(); | ||||
|     [[nodiscard]] bool IsRescaling() const noexcept; | ||||
|  | ||||
|     [[nodiscard]] bool BlackListImage(ImageId image_id); | ||||
|  | ||||
| @@ -216,9 +221,10 @@ private: | ||||
|     void RunGarbageCollector(); | ||||
|  | ||||
|     /// Fills image_view_ids in the image views in indices | ||||
|     template <bool has_blacklists> | ||||
|     void FillImageViews(DescriptorTable<TICEntry>& table, | ||||
|                         std::span<ImageViewId> cached_image_view_ids, std::span<const u32> indices, | ||||
|                         std::span<ImageViewId> image_view_ids); | ||||
|                         std::span<ImageViewId> cached_image_view_ids, | ||||
|                         std::span<ImageViewInOut> views); | ||||
|  | ||||
|     /// Find or create an image view in the guest descriptor table | ||||
|     ImageViewId VisitImageView(DescriptorTable<TICEntry>& table, | ||||
| @@ -336,7 +342,7 @@ private: | ||||
|     /// Returns true if the current clear parameters clear the whole image of a given image view | ||||
|     [[nodiscard]] bool IsFullClear(ImageViewId id); | ||||
|  | ||||
|     bool ImageCanRescale(Image& image); | ||||
|     bool ImageCanRescale(ImageBase& image); | ||||
|     void InvalidateScale(Image& image); | ||||
|     bool ScaleUp(Image& image); | ||||
|     bool ScaleDown(Image& image); | ||||
|   | ||||
| @@ -22,6 +22,13 @@ using ImageAllocId = SlotId; | ||||
| using SamplerId = SlotId; | ||||
| using FramebufferId = SlotId; | ||||
|  | ||||
| /// Fake image ID for null image views | ||||
| constexpr ImageId NULL_IMAGE_ID{0}; | ||||
| /// Image view ID for null descriptors | ||||
| constexpr ImageViewId NULL_IMAGE_VIEW_ID{0}; | ||||
| /// Sampler ID for bugged sampler ids | ||||
| constexpr SamplerId NULL_SAMPLER_ID{0}; | ||||
|  | ||||
| enum class ImageType : u32 { | ||||
|     e1D, | ||||
|     e2D, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user