From 26100c586f1c3512f539cf1269d4acbd638928b4 Mon Sep 17 00:00:00 2001 From: DrChat Date: Fri, 22 Dec 2017 23:16:20 -0600 Subject: [PATCH] [Vulkan] Track render target state with the pipeline cache --- src/xenia/gpu/vulkan/pipeline_cache.cc | 57 ++++++++++++++++++++++++++ src/xenia/gpu/vulkan/pipeline_cache.h | 15 ++++--- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/src/xenia/gpu/vulkan/pipeline_cache.cc b/src/xenia/gpu/vulkan/pipeline_cache.cc index ca8806085..1214fe0e0 100644 --- a/src/xenia/gpu/vulkan/pipeline_cache.cc +++ b/src/xenia/gpu/vulkan/pipeline_cache.cc @@ -791,6 +791,22 @@ bool PipelineCache::SetShadowRegister(float* dest, uint32_t register_name) { return true; } +bool PipelineCache::SetShadowRegisterArray(uint32_t* dest, uint32_t num, + uint32_t register_name) { + bool dirty = false; + for (uint32_t i = 0; i < num; i++) { + uint32_t value = register_file_->values[register_name + i].u32; + if (dest[i] == value) { + continue; + } + + dest[i] = value; + dirty |= true; + } + + return dirty; +} + PipelineCache::UpdateStatus PipelineCache::UpdateState( VulkanShader* vertex_shader, VulkanShader* pixel_shader, PrimitiveType primitive_type) { @@ -810,6 +826,8 @@ PipelineCache::UpdateStatus PipelineCache::UpdateState( } UpdateStatus status; + status = UpdateRenderTargetState(); + CHECK_UPDATE_STATUS(status, mismatch, "Unable to update render target state"); status = UpdateShaderStages(vertex_shader, pixel_shader, primitive_type); CHECK_UPDATE_STATUS(status, mismatch, "Unable to update shader stages"); status = UpdateVertexInputState(vertex_shader); @@ -831,6 +849,45 @@ PipelineCache::UpdateStatus PipelineCache::UpdateState( return mismatch ? UpdateStatus::kMismatch : UpdateStatus::kCompatible; } +PipelineCache::UpdateStatus PipelineCache::UpdateRenderTargetState() { + auto& regs = update_render_targets_regs_; + bool dirty = false; + + // Check the render target formats + struct { + reg::RB_COLOR_INFO rb_color_info; + reg::RB_DEPTH_INFO rb_depth_info; + reg::RB_COLOR_INFO rb_color1_info; + reg::RB_COLOR_INFO rb_color2_info; + reg::RB_COLOR_INFO rb_color3_info; + }* cur_regs = reinterpret_cast( + ®ister_file_->values[XE_GPU_REG_RB_COLOR_INFO].u32); + + dirty |= + regs.rb_color_info.color_format != cur_regs->rb_color_info.color_format; + dirty |= + regs.rb_depth_info.depth_format != cur_regs->rb_depth_info.depth_format; + dirty |= + regs.rb_color1_info.color_format != cur_regs->rb_color1_info.color_format; + dirty |= + regs.rb_color2_info.color_format != cur_regs->rb_color2_info.color_format; + dirty |= + regs.rb_color3_info.color_format != cur_regs->rb_color3_info.color_format; + + // And copy the regs over. + regs.rb_color_info.color_format = cur_regs->rb_color_info.color_format; + regs.rb_depth_info.depth_format = cur_regs->rb_depth_info.depth_format; + regs.rb_color1_info.color_format = cur_regs->rb_color1_info.color_format; + regs.rb_color2_info.color_format = cur_regs->rb_color2_info.color_format; + regs.rb_color3_info.color_format = cur_regs->rb_color3_info.color_format; + XXH64_update(&hash_state_, ®s, sizeof(regs)); + if (!dirty) { + return UpdateStatus::kCompatible; + } + + return UpdateStatus::kMismatch; +} + PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages( VulkanShader* vertex_shader, VulkanShader* pixel_shader, PrimitiveType primitive_type) { diff --git a/src/xenia/gpu/vulkan/pipeline_cache.h b/src/xenia/gpu/vulkan/pipeline_cache.h index b3fbcdcc0..914f8ac4c 100644 --- a/src/xenia/gpu/vulkan/pipeline_cache.h +++ b/src/xenia/gpu/vulkan/pipeline_cache.h @@ -131,6 +131,7 @@ class PipelineCache { VulkanShader* pixel_shader, PrimitiveType primitive_type); + UpdateStatus UpdateRenderTargetState(); UpdateStatus UpdateShaderStages(VulkanShader* vertex_shader, VulkanShader* pixel_shader, PrimitiveType primitive_type); @@ -144,18 +145,20 @@ class PipelineCache { bool SetShadowRegister(uint32_t* dest, uint32_t register_name); bool SetShadowRegister(float* dest, uint32_t register_name); + bool SetShadowRegisterArray(uint32_t* dest, uint32_t num, + uint32_t register_name); struct UpdateRenderTargetsRegisters { uint32_t rb_modecontrol; - uint32_t rb_surface_info; - uint32_t rb_color_info; - uint32_t rb_color1_info; - uint32_t rb_color2_info; - uint32_t rb_color3_info; + reg::RB_SURFACE_INFO rb_surface_info; + reg::RB_COLOR_INFO rb_color_info; + reg::RB_DEPTH_INFO rb_depth_info; + reg::RB_COLOR_INFO rb_color1_info; + reg::RB_COLOR_INFO rb_color2_info; + reg::RB_COLOR_INFO rb_color3_info; uint32_t rb_color_mask; uint32_t rb_depthcontrol; uint32_t rb_stencilrefmask; - uint32_t rb_depth_info; UpdateRenderTargetsRegisters() { Reset(); } void Reset() { std::memset(this, 0, sizeof(*this)); }