[D3D12] Count dirty RT rows rather than tiles

This commit is contained in:
Triang3l 2018-08-11 21:04:14 +03:00
parent 9b303c64ba
commit c7da5f0572
2 changed files with 26 additions and 28 deletions

View File

@ -442,46 +442,45 @@ bool RenderTargetCache::UpdateRenderTargets() {
if (!full_update) { if (!full_update) {
for (uint32_t i = 0; i < 5; ++i) { for (uint32_t i = 0; i < 5; ++i) {
const RenderTargetBinding& binding_1 = current_bindings_[i]; const RenderTargetBinding& binding_1 = current_bindings_[i];
uint32_t edram_length_1; uint32_t edram_dirty_rows_1;
if (binding_1.is_bound) { if (binding_1.is_bound) {
if (enabled[i]) { if (enabled[i]) {
continue; continue;
} }
// Checking if now overlapping a previously used render target. // Checking if now overlapping a previously used render target.
// binding_1 is the previously used render target. // binding_1 is the previously used render target.
edram_length_1 = binding_1.edram_dirty_length; edram_dirty_rows_1 = binding_1.edram_dirty_rows;
} else { } else {
if (!(render_targets_to_attach & (1 << i))) { if (!(render_targets_to_attach & (1 << i))) {
continue; continue;
} }
// Checking if the new render target is overlapping any bound one. // Checking if the new render target is overlapping any bound one.
// binding_1 is the new render target. // binding_1 is the new render target.
edram_length_1 = edram_dirty_rows * edram_row_tiles[i]; edram_dirty_rows_1 = edram_dirty_rows;
} }
for (uint32_t j = 0; j < 5; ++j) { for (uint32_t j = 0; j < 5; ++j) {
const RenderTargetBinding& binding_2 = current_bindings_[j]; const RenderTargetBinding& binding_2 = current_bindings_[j];
if (!binding_2.is_bound) { if (!binding_2.is_bound) {
continue; continue;
} }
uint32_t edram_length_2; uint32_t edram_dirty_rows_2;
if (binding_1.is_bound) { if (binding_1.is_bound) {
if (!enabled[j]) { if (!enabled[j]) {
continue; continue;
} }
// Checking if now overlapping a previously used render target. // Checking if now overlapping a previously used render target.
// binding_2 is a currently used render target. // binding_2 is a currently used render target.
edram_length_2 = edram_dirty_rows * edram_row_tiles[i]; edram_dirty_rows_2 = edram_dirty_rows;
} else { } else {
// Checking if the new render target is overlapping any bound one. // Checking if the new render target is overlapping any bound one.
// binding_2 is another bound render target. // binding_2 is another bound render target.
edram_length_2 = binding_2.edram_dirty_length; edram_dirty_rows_2 = binding_2.edram_dirty_rows;
} }
// Do a full update if there is overlap. // Do a full update if there is overlap.
if (edram_bases[i] < edram_bases[j] + edram_length_2 && if (edram_bases[i] <
edram_bases[i] + edram_length_1 > edram_bases[j]) { edram_bases[j] + edram_dirty_rows_2 * edram_row_tiles[j] &&
XELOGGPU("RT Cache: Overlap between %u (%u:%u) and %u (%u:%u)", i, edram_bases[j] <
edram_bases[i], edram_bases[i] + edram_length_1 - 1, j, edram_bases[i] + edram_dirty_rows_1 * edram_row_tiles[i]) {
edram_bases[j], edram_bases[j] + edram_length_2 - 1);
full_update = true; full_update = true;
break; break;
} }
@ -545,7 +544,7 @@ bool RenderTargetCache::UpdateRenderTargets() {
RenderTargetBinding& binding = current_bindings_[i]; RenderTargetBinding& binding = current_bindings_[i];
binding.is_bound = true; binding.is_bound = true;
binding.edram_base = edram_bases[i]; binding.edram_base = edram_bases[i];
binding.edram_dirty_length = 0; binding.edram_dirty_rows = 0;
binding.format = formats[i]; binding.format = formats[i];
binding.render_target = nullptr; binding.render_target = nullptr;
@ -682,8 +681,8 @@ bool RenderTargetCache::UpdateRenderTargets() {
// Nothing to store to the EDRAM buffer if there was an error. // Nothing to store to the EDRAM buffer if there was an error.
continue; continue;
} }
binding.edram_dirty_length = std::max( binding.edram_dirty_rows =
binding.edram_dirty_length, edram_dirty_rows * edram_row_tiles[i]); std::max(binding.edram_dirty_rows, edram_dirty_rows);
} }
return true; return true;
@ -895,12 +894,6 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
return; return;
} }
uint32_t surface_pitch_ss =
current_surface_pitch_ *
(current_msaa_samples_ >= MsaaSamples::k4X ? 2 : 1);
uint32_t surface_pitch_tiles = (surface_pitch_ss + 79) / 80;
assert_true(surface_pitch_tiles != 0);
// TODO(Triang3l): Clear the buffer if calling for the first time. // TODO(Triang3l): Clear the buffer if calling for the first time.
uint32_t store_bindings[5]; uint32_t store_bindings[5];
@ -916,9 +909,8 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
for (uint32_t i = 0; i < 5; ++i) { for (uint32_t i = 0; i < 5; ++i) {
const RenderTargetBinding& binding = current_bindings_[i]; const RenderTargetBinding& binding = current_bindings_[i];
RenderTarget* render_target = binding.render_target; RenderTarget* render_target = binding.render_target;
// TODO(Triang3l): Change edram_dirty_length to dirty row count.
if (!binding.is_bound || render_target == nullptr || if (!binding.is_bound || render_target == nullptr ||
binding.edram_dirty_length < surface_pitch_tiles) { binding.edram_dirty_rows < 0) {
continue; continue;
} }
store_bindings[store_binding_count] = i; store_bindings[store_binding_count] = i;
@ -1010,6 +1002,13 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
return a < b; return a < b;
}); });
// Calculate the dispatch width.
uint32_t surface_pitch_ss =
current_surface_pitch_ *
(current_msaa_samples_ >= MsaaSamples::k4X ? 2 : 1);
uint32_t surface_pitch_tiles = (surface_pitch_ss + 79) / 80;
assert_true(surface_pitch_tiles != 0);
// Store each render target. // Store each render target.
for (uint32_t i = 0; i < store_binding_count; ++i) { for (uint32_t i = 0; i < store_binding_count; ++i) {
const RenderTargetBinding& binding = current_bindings_[store_bindings[i]]; const RenderTargetBinding& binding = current_bindings_[store_bindings[i]];
@ -1093,9 +1092,8 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
0, sizeof(root_constants) / sizeof(uint32_t), &root_constants, 0); 0, sizeof(root_constants) / sizeof(uint32_t), &root_constants, 0);
command_processor_->SetPipeline( command_processor_->SetPipeline(
edram_load_store_pipelines_[size_t(pipeline_index)]); edram_load_store_pipelines_[size_t(pipeline_index)]);
command_list->Dispatch( command_list->Dispatch(root_constants.pitch_tiles, binding.edram_dirty_rows,
root_constants.pitch_tiles, 1);
binding.edram_dirty_length / root_constants.pitch_tiles, 1);
// Commit the UAV write and prepare for copying again. // Commit the UAV write and prepare for copying again.
barrier_count = 1; barrier_count = 1;

View File

@ -301,9 +301,9 @@ class RenderTargetCache {
// Whether this render target has been used since the last full update. // Whether this render target has been used since the last full update.
bool is_bound; bool is_bound;
uint32_t edram_base; uint32_t edram_base;
// How many tiles has already been drawn to the render target since the last // How many 16-pixel rows has already been drawn to the render target since
// full update. // the last full update.
uint32_t edram_dirty_length; uint32_t edram_dirty_rows;
union { union {
uint32_t format; uint32_t format;
ColorRenderTargetFormat color_format; ColorRenderTargetFormat color_format;