Browse Source

[vulkan] Add resume/supend bits on renderpass

tiled-gpu
CamilleLaVey 3 weeks ago
parent
commit
4fbdc133dd
  1. 12
      src/video_core/renderer_vulkan/vk_buffer_cache.cpp
  2. 173
      src/video_core/renderer_vulkan/vk_scheduler.cpp
  3. 9
      src/video_core/renderer_vulkan/vk_scheduler.h

12
src/video_core/renderer_vulkan/vk_buffer_cache.cpp

@ -197,7 +197,7 @@ public:
} }
if (!host_visible) { if (!host_visible) {
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.RequestOutsideRenderPassOperationContext(true);
scheduler.Record([src_buffer = staging.buffer, src_offset = staging.offset, scheduler.Record([src_buffer = staging.buffer, src_offset = staging.offset,
dst_buffer = *buffer, size_bytes](vk::CommandBuffer cmdbuf) { dst_buffer = *buffer, size_bytes](vk::CommandBuffer cmdbuf) {
const VkBufferCopy copy{ const VkBufferCopy copy{
@ -454,7 +454,7 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
return; return;
} }
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.RequestOutsideRenderPassOperationContext(true);
scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) { scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) {
if (barrier) { if (barrier) {
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
@ -475,7 +475,7 @@ void BufferCacheRuntime::PreCopyBarrier() {
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
}; };
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.RequestOutsideRenderPassOperationContext(true);
scheduler.Record([](vk::CommandBuffer cmdbuf) { scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
0, READ_BARRIER); 0, READ_BARRIER);
@ -489,7 +489,7 @@ void BufferCacheRuntime::PostCopyBarrier() {
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
}; };
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.RequestOutsideRenderPassOperationContext(true);
scheduler.Record([](vk::CommandBuffer cmdbuf) { scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
0, WRITE_BARRIER); 0, WRITE_BARRIER);
@ -513,7 +513,7 @@ void BufferCacheRuntime::ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t si
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
}; };
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.RequestOutsideRenderPassOperationContext(true);
scheduler.Record([dest_buffer, offset, size, value](vk::CommandBuffer cmdbuf) { scheduler.Record([dest_buffer, offset, size, value](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
0, READ_BARRIER); 0, READ_BARRIER);
@ -695,7 +695,7 @@ vk::Buffer BufferCacheRuntime::CreateNullBuffer() {
ret.SetObjectNameEXT("Null buffer"); ret.SetObjectNameEXT("Null buffer");
} }
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.RequestOutsideRenderPassOperationContext(true);
scheduler.Record([buffer = *ret](vk::CommandBuffer cmdbuf) { scheduler.Record([buffer = *ret](vk::CommandBuffer cmdbuf) {
cmdbuf.FillBuffer(buffer, 0, VK_WHOLE_SIZE, 0); cmdbuf.FillBuffer(buffer, 0, VK_WHOLE_SIZE, 0);
}); });

173
src/video_core/renderer_vulkan/vk_scheduler.cpp

@ -107,7 +107,12 @@ void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass
state.framebuffer = VkFramebuffer{}; state.framebuffer = VkFramebuffer{};
state.attachment_views = attachment_views; state.attachment_views = attachment_views;
state.render_area = render_area; state.render_area = render_area;
state.num_color = framebuffer->NumColorAttachments();
state.has_depth = framebuffer->HasAspectDepthBit();
state.has_stencil = framebuffer->HasAspectStencilBit();
state.layer_count = framebuffer->NumLayers();
state.rendering = true; state.rendering = true;
state.suspended = false;
if (GPU::Logging::IsActive() && Settings::values.gpu_log_vulkan_calls.GetValue()) { if (GPU::Logging::IsActive() && Settings::values.gpu_log_vulkan_calls.GetValue()) {
const std::string render_pass_info = const std::string render_pass_info =
@ -116,58 +121,7 @@ void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass
GPU::Logging::GPULogger::GetInstance().LogRenderPassBegin(render_pass_info); GPU::Logging::GPULogger::GetInstance().LogRenderPassBegin(render_pass_info);
} }
const u32 num_color = framebuffer->NumColorAttachments();
const bool has_depth = framebuffer->HasAspectDepthBit();
const bool has_stencil = framebuffer->HasAspectStencilBit();
const VkImageView depth_view = framebuffer->DepthAttachment();
const u32 layers = framebuffer->NumLayers();
std::array<VkRenderingAttachmentInfo, VideoCommon::NUM_RT> color_infos{};
for (u32 index = 0; index < num_color; ++index) {
color_infos[index] = VkRenderingAttachmentInfo{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = color_views[index],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = VK_RESOLVE_MODE_NONE,
.resolveImageView = VK_NULL_HANDLE,
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = {.color = {.float32 = {1.0f, 0.0f, 1.0f, 1.0f}}},
};
}
const VkRenderingAttachmentInfo depth_info{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = depth_view,
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = VK_RESOLVE_MODE_NONE,
.resolveImageView = VK_NULL_HANDLE,
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = {},
};
Record([color_infos, depth_info, num_color, has_depth, has_stencil, layers,
render_area](vk::CommandBuffer cmdbuf) {
const VkRenderingInfo rendering_info{
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.pNext = nullptr,
.flags = 0,
.renderArea =
{
.offset = {.x = 0, .y = 0},
.extent = render_area,
},
.layerCount = layers,
.viewMask = 0,
.colorAttachmentCount = num_color,
.pColorAttachments = color_infos.data(),
.pDepthAttachment = has_depth ? &depth_info : nullptr,
.pStencilAttachment = has_stencil ? &depth_info : nullptr,
};
cmdbuf.BeginRendering(rendering_info);
});
RecordDynamicBegin(false, true);
num_renderpass_images = framebuffer->NumImages(); num_renderpass_images = framebuffer->NumImages();
renderpass_images = framebuffer->Images(); renderpass_images = framebuffer->Images();
renderpass_image_ranges = framebuffer->ImageRanges(); renderpass_image_ranges = framebuffer->ImageRanges();
@ -281,9 +235,16 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
attachment_views[index] = color_views[index]; attachment_views[index] = color_views[index];
} }
attachment_views[8] = framebuffer->DepthAttachment(); attachment_views[8] = framebuffer->DepthAttachment();
if (state.rendering && attachment_views == state.attachment_views &&
render_area.width == state.render_area.width &&
render_area.height == state.render_area.height) {
const bool same_target = state.rendering &&
attachment_views == state.attachment_views &&
render_area.width == state.render_area.width &&
render_area.height == state.render_area.height;
if (same_target && !state.suspended) {
return;
}
if (same_target && state.suspended) {
RecordDynamicBegin(true, true);
state.suspended = false;
return; return;
} }
EndRenderPass(); EndRenderPass();
@ -302,7 +263,16 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
BeginRenderPassImpl(framebuffer, renderpass, nullptr, 0); BeginRenderPassImpl(framebuffer, renderpass, nullptr, 0);
} }
void Scheduler::RequestOutsideRenderPassOperationContext() {
void Scheduler::RequestOutsideRenderPassOperationContext(bool allow_suspend) {
if (allow_suspend && device.IsKhrDynamicRenderingSupported() && state.rendering &&
!state.suspended) {
query_cache->CounterClose(VideoCommon::QueryType::StreamingByteCount);
query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false);
query_cache->NotifySegment(false);
Record([](vk::CommandBuffer cmdbuf) { cmdbuf.EndRendering(); });
state.suspended = true;
return;
}
EndRenderPass(); EndRenderPass();
} }
@ -466,6 +436,69 @@ void Scheduler::InvalidateState() {
state_tracker.InvalidateCommandBufferState(); state_tracker.InvalidateCommandBufferState();
} }
void Scheduler::RecordDynamicBegin(bool resuming, bool suspending) {
const std::array<VkImageView, 9> views = state.attachment_views;
const u32 num_color = state.num_color;
const bool has_depth = state.has_depth;
const bool has_stencil = state.has_stencil;
const u32 layers = state.layer_count;
const VkExtent2D render_area = state.render_area;
VkRenderingFlags flags = 0;
if (resuming) {
flags |= VK_RENDERING_RESUMING_BIT;
}
if (suspending) {
flags |= VK_RENDERING_SUSPENDING_BIT;
}
Record([views, num_color, has_depth, has_stencil, layers, render_area,
flags](vk::CommandBuffer cmdbuf) {
std::array<VkRenderingAttachmentInfo, VideoCommon::NUM_RT> color_infos{};
for (u32 index = 0; index < num_color; ++index) {
color_infos[index] = VkRenderingAttachmentInfo{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = views[index],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = VK_RESOLVE_MODE_NONE,
.resolveImageView = VK_NULL_HANDLE,
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = {},
};
}
const VkRenderingAttachmentInfo depth_info{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = views[8],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = VK_RESOLVE_MODE_NONE,
.resolveImageView = VK_NULL_HANDLE,
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = {},
};
const VkRenderingInfo rendering_info{
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.pNext = nullptr,
.flags = flags,
.renderArea =
{
.offset = {.x = 0, .y = 0},
.extent = render_area,
},
.layerCount = layers,
.viewMask = 0,
.colorAttachmentCount = num_color,
.pColorAttachments = color_infos.data(),
.pDepthAttachment = has_depth ? &depth_info : nullptr,
.pStencilAttachment = has_stencil ? &depth_info : nullptr,
};
cmdbuf.BeginRendering(rendering_info);
});
}
void Scheduler::EndPendingOperations() { void Scheduler::EndPendingOperations() {
query_cache->CounterReset(VideoCommon::QueryType::ZPassPixelCount64); query_cache->CounterReset(VideoCommon::QueryType::ZPassPixelCount64);
EndRenderPass(); EndRenderPass();
@ -478,16 +511,29 @@ void Scheduler::EndRenderPass()
return; return;
} }
query_cache->CounterClose(VideoCommon::QueryType::StreamingByteCount);
const bool dynamic = device.IsKhrDynamicRenderingSupported();
if (!state.suspended) {
query_cache->CounterClose(VideoCommon::QueryType::StreamingByteCount);
// Log render pass end
if (GPU::Logging::IsActive() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogRenderPassEnd();
// Log render pass end
if (GPU::Logging::IsActive() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogRenderPassEnd();
}
query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false);
query_cache->NotifySegment(false);
if (dynamic) {
Record([](vk::CommandBuffer cmdbuf) { cmdbuf.EndRendering(); });
state.suspended = true;
}
} }
query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false);
query_cache->NotifySegment(false);
if (dynamic && state.suspended) {
RecordDynamicBegin(true, false);
}
Record([num_images = num_renderpass_images, Record([num_images = num_renderpass_images,
images = renderpass_images, images = renderpass_images,
@ -555,6 +601,7 @@ void Scheduler::EndRenderPass()
state.framebuffer = VkFramebuffer{}; state.framebuffer = VkFramebuffer{};
state.attachment_views = {}; state.attachment_views = {};
state.rendering = false; state.rendering = false;
state.suspended = false;
num_renderpass_images = 0; num_renderpass_images = 0;
} }

9
src/video_core/renderer_vulkan/vk_scheduler.h

@ -67,7 +67,7 @@ public:
/// Requests the current execution context to be able to execute operations only allowed outside /// Requests the current execution context to be able to execute operations only allowed outside
/// of a renderpass. /// of a renderpass.
void RequestOutsideRenderPassOperationContext();
void RequestOutsideRenderPassOperationContext(bool allow_suspend = false);
/// Returns true when a render pass is currently active in the scheduler state. /// Returns true when a render pass is currently active in the scheduler state.
bool IsRenderPassActive() const { bool IsRenderPassActive() const {
@ -254,6 +254,11 @@ private:
VkExtent2D render_area = {0, 0}; VkExtent2D render_area = {0, 0};
GraphicsPipeline* graphics_pipeline = nullptr; GraphicsPipeline* graphics_pipeline = nullptr;
bool rendering = false; bool rendering = false;
bool suspended = false;
u32 num_color = 0;
bool has_depth = false;
bool has_stencil = false;
u32 layer_count = 1;
bool is_rescaling = false; bool is_rescaling = false;
bool rescaling_defined = false; bool rescaling_defined = false;
bool needs_state_enable_refresh = false; bool needs_state_enable_refresh = false;
@ -284,6 +289,8 @@ private:
void EndPendingOperations(); void EndPendingOperations();
void RecordDynamicBegin(bool resuming, bool suspending);
void EndRenderPass(); void EndRenderPass();
void AcquireNewChunk(); void AcquireNewChunk();

Loading…
Cancel
Save