mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-04 17:53:17 +00:00
shader_recompiler: Implement AMD buffer bounds checking behavior. (#2448)
* shader_recompiler: Implement AMD buffer bounds checking behavior. * shader_recompiler: Use SRT flatbuf for bounds check size. * shader_recompiler: Fix buffer atomic bounds check. * buffer_cache: Prevent false image-to-buffer sync. Lowering vertex fetch to formatted buffer surfaced an issue where a CPU modified range may be overwritten with stale GPU modified image data. * Address review comments.
This commit is contained in:
parent
b06790dfe5
commit
fd3d3c4158
19 changed files with 376 additions and 158 deletions
|
@ -608,7 +608,11 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr,
|
|||
return false;
|
||||
}
|
||||
Image& image = texture_cache.GetImage(image_id);
|
||||
if (False(image.flags & ImageFlagBits::GpuModified)) {
|
||||
// Only perform sync if image is:
|
||||
// - GPU modified; otherwise there are no changes to synchronize.
|
||||
// - Not CPU modified; otherwise we could overwrite CPU changes with stale GPU changes.
|
||||
if (False(image.flags & ImageFlagBits::GpuModified) ||
|
||||
True(image.flags & ImageFlagBits::CpuDirty)) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_MSG(device_addr == image.info.guest_address,
|
||||
|
|
|
@ -210,9 +210,6 @@ bool Instance::CreateDevice() {
|
|||
vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT,
|
||||
vk::PhysicalDevicePortabilitySubsetFeaturesKHR>();
|
||||
features = feature_chain.get().features;
|
||||
#ifdef __APPLE__
|
||||
portability_features = feature_chain.get<vk::PhysicalDevicePortabilitySubsetFeaturesKHR>();
|
||||
#endif
|
||||
|
||||
const vk::StructureChain properties_chain = physical_device.getProperties2<
|
||||
vk::PhysicalDeviceProperties2, vk::PhysicalDeviceVulkan11Properties,
|
||||
|
@ -258,16 +255,19 @@ bool Instance::CreateDevice() {
|
|||
add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
|
||||
dynamic_color_write_mask = add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||
if (dynamic_color_write_mask) {
|
||||
dynamic_color_write_mask =
|
||||
feature_chain.get<vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT>()
|
||||
.extendedDynamicState3ColorWriteMask;
|
||||
dynamic_state_3 = add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||
if (dynamic_state_3) {
|
||||
dynamic_state_3_features =
|
||||
feature_chain.get<vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT>();
|
||||
LOG_INFO(Render_Vulkan, "- extendedDynamicState3ColorWriteMask: {}",
|
||||
dynamic_state_3_features.extendedDynamicState3ColorWriteMask);
|
||||
}
|
||||
null_descriptor = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
|
||||
if (null_descriptor) {
|
||||
null_descriptor =
|
||||
feature_chain.get<vk::PhysicalDeviceRobustness2FeaturesEXT>().nullDescriptor;
|
||||
robustness2 = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
|
||||
if (robustness2) {
|
||||
robustness2_features = feature_chain.get<vk::PhysicalDeviceRobustness2FeaturesEXT>();
|
||||
LOG_INFO(Render_Vulkan, "- robustBufferAccess2: {}",
|
||||
robustness2_features.robustBufferAccess2);
|
||||
LOG_INFO(Render_Vulkan, "- nullDescriptor: {}", robustness2_features.nullDescriptor);
|
||||
}
|
||||
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
depth_clip_control = add_extension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
||||
|
@ -284,6 +284,9 @@ bool Instance::CreateDevice() {
|
|||
#ifdef __APPLE__
|
||||
// Required by Vulkan spec if supported.
|
||||
portability_subset = add_extension(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
|
||||
if (portability_subset) {
|
||||
portability_features = feature_chain.get<vk::PhysicalDevicePortabilitySubsetFeaturesKHR>();
|
||||
}
|
||||
#endif
|
||||
|
||||
const auto family_properties = physical_device.getQueueFamilyProperties();
|
||||
|
@ -387,13 +390,15 @@ bool Instance::CreateDevice() {
|
|||
.customBorderColorWithoutFormat = true,
|
||||
},
|
||||
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT{
|
||||
.extendedDynamicState3ColorWriteMask = true,
|
||||
.extendedDynamicState3ColorWriteMask =
|
||||
dynamic_state_3_features.extendedDynamicState3ColorWriteMask,
|
||||
},
|
||||
vk::PhysicalDeviceDepthClipControlFeaturesEXT{
|
||||
.depthClipControl = true,
|
||||
},
|
||||
vk::PhysicalDeviceRobustness2FeaturesEXT{
|
||||
.nullDescriptor = true,
|
||||
.robustBufferAccess2 = robustness2_features.robustBufferAccess2,
|
||||
.nullDescriptor = robustness2_features.nullDescriptor,
|
||||
},
|
||||
vk::PhysicalDeviceVertexInputDynamicStateFeaturesEXT{
|
||||
.vertexInputDynamicState = true,
|
||||
|
@ -420,13 +425,13 @@ bool Instance::CreateDevice() {
|
|||
if (!custom_border_color) {
|
||||
device_chain.unlink<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>();
|
||||
}
|
||||
if (!dynamic_color_write_mask) {
|
||||
if (!dynamic_state_3) {
|
||||
device_chain.unlink<vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT>();
|
||||
}
|
||||
if (!depth_clip_control) {
|
||||
device_chain.unlink<vk::PhysicalDeviceDepthClipControlFeaturesEXT>();
|
||||
}
|
||||
if (!null_descriptor) {
|
||||
if (!robustness2) {
|
||||
device_chain.unlink<vk::PhysicalDeviceRobustness2FeaturesEXT>();
|
||||
}
|
||||
if (!vertex_input_dynamic_state) {
|
||||
|
|
|
@ -99,9 +99,10 @@ public:
|
|||
return depth_clip_control;
|
||||
}
|
||||
|
||||
/// Returns true when dynamic color write mask state is supported
|
||||
/// Returns true when the extendedDynamicState3ColorWriteMask feature of
|
||||
/// VK_EXT_extended_dynamic_state3 is supported.
|
||||
bool IsDynamicColorWriteMaskSupported() const {
|
||||
return dynamic_color_write_mask;
|
||||
return dynamic_state_3 && dynamic_state_3_features.extendedDynamicState3ColorWriteMask;
|
||||
}
|
||||
|
||||
/// Returns true when VK_EXT_vertex_input_dynamic_state is supported.
|
||||
|
@ -109,9 +110,14 @@ public:
|
|||
return vertex_input_dynamic_state;
|
||||
}
|
||||
|
||||
/// Returns true when the robustBufferAccess2 feature of VK_EXT_robustness2 is supported.
|
||||
bool IsRobustBufferAccess2Supported() const {
|
||||
return robustness2 && robustness2_features.robustBufferAccess2;
|
||||
}
|
||||
|
||||
/// Returns true when the nullDescriptor feature of VK_EXT_robustness2 is supported.
|
||||
bool IsNullDescriptorSupported() const {
|
||||
return null_descriptor;
|
||||
return robustness2 && robustness2_features.nullDescriptor;
|
||||
}
|
||||
|
||||
/// Returns true when VK_KHR_fragment_shader_barycentric is supported.
|
||||
|
@ -303,6 +309,8 @@ private:
|
|||
vk::PhysicalDevicePushDescriptorPropertiesKHR push_descriptor_props;
|
||||
vk::PhysicalDeviceFeatures features;
|
||||
vk::PhysicalDevicePortabilitySubsetFeaturesKHR portability_features;
|
||||
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT dynamic_state_3_features;
|
||||
vk::PhysicalDeviceRobustness2FeaturesEXT robustness2_features;
|
||||
vk::DriverIdKHR driver_id;
|
||||
vk::UniqueDebugUtilsMessengerEXT debug_callback{};
|
||||
std::string vendor_name;
|
||||
|
@ -317,9 +325,9 @@ private:
|
|||
bool custom_border_color{};
|
||||
bool fragment_shader_barycentric{};
|
||||
bool depth_clip_control{};
|
||||
bool dynamic_color_write_mask{};
|
||||
bool dynamic_state_3{};
|
||||
bool vertex_input_dynamic_state{};
|
||||
bool null_descriptor{};
|
||||
bool robustness2{};
|
||||
bool list_restart{};
|
||||
bool legacy_vertex_attributes{};
|
||||
bool shader_stencil_export{};
|
||||
|
|
|
@ -200,6 +200,7 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
|
|||
.support_legacy_vertex_attributes = instance_.IsLegacyVertexAttributesSupported(),
|
||||
.supports_image_load_store_lod = instance_.IsImageLoadStoreLodSupported(),
|
||||
.supports_native_cube_calc = instance_.IsAmdGcnShaderSupported(),
|
||||
.supports_robust_buffer_access = instance_.IsRobustBufferAccess2Supported(),
|
||||
.needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() &&
|
||||
instance.GetDriverID() == vk::DriverId::eNvidiaProprietary,
|
||||
.needs_lds_barriers = instance.GetDriverID() == vk::DriverId::eNvidiaProprietary ||
|
||||
|
|
|
@ -447,7 +447,6 @@ bool Rasterizer::BindResources(const Pipeline* pipeline) {
|
|||
set_writes.clear();
|
||||
buffer_barriers.clear();
|
||||
buffer_infos.clear();
|
||||
buffer_views.clear();
|
||||
image_infos.clear();
|
||||
|
||||
// Bind resource buffers and textures.
|
||||
|
|
|
@ -110,18 +110,17 @@ private:
|
|||
std::pair<VideoCore::ImageId, VideoCore::TextureCache::RenderTargetDesc>, 8>
|
||||
cb_descs;
|
||||
std::optional<std::pair<VideoCore::ImageId, VideoCore::TextureCache::DepthTargetDesc>> db_desc;
|
||||
boost::container::static_vector<vk::DescriptorImageInfo, 64> image_infos;
|
||||
boost::container::static_vector<vk::BufferView, 16> buffer_views;
|
||||
boost::container::static_vector<vk::DescriptorBufferInfo, 32> buffer_infos;
|
||||
boost::container::static_vector<VideoCore::ImageId, 64> bound_images;
|
||||
boost::container::static_vector<vk::DescriptorImageInfo, Shader::NumImages> image_infos;
|
||||
boost::container::static_vector<vk::DescriptorBufferInfo, Shader::NumBuffers> buffer_infos;
|
||||
boost::container::static_vector<VideoCore::ImageId, Shader::NumImages> bound_images;
|
||||
|
||||
Pipeline::DescriptorWrites set_writes;
|
||||
Pipeline::BufferBarriers buffer_barriers;
|
||||
|
||||
using BufferBindingInfo = std::pair<VideoCore::BufferId, AmdGpu::Buffer>;
|
||||
boost::container::static_vector<BufferBindingInfo, 32> buffer_bindings;
|
||||
boost::container::static_vector<BufferBindingInfo, Shader::NumBuffers> buffer_bindings;
|
||||
using ImageBindingInfo = std::pair<VideoCore::ImageId, VideoCore::TextureCache::TextureDesc>;
|
||||
boost::container::static_vector<ImageBindingInfo, 64> image_bindings;
|
||||
boost::container::static_vector<ImageBindingInfo, Shader::NumImages> image_bindings;
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue