diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 2ed0ddc8..4530f690 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -31,7 +31,11 @@ BufferCache::BufferCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& s Vulkan::SetObjectName(instance.GetDevice(), gds_buffer.Handle(), "GDS Buffer"); // Ensure the first slot is used for the null buffer - void(slot_buffers.insert(instance, scheduler, MemoryUsage::DeviceLocal, 0, ReadFlags, 1)); + const auto null_id = + slot_buffers.insert(instance, scheduler, MemoryUsage::DeviceLocal, 0, ReadFlags, 1); + ASSERT(null_id.index == 0); + const vk::Buffer& null_buffer = slot_buffers[null_id].buffer; + Vulkan::SetObjectName(instance.GetDevice(), null_buffer, "Null Buffer"); } BufferCache::~BufferCache() = default; diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index cd6ea28f..8927083c 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -62,6 +62,11 @@ public: return &gds_buffer; } + /// Retrieves the buffer with the specified id. + [[nodiscard]] Buffer& GetBuffer(BufferId id) { + return slot_buffers[id]; + } + /// Invalidates any buffer in the logical page range. void InvalidateMemory(VAddr device_addr, u64 size); diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 96358bf6..d9296b50 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -221,8 +221,12 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, const auto& image_view = texture_cache.FindTexture(image_info, view_info); const auto& image = texture_cache.GetImage(image_view.image_id); image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view, image.layout); - } else { + } else if (instance.IsNullDescriptorSupported()) { image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, vk::ImageLayout::eGeneral); + } else { + auto& null_image = texture_cache.GetImageView(VideoCore::NULL_IMAGE_VIEW_ID); + image_infos.emplace_back(VK_NULL_HANDLE, *null_image.image_view, + vk::ImageLayout::eGeneral); } set_writes.push_back({ .dstSet = VK_NULL_HANDLE, diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index f7474b24..dc311a7c 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -386,8 +386,11 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, push_data.AddOffset(binding, adjust); } buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned, size + adjust); - } else { + } else if (instance.IsNullDescriptorSupported()) { buffer_infos.emplace_back(VK_NULL_HANDLE, 0, VK_WHOLE_SIZE); + } else { + auto& null_buffer = buffer_cache.GetBuffer(VideoCore::NULL_BUFFER_ID); + buffer_infos.emplace_back(null_buffer.Handle(), 0, VK_WHOLE_SIZE); } set_writes.push_back({ .dstSet = VK_NULL_HANDLE, @@ -451,8 +454,12 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, const auto& image_view = texture_cache.FindTexture(image_info, view_info); const auto& image = texture_cache.GetImage(image_view.image_id); image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view, image.layout); - } else { + } else if (instance.IsNullDescriptorSupported()) { image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, vk::ImageLayout::eGeneral); + } else { + auto& null_image = texture_cache.GetImageView(VideoCore::NULL_IMAGE_VIEW_ID); + image_infos.emplace_back(VK_NULL_HANDLE, *null_image.image_view, + vk::ImageLayout::eGeneral); } set_writes.push_back({ .dstSet = VK_NULL_HANDLE, diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 0ea814e1..0bc73e14 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -381,9 +381,12 @@ bool Instance::CreateDevice() { device_chain.unlink(); } if (robustness) { - device_chain.get().nullDescriptor = + null_descriptor = feature_chain.get().nullDescriptor; + device_chain.get().nullDescriptor = + null_descriptor; } else { + null_descriptor = false; device_chain.unlink(); } if (!vertex_input_dynamic_state) { diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 3b354bab..1c94f586 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -132,6 +132,11 @@ public: return vertex_input_dynamic_state; } + /// Returns true when the nullDescriptor feature of VK_EXT_robustness2 is supported. + bool IsNullDescriptorSupported() const { + return null_descriptor; + } + /// Returns the vendor ID of the physical device u32 GetVendorID() const { return properties.vendorID; @@ -279,6 +284,7 @@ private: bool workgroup_memory_explicit_layout{}; bool color_write_en{}; bool vertex_input_dynamic_state{}; + bool null_descriptor{}; u64 min_imported_host_pointer_alignment{}; u32 subgroup_size{}; bool tooling_info{}; diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 3219f45b..8621e95f 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -29,10 +29,16 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& info.UpdateSize(); const ImageId null_id = slot_images.insert(instance, scheduler, info); ASSERT(null_id.index == 0); + const vk::Image& null_image = slot_images[null_id].image; + Vulkan::SetObjectName(instance.GetDevice(), null_image, "Null Image"); slot_images[null_id].flags = ImageFlagBits::Tracked; ImageViewInfo view_info; - void(slot_image_views.insert(instance, view_info, slot_images[null_id], null_id)); + const auto null_view_id = + slot_image_views.insert(instance, view_info, slot_images[null_id], null_id); + ASSERT(null_view_id.index == 0); + const vk::ImageView& null_image_view = slot_image_views[null_view_id].image_view.get(); + Vulkan::SetObjectName(instance.GetDevice(), null_image_view, "Null Image View"); } TextureCache::~TextureCache() = default; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index cc19ac4a..329128a3 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -98,6 +98,11 @@ public: return slot_images[id]; } + /// Retrieves the image view with the specified id. + [[nodiscard]] ImageView& GetImageView(ImageId id) { + return slot_image_views[id]; + } + bool IsMeta(VAddr address) const { return surface_metas.contains(address); }