[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) {
for (uint32_t i = 0; i < 5; ++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 (enabled[i]) {
continue;
}
// Checking if now overlapping a 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 {
if (!(render_targets_to_attach & (1 << i))) {
continue;
}
// Checking if the new render target is overlapping any bound one.
// 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) {
const RenderTargetBinding& binding_2 = current_bindings_[j];
if (!binding_2.is_bound) {
continue;
}
uint32_t edram_length_2;
uint32_t edram_dirty_rows_2;
if (binding_1.is_bound) {
if (!enabled[j]) {
continue;
}
// Checking if now overlapping a previously 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 {
// Checking if the new render target is overlapping any bound one.
// 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.
if (edram_bases[i] < edram_bases[j] + edram_length_2 &&
edram_bases[i] + edram_length_1 > edram_bases[j]) {
XELOGGPU("RT Cache: Overlap between %u (%u:%u) and %u (%u:%u)", i,
edram_bases[i], edram_bases[i] + edram_length_1 - 1, j,
edram_bases[j], edram_bases[j] + edram_length_2 - 1);
if (edram_bases[i] <
edram_bases[j] + edram_dirty_rows_2 * edram_row_tiles[j] &&
edram_bases[j] <
edram_bases[i] + edram_dirty_rows_1 * edram_row_tiles[i]) {
full_update = true;
break;
}
@ -545,7 +544,7 @@ bool RenderTargetCache::UpdateRenderTargets() {
RenderTargetBinding& binding = current_bindings_[i];
binding.is_bound = true;
binding.edram_base = edram_bases[i];
binding.edram_dirty_length = 0;
binding.edram_dirty_rows = 0;
binding.format = formats[i];
binding.render_target = nullptr;
@ -682,8 +681,8 @@ bool RenderTargetCache::UpdateRenderTargets() {
// Nothing to store to the EDRAM buffer if there was an error.
continue;
}
binding.edram_dirty_length = std::max(
binding.edram_dirty_length, edram_dirty_rows * edram_row_tiles[i]);
binding.edram_dirty_rows =
std::max(binding.edram_dirty_rows, edram_dirty_rows);
}
return true;
@ -895,12 +894,6 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
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.
uint32_t store_bindings[5];
@ -916,9 +909,8 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
for (uint32_t i = 0; i < 5; ++i) {
const RenderTargetBinding& binding = current_bindings_[i];
RenderTarget* render_target = binding.render_target;
// TODO(Triang3l): Change edram_dirty_length to dirty row count.
if (!binding.is_bound || render_target == nullptr ||
binding.edram_dirty_length < surface_pitch_tiles) {
binding.edram_dirty_rows < 0) {
continue;
}
store_bindings[store_binding_count] = i;
@ -1010,6 +1002,13 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
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.
for (uint32_t i = 0; i < store_binding_count; ++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);
command_processor_->SetPipeline(
edram_load_store_pipelines_[size_t(pipeline_index)]);
command_list->Dispatch(
root_constants.pitch_tiles,
binding.edram_dirty_length / root_constants.pitch_tiles, 1);
command_list->Dispatch(root_constants.pitch_tiles, binding.edram_dirty_rows,
1);
// Commit the UAV write and prepare for copying again.
barrier_count = 1;

View File

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