graphics: synchronize host file writes and depth clipping

Map paired PS5 depth-clip state through Vulkan pipeline creation and preserve asymmetric hard failures. Prepare GPU-mapped guest ranges before kernel file reads so buffer, texture, and alias ownership remains coherent. Add focused regression coverage and update the current launch target.
This commit is contained in:
nmzik
2026-07-19 14:33:38 +02:00
parent 91690ac29e
commit aebf6b4913
15 changed files with 184 additions and 6 deletions
+1 -1
View File
@@ -687,7 +687,7 @@ static void ClipCheck(const HW::ClipControl& c) {
// dx_linear_attr_clip_enable preserves linear (noperspective) attributes at clip-generated
// vertices, which Vulkan provides as part of clipping and interpolation.
EXIT_NOT_IMPLEMENTED(c.user_clip_planes != 0 || c.user_clip_plane_mode != 0 ||
c.vertex_kill_any || c.min_z_clip_disable || c.max_z_clip_disable ||
c.vertex_kill_any || !c.IsZClipModeRepresentable() ||
c.user_clip_plane_negate_y || c.clip_disable ||
c.user_clip_plane_cull_only || c.cull_on_clipping_error_disable ||
c.force_viewport_index_from_vs_enable);
@@ -61,6 +61,41 @@ bool GpuResourceManager::HandleFault(PageFaultAccess access, uint64_t fault_vadd
return m_page_manager.HandleFault(access, fault_vaddr);
}
void GpuResourceManager::PrepareHostWrite(uint64_t vaddr, uint64_t size) {
if (!m_page_manager.HasAnyMapping(vaddr, size)) {
return;
}
if (LabelInCallback()) {
EXIT("unsupported host write from an asynchronous GPU label callback, addr=0x%016" PRIx64
" size=0x%016" PRIx64 "\n",
vaddr, size);
}
const auto handle_range = [this, vaddr, size]() {
if (!m_page_manager.HandleWriteRange(vaddr, size)) {
EXIT("failed to prepare host write, addr=0x%016" PRIx64 " size=0x%016" PRIx64
"\n",
vaddr, size);
}
};
if (auto* cp = GraphicsRunCurrentCommandProcessor(); cp != nullptr) {
cp->BeginReadbackTransaction();
{
ResourceMutex::FaultScope fault(m_resource_mutex);
handle_range();
}
cp->EndReadbackTransaction();
return;
}
if (m_resource_mutex.IsOwnedByCurrentThread()) {
EXIT("unsupported host write from a pre-owned resource transaction, addr=0x%016" PRIx64
" size=0x%016" PRIx64 "\n",
vaddr, size);
}
GraphicsRunSubmissionLock submissions;
ResourceMutex::FaultScope fault(m_resource_mutex);
handle_range();
}
bool GpuResourceManager::IsMapped(uint64_t vaddr, uint64_t size) const noexcept {
return m_page_manager.IsMapped(vaddr, size);
}
@@ -24,6 +24,7 @@ public:
[[nodiscard]] TextureCache* GetTextureCache() { return &m_texture_cache; }
[[nodiscard]] bool HandleFault(PageFaultAccess access, uint64_t fault_vaddr) noexcept;
void PrepareHostWrite(uint64_t vaddr, uint64_t size);
[[nodiscard]] bool IsMapped(uint64_t vaddr, uint64_t size) const noexcept;
void MapMemory(uint64_t vaddr, uint64_t size, GpuAccess access);
void UnmapMemory(uint64_t vaddr, uint64_t size, GpuAccess access);
@@ -88,7 +88,10 @@ PipelineCache::GraphicsPipeline* PipelineCache::CreateGraphicsPipeline(
}
}
static_params.negative_one_to_one = !ctx->GetClipControl().dx_clip_space;
const auto& clip_control = ctx->GetClipControl();
EXIT_NOT_IMPLEMENTED(!clip_control.IsZClipModeRepresentable());
static_params.negative_one_to_one = !clip_control.dx_clip_space;
static_params.depth_clip_enable = clip_control.IsZClipEnabled();
static_params.topology = topology;
static_params.samples = framebuffer->samples;
static_params.sample_shading_enable =
@@ -33,6 +33,7 @@ struct PipelineStaticParameters {
float viewport_scale[3] = {};
float viewport_offset[3] = {};
bool negative_one_to_one = false;
bool depth_clip_enable = true;
int scissor_ltrb[4] = {0};
vk::PrimitiveTopology topology = vk::PrimitiveTopology::ePointList;
uint32_t samples = 1;
@@ -75,7 +76,7 @@ static_assert(std::is_trivially_copyable_v<PipelineStaticParameters>);
static_assert(std::is_standard_layout_v<PipelineStaticParameters>);
static_assert(alignof(PipelineStaticParameters) == 1);
static_assert(sizeof(PipelineStaticParameters) ==
sizeof(float[3]) + sizeof(float[3]) + sizeof(bool) + sizeof(int[4]) +
sizeof(float[3]) + sizeof(float[3]) + sizeof(bool) * 2 + sizeof(int[4]) +
sizeof(vk::PrimitiveTopology) + sizeof(uint32_t) + sizeof(bool) * 4 +
sizeof(vk::CompareOp) + sizeof(bool) + sizeof(float) * 2 + sizeof(bool) +
sizeof(PipelineStencilStaticState) * 2 + sizeof(uint32_t) +
+1 -1
View File
@@ -734,7 +734,7 @@ void CreatePipelineInternal(PipelineCache::GraphicsPipeline* pipeline, vk::Rende
clip_ext.sType = vk::StructureType::ePipelineRasterizationDepthClipStateCreateInfoEXT;
clip_ext.pNext = nullptr;
clip_ext.flags = {};
clip_ext.depthClipEnable = VK_FALSE;
clip_ext.depthClipEnable = static_params.depth_clip_enable ? VK_TRUE : VK_FALSE;
vk::PipelineRasterizationStateCreateInfo rasterizer {};
rasterizer.sType = vk::StructureType::ePipelineRasterizationStateCreateInfo;