summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Wollnashorn2023-06-16 13:26:44 +0200
committerGravatar Wollnashorn2023-06-16 13:45:14 +0200
commit2dc0ff79ece34286c7078922668fd9f0a19b47b7 (patch)
treea474956c3fdc432f7259c70337d2c304baf80740
parentvideo_core: Fallback to default anisotropy instead to 1x anisotropy (diff)
downloadyuzu-2dc0ff79ece34286c7078922668fd9f0a19b47b7.tar.gz
yuzu-2dc0ff79ece34286c7078922668fd9f0a19b47b7.tar.xz
yuzu-2dc0ff79ece34286c7078922668fd9f0a19b47b7.zip
video_core: Use sampler IDs instead pointers in the pipeline config
The previous approach of storing pointers returned by `GetGraphicsSampler`/`GetComputeSampler` caused UB, as these functions can cause reallocation of the sampler slot vector and therefore invalidate the pointers
-rw-r--r--src/video_core/renderer_opengl/gl_compute_pipeline.cpp23
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.cpp8
-rw-r--r--src/video_core/renderer_vulkan/pipeline_helper.h5
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp6
-rw-r--r--src/video_core/texture_cache/image_view_base.cpp1
-rw-r--r--src/video_core/texture_cache/texture_cache.h30
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h12
8 files changed, 68 insertions, 23 deletions
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
index 1a0cea9b7..3151c0db8 100644
--- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
@@ -87,7 +87,8 @@ void ComputePipeline::Configure() {
87 texture_cache.SynchronizeComputeDescriptors(); 87 texture_cache.SynchronizeComputeDescriptors();
88 88
89 boost::container::static_vector<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views; 89 boost::container::static_vector<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views;
90 std::array<GLuint, MAX_TEXTURES> samplers; 90 boost::container::static_vector<VideoCommon::SamplerId, MAX_TEXTURES> samplers;
91 std::array<GLuint, MAX_TEXTURES> gl_samplers;
91 std::array<GLuint, MAX_TEXTURES> textures; 92 std::array<GLuint, MAX_TEXTURES> textures;
92 std::array<GLuint, MAX_IMAGES> images; 93 std::array<GLuint, MAX_IMAGES> images;
93 GLsizei sampler_binding{}; 94 GLsizei sampler_binding{};
@@ -131,7 +132,6 @@ void ComputePipeline::Configure() {
131 for (u32 index = 0; index < desc.count; ++index) { 132 for (u32 index = 0; index < desc.count; ++index) {
132 const auto handle{read_handle(desc, index)}; 133 const auto handle{read_handle(desc, index)};
133 views.push_back({handle.first}); 134 views.push_back({handle.first});
134 samplers[sampler_binding++] = 0;
135 } 135 }
136 } 136 }
137 for (const auto& desc : info.image_buffer_descriptors) { 137 for (const auto& desc : info.image_buffer_descriptors) {
@@ -142,8 +142,8 @@ void ComputePipeline::Configure() {
142 const auto handle{read_handle(desc, index)}; 142 const auto handle{read_handle(desc, index)};
143 views.push_back({handle.first}); 143 views.push_back({handle.first});
144 144
145 Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); 145 VideoCommon::SamplerId sampler = texture_cache.GetComputeSamplerId(handle.second);
146 samplers[sampler_binding++] = sampler->Handle(); 146 samplers.push_back(sampler);
147 } 147 }
148 } 148 }
149 for (const auto& desc : info.image_descriptors) { 149 for (const auto& desc : info.image_descriptors) {
@@ -186,10 +186,17 @@ void ComputePipeline::Configure() {
186 186
187 const VideoCommon::ImageViewInOut* views_it{views.data() + num_texture_buffers + 187 const VideoCommon::ImageViewInOut* views_it{views.data() + num_texture_buffers +
188 num_image_buffers}; 188 num_image_buffers};
189 const VideoCommon::SamplerId* samplers_it{samplers.data()};
189 texture_binding += num_texture_buffers; 190 texture_binding += num_texture_buffers;
190 image_binding += num_image_buffers; 191 image_binding += num_image_buffers;
191 192
192 u32 texture_scaling_mask{}; 193 u32 texture_scaling_mask{};
194
195 for (const auto& desc : info.texture_buffer_descriptors) {
196 for (u32 index = 0; index < desc.count; ++index) {
197 gl_samplers[sampler_binding++] = 0;
198 }
199 }
193 for (const auto& desc : info.texture_descriptors) { 200 for (const auto& desc : info.texture_descriptors) {
194 for (u32 index = 0; index < desc.count; ++index) { 201 for (u32 index = 0; index < desc.count; ++index) {
195 ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; 202 ImageView& image_view{texture_cache.GetImageView((views_it++)->id)};
@@ -198,6 +205,12 @@ void ComputePipeline::Configure() {
198 texture_scaling_mask |= 1u << texture_binding; 205 texture_scaling_mask |= 1u << texture_binding;
199 } 206 }
200 ++texture_binding; 207 ++texture_binding;
208
209 const Sampler& sampler{texture_cache.GetSampler(*(samplers_it++))};
210 const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
211 !image_view.SupportsAnisotropy()};
212 gl_samplers[sampler_binding++] =
213 use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy() : sampler.Handle();
201 } 214 }
202 } 215 }
203 u32 image_scaling_mask{}; 216 u32 image_scaling_mask{};
@@ -228,7 +241,7 @@ void ComputePipeline::Configure() {
228 if (texture_binding != 0) { 241 if (texture_binding != 0) {
229 ASSERT(texture_binding == sampler_binding); 242 ASSERT(texture_binding == sampler_binding);
230 glBindTextures(0, texture_binding, textures.data()); 243 glBindTextures(0, texture_binding, textures.data());
231 glBindSamplers(0, sampler_binding, samplers.data()); 244 glBindSamplers(0, sampler_binding, gl_samplers.data());
232 } 245 }
233 if (image_binding != 0) { 246 if (image_binding != 0) {
234 glBindImageTextures(0, image_binding, images.data()); 247 glBindImageTextures(0, image_binding, images.data());
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index 58e4e1919..c58f760b8 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -275,7 +275,7 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
275template <typename Spec> 275template <typename Spec>
276void GraphicsPipeline::ConfigureImpl(bool is_indexed) { 276void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
277 std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views; 277 std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views;
278 std::array<const Sampler*, MAX_TEXTURES> samplers; 278 std::array<VideoCommon::SamplerId, MAX_TEXTURES> samplers;
279 size_t views_index{}; 279 size_t views_index{};
280 size_t samplers_index{}; 280 size_t samplers_index{};
281 281
@@ -350,7 +350,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
350 const auto handle{read_handle(desc, index)}; 350 const auto handle{read_handle(desc, index)};
351 views[views_index++] = {handle.first}; 351 views[views_index++] = {handle.first};
352 352
353 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; 353 VideoCommon::SamplerId sampler{texture_cache.GetGraphicsSamplerId(handle.second)};
354 samplers[samplers_index++] = sampler; 354 samplers[samplers_index++] = sampler;
355 } 355 }
356 } 356 }
@@ -444,7 +444,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
444 program_manager.BindSourcePrograms(source_programs); 444 program_manager.BindSourcePrograms(source_programs);
445 } 445 }
446 const VideoCommon::ImageViewInOut* views_it{views.data()}; 446 const VideoCommon::ImageViewInOut* views_it{views.data()};
447 const Sampler** samplers_it{samplers.data()}; 447 const VideoCommon::SamplerId* samplers_it{samplers.data()};
448 GLsizei texture_binding = 0; 448 GLsizei texture_binding = 0;
449 GLsizei image_binding = 0; 449 GLsizei image_binding = 0;
450 GLsizei sampler_binding{}; 450 GLsizei sampler_binding{};
@@ -484,7 +484,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
484 ++texture_binding; 484 ++texture_binding;
485 ++stage_texture_binding; 485 ++stage_texture_binding;
486 486
487 const Sampler& sampler{**(samplers_it++)}; 487 const Sampler& sampler{texture_cache.GetSampler(*(samplers_it++))};
488 const bool use_fallback_sampler{sampler.HasAddedAnisotropy() && 488 const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
489 !image_view.SupportsAnisotropy()}; 489 !image_view.SupportsAnisotropy()};
490 gl_samplers[sampler_binding++] = 490 gl_samplers[sampler_binding++] =
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h
index 0a9dce937..71c783709 100644
--- a/src/video_core/renderer_vulkan/pipeline_helper.h
+++ b/src/video_core/renderer_vulkan/pipeline_helper.h
@@ -178,7 +178,7 @@ public:
178inline void PushImageDescriptors(TextureCache& texture_cache, 178inline void PushImageDescriptors(TextureCache& texture_cache,
179 GuestDescriptorQueue& guest_descriptor_queue, 179 GuestDescriptorQueue& guest_descriptor_queue,
180 const Shader::Info& info, RescalingPushConstant& rescaling, 180 const Shader::Info& info, RescalingPushConstant& rescaling,
181 const Sampler**& samplers, 181 const VideoCommon::SamplerId*& samplers,
182 const VideoCommon::ImageViewInOut*& views) { 182 const VideoCommon::ImageViewInOut*& views) {
183 const u32 num_texture_buffers = Shader::NumDescriptors(info.texture_buffer_descriptors); 183 const u32 num_texture_buffers = Shader::NumDescriptors(info.texture_buffer_descriptors);
184 const u32 num_image_buffers = Shader::NumDescriptors(info.image_buffer_descriptors); 184 const u32 num_image_buffers = Shader::NumDescriptors(info.image_buffer_descriptors);
@@ -187,9 +187,10 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
187 for (const auto& desc : info.texture_descriptors) { 187 for (const auto& desc : info.texture_descriptors) {
188 for (u32 index = 0; index < desc.count; ++index) { 188 for (u32 index = 0; index < desc.count; ++index) {
189 const VideoCommon::ImageViewId image_view_id{(views++)->id}; 189 const VideoCommon::ImageViewId image_view_id{(views++)->id};
190 const VideoCommon::SamplerId sampler_id{*(samplers++)};
190 ImageView& image_view{texture_cache.GetImageView(image_view_id)}; 191 ImageView& image_view{texture_cache.GetImageView(image_view_id)};
191 const VkImageView vk_image_view{image_view.Handle(desc.type)}; 192 const VkImageView vk_image_view{image_view.Handle(desc.type)};
192 const Sampler& sampler{**(samplers++)}; 193 const Sampler& sampler{texture_cache.GetSampler(sampler_id)};
193 const bool use_fallback_sampler{sampler.HasAddedAnisotropy() && 194 const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
194 !image_view.SupportsAnisotropy()}; 195 !image_view.SupportsAnisotropy()};
195 const VkSampler vk_sampler{use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy() 196 const VkSampler vk_sampler{use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy()
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index eb292dc34..73e585c2b 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -115,7 +115,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
115 115
116 static constexpr size_t max_elements = 64; 116 static constexpr size_t max_elements = 64;
117 boost::container::static_vector<VideoCommon::ImageViewInOut, max_elements> views; 117 boost::container::static_vector<VideoCommon::ImageViewInOut, max_elements> views;
118 boost::container::static_vector<const Sampler*, max_elements> samplers; 118 boost::container::static_vector<VideoCommon::SamplerId, max_elements> samplers;
119 119
120 const auto& qmd{kepler_compute.launch_description}; 120 const auto& qmd{kepler_compute.launch_description};
121 const auto& cbufs{qmd.const_buffer_config}; 121 const auto& cbufs{qmd.const_buffer_config};
@@ -160,7 +160,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
160 const auto handle{read_handle(desc, index)}; 160 const auto handle{read_handle(desc, index)};
161 views.push_back({handle.first}); 161 views.push_back({handle.first});
162 162
163 Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); 163 VideoCommon::SamplerId sampler = texture_cache.GetComputeSamplerId(handle.second);
164 samplers.push_back(sampler); 164 samplers.push_back(sampler);
165 } 165 }
166 } 166 }
@@ -192,7 +192,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
192 buffer_cache.BindHostComputeBuffers(); 192 buffer_cache.BindHostComputeBuffers();
193 193
194 RescalingPushConstant rescaling; 194 RescalingPushConstant rescaling;
195 const Sampler** samplers_it{samplers.data()}; 195 const VideoCommon::SamplerId* samplers_it{samplers.data()};
196 const VideoCommon::ImageViewInOut* views_it{views.data()}; 196 const VideoCommon::ImageViewInOut* views_it{views.data()};
197 PushImageDescriptors(texture_cache, guest_descriptor_queue, info, rescaling, samplers_it, 197 PushImageDescriptors(texture_cache, guest_descriptor_queue, info, rescaling, samplers_it,
198 views_it); 198 views_it);
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index e6e004cb6..c1595642e 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -298,7 +298,7 @@ void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) {
298template <typename Spec> 298template <typename Spec>
299void GraphicsPipeline::ConfigureImpl(bool is_indexed) { 299void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
300 std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views; 300 std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views;
301 std::array<const Sampler*, MAX_IMAGE_ELEMENTS> samplers; 301 std::array<VideoCommon::SamplerId, MAX_IMAGE_ELEMENTS> samplers;
302 size_t sampler_index{}; 302 size_t sampler_index{};
303 size_t view_index{}; 303 size_t view_index{};
304 304
@@ -367,7 +367,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
367 const auto handle{read_handle(desc, index)}; 367 const auto handle{read_handle(desc, index)};
368 views[view_index++] = {handle.first}; 368 views[view_index++] = {handle.first};
369 369
370 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; 370 VideoCommon::SamplerId sampler{texture_cache.GetGraphicsSamplerId(handle.second)};
371 samplers[sampler_index++] = sampler; 371 samplers[sampler_index++] = sampler;
372 } 372 }
373 } 373 }
@@ -453,7 +453,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
453 453
454 RescalingPushConstant rescaling; 454 RescalingPushConstant rescaling;
455 RenderAreaPushConstant render_area; 455 RenderAreaPushConstant render_area;
456 const Sampler** samplers_it{samplers.data()}; 456 const VideoCommon::SamplerId* samplers_it{samplers.data()};
457 const VideoCommon::ImageViewInOut* views_it{views.data()}; 457 const VideoCommon::ImageViewInOut* views_it{views.data()};
458 const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { 458 const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
459 buffer_cache.BindHostStageBuffers(stage); 459 buffer_cache.BindHostStageBuffers(stage);
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp
index 5ebe9b9bb..000eec869 100644
--- a/src/video_core/texture_cache/image_view_base.cpp
+++ b/src/video_core/texture_cache/image_view_base.cpp
@@ -46,7 +46,6 @@ ImageViewBase::ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_in
46ImageViewBase::ImageViewBase(const NullImageViewParams&) : image_id{NULL_IMAGE_ID} {} 46ImageViewBase::ImageViewBase(const NullImageViewParams&) : image_id{NULL_IMAGE_ID} {}
47 47
48bool ImageViewBase::SupportsAnisotropy() const noexcept { 48bool ImageViewBase::SupportsAnisotropy() const noexcept {
49 using namespace VideoCommon;
50 switch (format) { 49 switch (format) {
51 case PixelFormat::R8_UNORM: 50 case PixelFormat::R8_UNORM:
52 case PixelFormat::R8_SNORM: 51 case PixelFormat::R8_SNORM:
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index c7f7448e9..4027d860b 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -222,30 +222,50 @@ void TextureCache<P>::CheckFeedbackLoop(std::span<const ImageViewInOut> views) {
222 222
223template <class P> 223template <class P>
224typename P::Sampler* TextureCache<P>::GetGraphicsSampler(u32 index) { 224typename P::Sampler* TextureCache<P>::GetGraphicsSampler(u32 index) {
225 return &slot_samplers[GetGraphicsSamplerId(index)];
226}
227
228template <class P>
229typename P::Sampler* TextureCache<P>::GetComputeSampler(u32 index) {
230 return &slot_samplers[GetComputeSamplerId(index)];
231}
232
233template <class P>
234SamplerId TextureCache<P>::GetGraphicsSamplerId(u32 index) {
225 if (index > channel_state->graphics_sampler_table.Limit()) { 235 if (index > channel_state->graphics_sampler_table.Limit()) {
226 LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index); 236 LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index);
227 return &slot_samplers[NULL_SAMPLER_ID]; 237 return NULL_SAMPLER_ID;
228 } 238 }
229 const auto [descriptor, is_new] = channel_state->graphics_sampler_table.Read(index); 239 const auto [descriptor, is_new] = channel_state->graphics_sampler_table.Read(index);
230 SamplerId& id = channel_state->graphics_sampler_ids[index]; 240 SamplerId& id = channel_state->graphics_sampler_ids[index];
231 if (is_new) { 241 if (is_new) {
232 id = FindSampler(descriptor); 242 id = FindSampler(descriptor);
233 } 243 }
234 return &slot_samplers[id]; 244 return id;
235} 245}
236 246
237template <class P> 247template <class P>
238typename P::Sampler* TextureCache<P>::GetComputeSampler(u32 index) { 248SamplerId TextureCache<P>::GetComputeSamplerId(u32 index) {
239 if (index > channel_state->compute_sampler_table.Limit()) { 249 if (index > channel_state->compute_sampler_table.Limit()) {
240 LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index); 250 LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index);
241 return &slot_samplers[NULL_SAMPLER_ID]; 251 return NULL_SAMPLER_ID;
242 } 252 }
243 const auto [descriptor, is_new] = channel_state->compute_sampler_table.Read(index); 253 const auto [descriptor, is_new] = channel_state->compute_sampler_table.Read(index);
244 SamplerId& id = channel_state->compute_sampler_ids[index]; 254 SamplerId& id = channel_state->compute_sampler_ids[index];
245 if (is_new) { 255 if (is_new) {
246 id = FindSampler(descriptor); 256 id = FindSampler(descriptor);
247 } 257 }
248 return &slot_samplers[id]; 258 return id;
259}
260
261template <class P>
262const typename P::Sampler& TextureCache<P>::GetSampler(SamplerId id) const noexcept {
263 return slot_samplers[id];
264}
265
266template <class P>
267typename P::Sampler& TextureCache<P>::GetSampler(SamplerId id) noexcept {
268 return slot_samplers[id];
249} 269}
250 270
251template <class P> 271template <class P>
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index 3bfa92154..d96ddea9d 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -159,6 +159,18 @@ public:
159 /// Get the sampler from the compute descriptor table in the specified index 159 /// Get the sampler from the compute descriptor table in the specified index
160 Sampler* GetComputeSampler(u32 index); 160 Sampler* GetComputeSampler(u32 index);
161 161
162 /// Get the sampler id from the graphics descriptor table in the specified index
163 SamplerId GetGraphicsSamplerId(u32 index);
164
165 /// Get the sampler id from the compute descriptor table in the specified index
166 SamplerId GetComputeSamplerId(u32 index);
167
168 /// Return a constant reference to the given sampler id
169 [[nodiscard]] const Sampler& GetSampler(SamplerId id) const noexcept;
170
171 /// Return a reference to the given sampler id
172 [[nodiscard]] Sampler& GetSampler(SamplerId id) noexcept;
173
162 /// Refresh the state for graphics image view and sampler descriptors 174 /// Refresh the state for graphics image view and sampler descriptors
163 void SynchronizeGraphicsDescriptors(); 175 void SynchronizeGraphicsDescriptors();
164 176