[vulkan, texture_cache] Add RT's management and feedback loop tracking in texture cache
This commit is contained in:
parent
476f035672
commit
c188b6a819
|
|
@ -291,55 +291,93 @@ void TextureCache<P>::CheckFeedbackLoop(std::span<const ImageViewInOut> views) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (render_targets_serial == last_feedback_loop_serial &&
|
||||
texture_bindings_serial == last_feedback_texture_serial) {
|
||||
if (last_feedback_loop_result) {
|
||||
runtime.BarrierFeedbackLoop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (rt_active_mask == 0) {
|
||||
last_feedback_loop_serial = render_targets_serial;
|
||||
last_feedback_texture_serial = texture_bindings_serial;
|
||||
last_feedback_loop_result = false;
|
||||
return;
|
||||
}
|
||||
const u32 depth_bit = 1u << NUM_RT;
|
||||
const bool depth_active = (rt_active_mask & depth_bit) != 0;
|
||||
|
||||
const bool requires_barrier = [&] {
|
||||
for (const auto& view : views) {
|
||||
if (!view.id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_render_target = false;
|
||||
|
||||
for (const auto& ct_view_id : render_targets.color_buffer_ids) {
|
||||
if (ct_view_id && ct_view_id == view.id) {
|
||||
is_render_target = true;
|
||||
break;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 0)) && view.id == render_targets.color_buffer_ids[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_render_target && render_targets.depth_buffer_id == view.id) {
|
||||
is_render_target = true;
|
||||
if ((rt_active_mask & (1u << 1)) && view.id == render_targets.color_buffer_ids[1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_render_target) {
|
||||
if ((rt_active_mask & (1u << 2)) && view.id == render_targets.color_buffer_ids[2]) {
|
||||
continue;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 3)) && view.id == render_targets.color_buffer_ids[3]) {
|
||||
continue;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 4)) && view.id == render_targets.color_buffer_ids[4]) {
|
||||
continue;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 5)) && view.id == render_targets.color_buffer_ids[5]) {
|
||||
continue;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 6)) && view.id == render_targets.color_buffer_ids[6]) {
|
||||
continue;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 7)) && view.id == render_targets.color_buffer_ids[7]) {
|
||||
continue;
|
||||
}
|
||||
if (depth_active && view.id == render_targets.depth_buffer_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& image_view = slot_image_views[view.id];
|
||||
|
||||
for (const auto& ct_view_id : render_targets.color_buffer_ids) {
|
||||
if (!ct_view_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& ct_view = slot_image_views[ct_view_id];
|
||||
|
||||
if (image_view.image_id == ct_view.image_id) {
|
||||
return true;
|
||||
}
|
||||
const ImageId view_image_id = slot_image_views[view.id].image_id;
|
||||
if ((rt_active_mask & (1u << 0)) && view_image_id == rt0_image_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (render_targets.depth_buffer_id) {
|
||||
auto& zt_view = slot_image_views[render_targets.depth_buffer_id];
|
||||
|
||||
if (image_view.image_id == zt_view.image_id) {
|
||||
return true;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 1)) && view_image_id == rt1_image_id) {
|
||||
return true;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 2)) && view_image_id == rt2_image_id) {
|
||||
return true;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 3)) && view_image_id == rt3_image_id) {
|
||||
return true;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 4)) && view_image_id == rt4_image_id) {
|
||||
return true;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 5)) && view_image_id == rt5_image_id) {
|
||||
return true;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 6)) && view_image_id == rt6_image_id) {
|
||||
return true;
|
||||
}
|
||||
if ((rt_active_mask & (1u << 7)) && view_image_id == rt7_image_id) {
|
||||
return true;
|
||||
}
|
||||
if (depth_active && view_image_id == rt_depth_image_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}();
|
||||
|
||||
last_feedback_loop_serial = render_targets_serial;
|
||||
last_feedback_texture_serial = texture_bindings_serial;
|
||||
last_feedback_loop_result = requires_barrier;
|
||||
if (requires_barrier) {
|
||||
runtime.BarrierFeedbackLoop();
|
||||
}
|
||||
|
|
@ -399,13 +437,19 @@ void TextureCache<P>::SynchronizeGraphicsDescriptors() {
|
|||
const bool linked_tsc = maxwell3d->regs.sampler_binding == SamplerBinding::ViaHeaderBinding;
|
||||
const u32 tic_limit = maxwell3d->regs.tex_header.limit;
|
||||
const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tex_sampler.limit;
|
||||
bool bindings_changed = false;
|
||||
if (channel_state->graphics_sampler_table.Synchronize(maxwell3d->regs.tex_sampler.Address(),
|
||||
tsc_limit)) {
|
||||
channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
|
||||
bindings_changed = true;
|
||||
}
|
||||
if (channel_state->graphics_image_table.Synchronize(maxwell3d->regs.tex_header.Address(),
|
||||
tic_limit)) {
|
||||
channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
|
||||
bindings_changed = true;
|
||||
}
|
||||
if (bindings_changed) {
|
||||
++texture_bindings_serial;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -415,12 +459,18 @@ void TextureCache<P>::SynchronizeComputeDescriptors() {
|
|||
const u32 tic_limit = kepler_compute->regs.tic.limit;
|
||||
const u32 tsc_limit = linked_tsc ? tic_limit : kepler_compute->regs.tsc.limit;
|
||||
const GPUVAddr tsc_gpu_addr = kepler_compute->regs.tsc.Address();
|
||||
bool bindings_changed = false;
|
||||
if (channel_state->compute_sampler_table.Synchronize(tsc_gpu_addr, tsc_limit)) {
|
||||
channel_state->compute_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
|
||||
bindings_changed = true;
|
||||
}
|
||||
if (channel_state->compute_image_table.Synchronize(kepler_compute->regs.tic.Address(),
|
||||
tic_limit)) {
|
||||
channel_state->compute_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
|
||||
bindings_changed = true;
|
||||
}
|
||||
if (bindings_changed) {
|
||||
++texture_bindings_serial;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -534,6 +584,7 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
|||
return;
|
||||
}
|
||||
|
||||
const RenderTargets previous_render_targets = render_targets;
|
||||
const bool rescaled = RescaleRenderTargets();
|
||||
if (is_rescaling != rescaled) {
|
||||
flags[Dirty::RescaleViewports] = true;
|
||||
|
|
@ -549,6 +600,70 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
|||
|
||||
PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id));
|
||||
|
||||
rt_active_mask = 0;
|
||||
const ImageViewId rt0_view = render_targets.color_buffer_ids[0];
|
||||
if (rt0_view) {
|
||||
rt_active_mask |= (1u << 0);
|
||||
rt0_image_id = slot_image_views[rt0_view].image_id;
|
||||
} else {
|
||||
rt0_image_id = ImageId{};
|
||||
}
|
||||
const ImageViewId rt1_view = render_targets.color_buffer_ids[1];
|
||||
if (rt1_view) {
|
||||
rt_active_mask |= (1u << 1);
|
||||
rt1_image_id = slot_image_views[rt1_view].image_id;
|
||||
} else {
|
||||
rt1_image_id = ImageId{};
|
||||
}
|
||||
const ImageViewId rt2_view = render_targets.color_buffer_ids[2];
|
||||
if (rt2_view) {
|
||||
rt_active_mask |= (1u << 2);
|
||||
rt2_image_id = slot_image_views[rt2_view].image_id;
|
||||
} else {
|
||||
rt2_image_id = ImageId{};
|
||||
}
|
||||
const ImageViewId rt3_view = render_targets.color_buffer_ids[3];
|
||||
if (rt3_view) {
|
||||
rt_active_mask |= (1u << 3);
|
||||
rt3_image_id = slot_image_views[rt3_view].image_id;
|
||||
} else {
|
||||
rt3_image_id = ImageId{};
|
||||
}
|
||||
const ImageViewId rt4_view = render_targets.color_buffer_ids[4];
|
||||
if (rt4_view) {
|
||||
rt_active_mask |= (1u << 4);
|
||||
rt4_image_id = slot_image_views[rt4_view].image_id;
|
||||
} else {
|
||||
rt4_image_id = ImageId{};
|
||||
}
|
||||
const ImageViewId rt5_view = render_targets.color_buffer_ids[5];
|
||||
if (rt5_view) {
|
||||
rt_active_mask |= (1u << 5);
|
||||
rt5_image_id = slot_image_views[rt5_view].image_id;
|
||||
} else {
|
||||
rt5_image_id = ImageId{};
|
||||
}
|
||||
const ImageViewId rt6_view = render_targets.color_buffer_ids[6];
|
||||
if (rt6_view) {
|
||||
rt_active_mask |= (1u << 6);
|
||||
rt6_image_id = slot_image_views[rt6_view].image_id;
|
||||
} else {
|
||||
rt6_image_id = ImageId{};
|
||||
}
|
||||
const ImageViewId rt7_view = render_targets.color_buffer_ids[7];
|
||||
if (rt7_view) {
|
||||
rt_active_mask |= (1u << 7);
|
||||
rt7_image_id = slot_image_views[rt7_view].image_id;
|
||||
} else {
|
||||
rt7_image_id = ImageId{};
|
||||
}
|
||||
if (depth_buffer_id) {
|
||||
rt_active_mask |= (1u << NUM_RT);
|
||||
rt_depth_image_id = slot_image_views[depth_buffer_id].image_id;
|
||||
} else {
|
||||
rt_depth_image_id = ImageId{};
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < NUM_RT; ++index) {
|
||||
render_targets.draw_buffers[index] = static_cast<u8>(maxwell3d->regs.rt_control.Map(index));
|
||||
}
|
||||
|
|
@ -564,12 +679,22 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
|||
};
|
||||
render_targets.is_rescaled = is_rescaling;
|
||||
|
||||
if (render_targets != previous_render_targets) {
|
||||
++render_targets_serial;
|
||||
}
|
||||
|
||||
flags[Dirty::DepthBiasGlobal] = true;
|
||||
}
|
||||
|
||||
template <class P>
|
||||
typename P::Framebuffer* TextureCache<P>::GetFramebuffer() {
|
||||
return &slot_framebuffers[GetFramebufferId(render_targets)];
|
||||
if (last_framebuffer_id && last_framebuffer_serial == render_targets_serial) {
|
||||
return &slot_framebuffers[last_framebuffer_id];
|
||||
}
|
||||
const FramebufferId framebuffer_id = GetFramebufferId(render_targets);
|
||||
last_framebuffer_id = framebuffer_id;
|
||||
last_framebuffer_serial = render_targets_serial;
|
||||
return &slot_framebuffers[framebuffer_id];
|
||||
}
|
||||
|
||||
template <class P>
|
||||
|
|
@ -2614,6 +2739,10 @@ void TextureCache<P>::RemoveFramebuffers(std::span<const ImageViewId> removed_vi
|
|||
if (it->first.Contains(removed_views)) {
|
||||
auto framebuffer_id = it->second;
|
||||
ASSERT(framebuffer_id);
|
||||
if (framebuffer_id == last_framebuffer_id) {
|
||||
last_framebuffer_id = {};
|
||||
last_framebuffer_serial = 0;
|
||||
}
|
||||
sentenced_framebuffers.Push(std::move(slot_framebuffers[framebuffer_id]));
|
||||
it = framebuffers.erase(it);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -455,6 +455,23 @@ private:
|
|||
std::deque<TextureCacheGPUMap> gpu_page_table_storage;
|
||||
|
||||
RenderTargets render_targets;
|
||||
u64 render_targets_serial = 0;
|
||||
u32 rt_active_mask = 0;
|
||||
ImageId rt0_image_id{};
|
||||
ImageId rt1_image_id{};
|
||||
ImageId rt2_image_id{};
|
||||
ImageId rt3_image_id{};
|
||||
ImageId rt4_image_id{};
|
||||
ImageId rt5_image_id{};
|
||||
ImageId rt6_image_id{};
|
||||
ImageId rt7_image_id{};
|
||||
ImageId rt_depth_image_id{};
|
||||
u64 texture_bindings_serial = 0;
|
||||
u64 last_feedback_loop_serial = 0;
|
||||
u64 last_feedback_texture_serial = 0;
|
||||
bool last_feedback_loop_result = false;
|
||||
FramebufferId last_framebuffer_id{};
|
||||
u64 last_framebuffer_serial = 0;
|
||||
|
||||
ankerl::unordered_dense::map<RenderTargets, FramebufferId> framebuffers;
|
||||
ankerl::unordered_dense::map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table;
|
||||
|
|
|
|||
Loading…
Reference in New Issue